~ubuntu-branches/ubuntu/maverick/cairo-dock/maverick

« back to all changes in this revision

Viewing changes to src/cairo-dock-surface-factory.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Baerts (matttbe)
  • Date: 2010-08-09 23:26:12 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100809232612-yp4c6ig3jt1bzpdv
Tags: 2.2.0~0beta4-0ubuntu1
* New Upstream Version (LP: #614624)
* Fixed a few bugs on LP:
 - LP: #518453: Dock appears under all windows
                 (Compiz - fullscreen window)
 - LP: #521369: Separator are not removed when closing
                 grouped windows
 - LP: #521762: Some sentences are not correct
 - LP: #526466: Icons of apps with same class shouldn't
                 be stacked by default
 - LP: #535083: Dialogues looks ugly when a lot of them
                 appears at the same time
 - More details on the 'ChangeLog' file
* debian/rules:
 - Autotools has been replaced by CMake
 - Man pages are now included in the source code
* debian/copyright:
 - Updated with the new pathes and new files
* debian/control:
 - Autotools has been replaced by CMake
 - Added libcurl4-gnutls-dev as Build-deps
 - Bump Standard-Version to 3.9.1
* debian/cairo-dock-core.install:
 - Man pages are now included in the source code
 - All sonames are now installed into lib32 or lib64
* debian/cairo-dock-dev.install:
 - pkgconfig is now installed into lib32 or lib64

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 <math.h>
22
 
#include <librsvg/rsvg.h>
23
 
#include <librsvg/rsvg-cairo.h>
24
 
#include <pango/pango.h>
25
 
 
26
 
#include "cairo-dock-log.h"
27
 
#include "cairo-dock-draw.h"
28
 
#include "cairo-dock-launcher-factory.h"
29
 
#include "cairo-dock-load.h"
30
 
#include "cairo-dock-surface-factory.h"
31
 
 
32
 
extern gboolean g_bUseOpenGL;
33
 
 
34
 
 
35
 
void cairo_dock_calculate_size_fill (double *fImageWidth, double *fImageHeight, int iWidthConstraint, int iHeightConstraint, gboolean bNoZoomUp, double *fZoomWidth, double *fZoomHeight)
36
 
{
37
 
        if (iWidthConstraint != 0)
38
 
        {
39
 
                *fZoomWidth = 1. * iWidthConstraint / (*fImageWidth);
40
 
                if (bNoZoomUp && *fZoomWidth > 1)
41
 
                        *fZoomWidth = 1;
42
 
                else
43
 
                        *fImageWidth = (double) iWidthConstraint;
44
 
        }
45
 
        else
46
 
                *fZoomWidth = 1.;
47
 
        if (iHeightConstraint != 0)
48
 
        {
49
 
                *fZoomHeight = 1. * iHeightConstraint / (*fImageHeight);
50
 
                if (bNoZoomUp && *fZoomHeight > 1)
51
 
                        *fZoomHeight = 1;
52
 
                else
53
 
                        *fImageHeight = (double) iHeightConstraint;
54
 
        }
55
 
        else
56
 
                *fZoomHeight = 1.;
57
 
}
58
 
 
59
 
void cairo_dock_calculate_size_constant_ratio (double *fImageWidth, double *fImageHeight, int iWidthConstraint, int iHeightConstraint, gboolean bNoZoomUp, double *fZoom)
60
 
{
61
 
        if (iWidthConstraint != 0 && iHeightConstraint != 0)
62
 
                *fZoom = MIN (iWidthConstraint / (*fImageWidth), iHeightConstraint / (*fImageHeight));
63
 
        else if (iWidthConstraint != 0)
64
 
                *fZoom = iWidthConstraint / (*fImageWidth);
65
 
        else if (iHeightConstraint != 0)
66
 
                *fZoom = iHeightConstraint / (*fImageHeight);
67
 
        else
68
 
                *fZoom = 1.;
69
 
        if (bNoZoomUp && *fZoom > 1)
70
 
                *fZoom = 1.;
71
 
        *fImageWidth = (*fImageWidth) * (*fZoom);
72
 
        *fImageHeight = (*fImageHeight) * (*fZoom);
73
 
}
74
 
 
75
 
 
76
 
 
77
 
void cairo_dock_calculate_constrainted_size (double *fImageWidth, double *fImageHeight, int iWidthConstraint, int iHeightConstraint, CairoDockLoadImageModifier iLoadingModifier, double *fZoomWidth, double *fZoomHeight)
78
 
{
79
 
        gboolean bFillSpace = iLoadingModifier & CAIRO_DOCK_FILL_SPACE;
80
 
        gboolean bKeepRatio = iLoadingModifier & CAIRO_DOCK_KEEP_RATIO;
81
 
        gboolean bNoZoomUp = iLoadingModifier & CAIRO_DOCK_DONT_ZOOM_IN;
82
 
        gint iOrientation = iLoadingModifier & CAIRO_DOCK_ORIENTATION_MASK;
83
 
        if (iOrientation > CAIRO_DOCK_ORIENTATION_VFLIP)  // inversion x/y
84
 
        {
85
 
                double tmp = *fImageWidth;
86
 
                *fImageWidth = *fImageHeight;
87
 
                *fImageHeight = tmp;
88
 
        }
89
 
        if (bKeepRatio)
90
 
        {
91
 
                cairo_dock_calculate_size_constant_ratio (fImageWidth,
92
 
                        fImageHeight,
93
 
                        iWidthConstraint,
94
 
                        iHeightConstraint,
95
 
                        bNoZoomUp,
96
 
                        fZoomWidth);
97
 
                *fZoomHeight = *fZoomWidth;
98
 
                if (bFillSpace)
99
 
                {
100
 
                        //double fUsefulWidth = *fImageWidth;
101
 
                        //double fUsefulHeight = *fImageHeight;
102
 
                        if (iWidthConstraint != 0)
103
 
                                *fImageWidth = iWidthConstraint;
104
 
                        if (iHeightConstraint != 0)
105
 
                                *fImageHeight = iHeightConstraint;
106
 
                }
107
 
        }
108
 
        else
109
 
        {
110
 
                cairo_dock_calculate_size_fill (fImageWidth,
111
 
                        fImageHeight,
112
 
                        iWidthConstraint,
113
 
                        iHeightConstraint,
114
 
                        bNoZoomUp,
115
 
                        fZoomWidth,
116
 
                        fZoomHeight);
117
 
        }
118
 
}
119
 
 
120
 
cairo_surface_t *_cairo_dock_create_blank_surface (cairo_t *pSourceContext, int iWidth, int iHeight)
121
 
{
122
 
        if (pSourceContext != NULL && ! g_bUseOpenGL)
123
 
                return cairo_surface_create_similar (cairo_get_target (pSourceContext),
124
 
                        CAIRO_CONTENT_COLOR_ALPHA,
125
 
                        iWidth,
126
 
                        iHeight);
127
 
        else
128
 
                return cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
129
 
                        iWidth,
130
 
                        iHeight);
131
 
}
132
 
 
133
 
static inline void _apply_orientation_and_scale (cairo_t *pCairoContext, CairoDockLoadImageModifier iLoadingModifier, double fImageWidth, double fImageHeight, double fZoomX, double fZoomY, double fUsefulWidth, double fUsefulheight)
134
 
{
135
 
        int iOrientation = iLoadingModifier & CAIRO_DOCK_ORIENTATION_MASK;
136
 
        
137
 
        cairo_translate (pCairoContext,
138
 
                fImageWidth/2,
139
 
                fImageHeight/2);
140
 
        cairo_scale (pCairoContext,
141
 
                fZoomX,
142
 
                fZoomY);
143
 
        switch (iOrientation)
144
 
        {
145
 
                case CAIRO_DOCK_ORIENTATION_HFLIP :
146
 
                        g_print ("orientation : HFLIP\n");
147
 
                        cairo_scale (pCairoContext, -1., 1.);
148
 
                break ;
149
 
                case CAIRO_DOCK_ORIENTATION_ROT_180 :
150
 
                        g_print ("orientation : ROT_180\n");
151
 
                        cairo_rotate (pCairoContext, G_PI);
152
 
                break ;
153
 
                case CAIRO_DOCK_ORIENTATION_VFLIP :
154
 
                        g_print ("orientation : VFLIP\n");
155
 
                        cairo_scale (pCairoContext, 1., -1.);
156
 
                break ;
157
 
                case CAIRO_DOCK_ORIENTATION_ROT_90_HFLIP :
158
 
                        g_print ("orientation : ROT_90_HFLIP\n");
159
 
                        cairo_scale (pCairoContext, -1., 1.);
160
 
                        cairo_rotate (pCairoContext, + G_PI/2);
161
 
                break ;
162
 
                case CAIRO_DOCK_ORIENTATION_ROT_90 :
163
 
                        g_print ("orientation : ROT_90\n");
164
 
                        cairo_rotate (pCairoContext, + G_PI/2);
165
 
                break ;
166
 
                case CAIRO_DOCK_ORIENTATION_ROT_90_VFLIP :
167
 
                        g_print ("orientation : ROT_90_VFLIP\n");
168
 
                        cairo_scale (pCairoContext, 1., -1.);
169
 
                        cairo_rotate (pCairoContext, + G_PI/2);
170
 
                break ;
171
 
                case CAIRO_DOCK_ORIENTATION_ROT_270 :
172
 
                        g_print ("orientation : ROT_270\n");
173
 
                        cairo_rotate (pCairoContext, - G_PI/2);
174
 
                break ;
175
 
                default :
176
 
                break ;
177
 
        }
178
 
        if (iOrientation < CAIRO_DOCK_ORIENTATION_ROT_90_HFLIP)
179
 
                cairo_translate (pCairoContext,
180
 
                        - fUsefulWidth/2/fZoomX,
181
 
                        - fUsefulheight/2/fZoomY);
182
 
        else
183
 
                cairo_translate (pCairoContext,
184
 
                        - fUsefulheight/2/fZoomY,
185
 
                        - fUsefulWidth/2/fZoomX);
186
 
}
187
 
 
188
 
 
189
 
cairo_surface_t *cairo_dock_create_surface_from_xicon_buffer (gulong *pXIconBuffer, int iBufferNbElements, cairo_t *pSourceContext, double fConstraintWidth, double fConstraintHeight, double fMaxScale, double *fWidth, double *fHeight)
190
 
{
191
 
        g_return_val_if_fail (cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
192
 
 
193
 
        //\____________________ On recupere la plus grosse des icones presentes dans le tampon (meilleur rendu).
194
 
        int iIndex = 0, iBestIndex = 0;
195
 
        while (iIndex + 2 < iBufferNbElements)
196
 
        {
197
 
                if (pXIconBuffer[iIndex] > pXIconBuffer[iBestIndex])
198
 
                        iBestIndex = iIndex;
199
 
                iIndex += 2 + pXIconBuffer[iIndex] * pXIconBuffer[iIndex+1];
200
 
        }
201
 
 
202
 
        //\____________________ On pre-multiplie chaque composante par le alpha (necessaire pour libcairo).
203
 
        int w = pXIconBuffer[iBestIndex];
204
 
        int h = pXIconBuffer[iBestIndex+1];
205
 
        iBestIndex += 2;
206
 
        //g_print ("%s (%dx%d)\n", __func__, w, h);
207
 
        
208
 
        int i, n = w * h;
209
 
        if (iBestIndex + n > iBufferNbElements)  // precaution au cas ou le nombre d'elements dans le buffer serait incorrect.
210
 
        {
211
 
                cd_warning ("This icon is broken !\nThis means that one of the current applications has sent a buggy icon to X.");
212
 
                return NULL;
213
 
        }
214
 
        gint pixel, alpha, red, green, blue;
215
 
        float fAlphaFactor;
216
 
        gint *pPixelBuffer = (gint *) &pXIconBuffer[iBestIndex];  // on va ecrire le resultat du filtre directement dans le tableau fourni en entree. C'est ok car sizeof(gulong) >= sizeof(gint), donc le tableau de pixels est plus petit que le buffer fourni en entree. merci a Hannemann pour ses tests et ses screenshots ! :-)
217
 
        for (i = 0; i < n; i ++)
218
 
        {
219
 
                pixel = (gint) pXIconBuffer[iBestIndex+i];
220
 
                alpha = (pixel & 0xFF000000) >> 24;
221
 
                red   = (pixel & 0x00FF0000) >> 16;
222
 
                green = (pixel & 0x0000FF00) >> 8;
223
 
                blue  = (pixel & 0x000000FF);
224
 
                fAlphaFactor = (float) alpha / 255;
225
 
                red *= fAlphaFactor;
226
 
                green *= fAlphaFactor;
227
 
                blue *= fAlphaFactor;
228
 
                pPixelBuffer[i] = (pixel & 0xFF000000) + (red << 16) + (green << 8) + blue;
229
 
        }
230
 
 
231
 
        //\____________________ On cree la surface a partir du tampon.
232
 
        int iStride = w * sizeof (gint);  // nbre d'octets entre le debut de 2 lignes.
233
 
        cairo_surface_t *surface_ini = cairo_image_surface_create_for_data ((guchar *)pPixelBuffer,
234
 
                CAIRO_FORMAT_ARGB32,
235
 
                w,
236
 
                h,
237
 
                iStride);
238
 
        
239
 
        *fWidth = (double) w;
240
 
        *fHeight = (double) h;
241
 
        double fIconWidthSaturationFactor = 1., fIconHeightSaturationFactor = 1.;
242
 
        cairo_dock_calculate_constrainted_size (fWidth,
243
 
                fHeight,
244
 
                fConstraintWidth,
245
 
                fConstraintHeight,
246
 
                CAIRO_DOCK_KEEP_RATIO | CAIRO_DOCK_FILL_SPACE,
247
 
                &fIconWidthSaturationFactor,
248
 
                &fIconHeightSaturationFactor);
249
 
        
250
 
        cairo_surface_t *pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
251
 
                ceil (*fWidth * fMaxScale),
252
 
                ceil (*fHeight * fMaxScale));
253
 
        cairo_t *pCairoContext = cairo_create (pNewSurface);
254
 
        
255
 
        double fUsefulWidth = w * fIconWidthSaturationFactor;  // a part dans le cas fill && keep ratio, c'est la meme chose que fImageWidth et fImageHeight.
256
 
        double fUsefulHeight = h * fIconHeightSaturationFactor;
257
 
        _apply_orientation_and_scale (pCairoContext,
258
 
                CAIRO_DOCK_KEEP_RATIO | CAIRO_DOCK_FILL_SPACE,
259
 
                ceil ((*fWidth) * fMaxScale), ceil ((*fHeight) * fMaxScale),
260
 
                fMaxScale * fIconWidthSaturationFactor, fMaxScale * fIconHeightSaturationFactor,
261
 
                fUsefulWidth * fMaxScale, fUsefulHeight * fMaxScale);
262
 
        cairo_set_source_surface (pCairoContext, surface_ini, 0, 0);
263
 
        cairo_paint (pCairoContext);
264
 
 
265
 
        cairo_surface_destroy (surface_ini);
266
 
        cairo_destroy (pCairoContext);
267
 
 
268
 
        return pNewSurface;
269
 
}
270
 
 
271
 
 
272
 
cairo_surface_t *cairo_dock_create_surface_from_pixbuf (GdkPixbuf *pixbuf, cairo_t *pSourceContext, double fMaxScale, int iWidthConstraint, int iHeightConstraint, CairoDockLoadImageModifier iLoadingModifier, double *fImageWidth, double *fImageHeight, double *fZoomX, double *fZoomY)
273
 
{
274
 
        *fImageWidth = gdk_pixbuf_get_width (pixbuf);
275
 
        *fImageHeight = gdk_pixbuf_get_height (pixbuf);
276
 
        double fIconWidthSaturationFactor = 1., fIconHeightSaturationFactor = 1.;
277
 
        cairo_dock_calculate_constrainted_size (fImageWidth,
278
 
                        fImageHeight,
279
 
                        iWidthConstraint,
280
 
                        iHeightConstraint,
281
 
                        iLoadingModifier,
282
 
                        &fIconWidthSaturationFactor,
283
 
                        &fIconHeightSaturationFactor);
284
 
 
285
 
        GdkPixbuf *pPixbufWithAlpha = pixbuf;
286
 
        if (! gdk_pixbuf_get_has_alpha (pixbuf))  // on lui rajoute un canal alpha s'il n'en a pas.
287
 
        {
288
 
                //g_print ("  ajout d'un canal alpha\n");
289
 
                pPixbufWithAlpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 255, 255, 255);  // TRUE <=> les pixels blancs deviennent transparents.
290
 
        }
291
 
 
292
 
        //\____________________ On pre-multiplie chaque composante par le alpha (necessaire pour libcairo).
293
 
        int iNbChannels = gdk_pixbuf_get_n_channels (pPixbufWithAlpha);
294
 
        int iRowstride = gdk_pixbuf_get_rowstride (pPixbufWithAlpha);
295
 
        int w = gdk_pixbuf_get_width (pPixbufWithAlpha);
296
 
        guchar *p, *pixels = gdk_pixbuf_get_pixels (pPixbufWithAlpha);
297
 
        int h = gdk_pixbuf_get_height (pPixbufWithAlpha);
298
 
        int x, y;
299
 
        int red, green, blue;
300
 
        float fAlphaFactor;
301
 
        for (y = 0; y < h; y ++)
302
 
        {
303
 
                for (x = 0; x < w; x ++)
304
 
                {
305
 
                        p = pixels + y * iRowstride + x * iNbChannels;
306
 
                        fAlphaFactor = (float) p[3] / 255;
307
 
                        red = p[0] * fAlphaFactor;
308
 
                        green = p[1] * fAlphaFactor;
309
 
                        blue = p[2] * fAlphaFactor;
310
 
                        p[0] = blue;
311
 
                        p[1] = green;
312
 
                        p[2] = red;
313
 
                }
314
 
        }
315
 
        
316
 
        cairo_surface_t *surface_ini = cairo_image_surface_create_for_data (pixels,
317
 
                CAIRO_FORMAT_ARGB32,
318
 
                w,
319
 
                h,
320
 
                iRowstride);
321
 
 
322
 
        cairo_surface_t *pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
323
 
                ceil ((*fImageWidth) * fMaxScale),
324
 
                ceil ((*fImageHeight) * fMaxScale));
325
 
        cairo_t *pCairoContext = cairo_create (pNewSurface);
326
 
        
327
 
        double fUsefulWidth = w * fIconWidthSaturationFactor;  // a part dans le cas fill && keep ratio, c'est la meme chose que fImageWidth et fImageHeight.
328
 
        double fUsefulHeight = h * fIconHeightSaturationFactor;
329
 
        _apply_orientation_and_scale (pCairoContext,
330
 
                iLoadingModifier,
331
 
                ceil ((*fImageWidth) * fMaxScale), ceil ((*fImageHeight) * fMaxScale),
332
 
                fMaxScale * fIconWidthSaturationFactor, fMaxScale * fIconHeightSaturationFactor,
333
 
                fUsefulWidth * fMaxScale, fUsefulHeight * fMaxScale);
334
 
        
335
 
        cairo_set_source_surface (pCairoContext, surface_ini, 0, 0);
336
 
        cairo_paint (pCairoContext);
337
 
        
338
 
        cairo_destroy (pCairoContext);
339
 
        cairo_surface_destroy (surface_ini);
340
 
        if (pPixbufWithAlpha != pixbuf)
341
 
                g_object_unref (pPixbufWithAlpha);
342
 
        
343
 
        if (fZoomX != NULL)
344
 
                *fZoomX = fIconWidthSaturationFactor;
345
 
        if (fZoomY != NULL)
346
 
                *fZoomY = fIconHeightSaturationFactor;
347
 
        
348
 
        return pNewSurface;
349
 
}
350
 
 
351
 
 
352
 
cairo_surface_t *cairo_dock_create_surface_from_image (const gchar *cImagePath, cairo_t* pSourceContext, double fMaxScale, int iWidthConstraint, int iHeightConstraint, CairoDockLoadImageModifier iLoadingModifier, double *fImageWidth, double *fImageHeight, double *fZoomX, double *fZoomY)
353
 
{
354
 
        //g_print ("%s (%s, %dx%dx%.2f, %d)\n", __func__, cImagePath, iWidthConstraint, iHeightConstraint, fMaxScale, iLoadingModifier);
355
 
        g_return_val_if_fail (cImagePath != NULL && pSourceContext != NULL && cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
356
 
        GError *erreur = NULL;
357
 
        RsvgDimensionData rsvg_dimension_data;
358
 
        RsvgHandle *rsvg_handle = NULL;
359
 
        cairo_surface_t* surface_ini;
360
 
        cairo_surface_t* pNewSurface = NULL;
361
 
        cairo_t* pCairoContext = NULL;
362
 
        double fIconWidthSaturationFactor = 1.;
363
 
        double fIconHeightSaturationFactor = 1.;
364
 
        
365
 
        //\_______________ On cherche a determiner le type de l'image. En effet, les SVG et les PNG sont charges differemment des autres.
366
 
        gboolean bIsSVG = FALSE, bIsPNG = FALSE, bIsXPM = FALSE;
367
 
        FILE *fd = fopen (cImagePath, "r");
368
 
        if (fd != NULL)
369
 
        {
370
 
                char buffer[8];
371
 
                if (fgets (buffer, 7, fd) != NULL)
372
 
                {
373
 
                        if (strncmp (buffer+2, "xml", 3) == 0)
374
 
                                bIsSVG = TRUE;
375
 
                        else if (strncmp (buffer+1, "PNG", 3) == 0)
376
 
                                bIsPNG = TRUE;
377
 
                        else if (strncmp (buffer+3, "XPM", 3) == 0)
378
 
                                bIsXPM = TRUE;
379
 
                        //cd_debug ("  format : %d;%d;%d", bIsSVG, bIsPNG, bIsXPM);
380
 
                }
381
 
                fclose (fd);
382
 
        }
383
 
        if (! bIsSVG && ! bIsPNG && ! bIsXPM)  // sinon en desespoir de cause on se base sur l'extension.
384
 
        {
385
 
                //cd_debug ("  on se base sur l'extension en desespoir de cause.");
386
 
                if (g_str_has_suffix (cImagePath, ".svg"))
387
 
                        bIsSVG = TRUE;
388
 
                else if (g_str_has_suffix (cImagePath, ".png"))
389
 
                        bIsPNG = TRUE;
390
 
        }
391
 
        
392
 
        bIsPNG = FALSE;  /// libcairo 1.6 - 1.8 est bugguee !!!...
393
 
        if (bIsSVG)
394
 
        {
395
 
                rsvg_handle = rsvg_handle_new_from_file (cImagePath, &erreur);
396
 
                if (erreur != NULL)
397
 
                {
398
 
                        cd_warning (erreur->message);
399
 
                        g_error_free (erreur);
400
 
                        return NULL;
401
 
                }
402
 
                else
403
 
                {
404
 
                        g_return_val_if_fail (rsvg_handle != NULL, NULL);
405
 
                        rsvg_handle_get_dimensions (rsvg_handle, &rsvg_dimension_data);
406
 
                        int w = rsvg_dimension_data.width;
407
 
                        int h = rsvg_dimension_data.height;
408
 
                        *fImageWidth = (gdouble) w;
409
 
                        *fImageHeight = (gdouble) h;
410
 
                        //g_print ("%.2fx%.2f\n", *fImageWidth, *fImageHeight);
411
 
                        cairo_dock_calculate_constrainted_size (fImageWidth,
412
 
                                fImageHeight,
413
 
                                iWidthConstraint,
414
 
                                iHeightConstraint,
415
 
                                iLoadingModifier,
416
 
                                &fIconWidthSaturationFactor,
417
 
                                &fIconHeightSaturationFactor);
418
 
                        
419
 
                        pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
420
 
                                ceil ((*fImageWidth) * fMaxScale),
421
 
                                ceil ((*fImageHeight) * fMaxScale));
422
 
 
423
 
                        pCairoContext = cairo_create (pNewSurface);
424
 
                        double fUsefulWidth = w * fIconWidthSaturationFactor;  // a part dans le cas fill && keep ratio, c'est la meme chose que fImageWidth et fImageHeight.
425
 
                        double fUsefulHeight = h * fIconHeightSaturationFactor;
426
 
                        _apply_orientation_and_scale (pCairoContext,
427
 
                                iLoadingModifier,
428
 
                                ceil ((*fImageWidth) * fMaxScale), ceil ((*fImageHeight) * fMaxScale),
429
 
                                fMaxScale * fIconWidthSaturationFactor, fMaxScale * fIconHeightSaturationFactor,
430
 
                                fUsefulWidth * fMaxScale, fUsefulHeight * fMaxScale);
431
 
 
432
 
                        rsvg_handle_render_cairo (rsvg_handle, pCairoContext);
433
 
                        cairo_destroy (pCairoContext);
434
 
                        g_object_unref (rsvg_handle);
435
 
                }
436
 
        }
437
 
        else if (bIsPNG)
438
 
        {
439
 
                surface_ini = cairo_image_surface_create_from_png (cImagePath);  // cree un fond noir :-(
440
 
                if (cairo_surface_status (surface_ini) == CAIRO_STATUS_SUCCESS)
441
 
                {
442
 
                        int w = cairo_image_surface_get_width (surface_ini);
443
 
                        int h = cairo_image_surface_get_height (surface_ini);
444
 
                        *fImageWidth = (double) w;
445
 
                        *fImageHeight = (double) h;
446
 
                        cairo_dock_calculate_constrainted_size (fImageWidth,
447
 
                                fImageHeight,
448
 
                                iWidthConstraint,
449
 
                                iHeightConstraint,
450
 
                                iLoadingModifier,
451
 
                                &fIconWidthSaturationFactor,
452
 
                                &fIconHeightSaturationFactor);
453
 
                        
454
 
                        pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
455
 
                                ceil ((*fImageWidth) * fMaxScale),
456
 
                                ceil ((*fImageHeight) * fMaxScale));
457
 
                        pCairoContext = cairo_create (pNewSurface);
458
 
                        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_SOURCE);
459
 
                        cairo_set_source_rgba (pCairoContext, 0., 0., 0., 0.);
460
 
                        cairo_paint (pCairoContext);
461
 
                        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
462
 
                        
463
 
                        double fUsefulWidth = w * fIconWidthSaturationFactor;  // a part dans le cas fill && keep ratio, c'est la meme chose que fImageWidth et fImageHeight.
464
 
                        double fUsefulHeight = h * fIconHeightSaturationFactor;
465
 
                        _apply_orientation_and_scale (pCairoContext,
466
 
                                iLoadingModifier,
467
 
                                ceil ((*fImageWidth) * fMaxScale), ceil ((*fImageHeight) * fMaxScale),
468
 
                                fMaxScale * fIconWidthSaturationFactor, fMaxScale * fIconHeightSaturationFactor,
469
 
                                fUsefulWidth * fMaxScale, fUsefulHeight * fMaxScale);
470
 
                        
471
 
                        cairo_set_source_surface (pCairoContext, surface_ini, 0, 0);
472
 
                        cairo_paint (pCairoContext);
473
 
                        cairo_destroy (pCairoContext);
474
 
                }
475
 
                cairo_surface_destroy (surface_ini);
476
 
        }
477
 
        else  // le code suivant permet de charger tout type d'image, mais en fait c'est un peu idiot d'utiliser des icones n'ayant pas de transparence.
478
 
        {
479
 
                GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (cImagePath, &erreur);  // semble se baser sur l'extension pour definir le type !
480
 
                if (erreur != NULL)
481
 
                {
482
 
                        cd_warning (erreur->message);
483
 
                        g_error_free (erreur);
484
 
                        return NULL;
485
 
                }
486
 
                pNewSurface = cairo_dock_create_surface_from_pixbuf (pixbuf,
487
 
                        pSourceContext,
488
 
                        fMaxScale,
489
 
                        iWidthConstraint,
490
 
                        iHeightConstraint,
491
 
                        iLoadingModifier,
492
 
                        fImageWidth,
493
 
                        fImageHeight,
494
 
                        &fIconWidthSaturationFactor,
495
 
                        &fIconHeightSaturationFactor);
496
 
                g_object_unref (pixbuf);
497
 
                
498
 
        }
499
 
        
500
 
        if (fZoomX != NULL)
501
 
                *fZoomX = fIconWidthSaturationFactor;
502
 
        if (fZoomY != NULL)
503
 
                *fZoomY = fIconHeightSaturationFactor;
504
 
        
505
 
        return pNewSurface;
506
 
}
507
 
 
508
 
cairo_surface_t *cairo_dock_create_surface_from_image_simple (const gchar *cImageFile, cairo_t* pSourceContext, double fImageWidth, double fImageHeight)
509
 
{
510
 
        g_return_val_if_fail (cImageFile != NULL, NULL);
511
 
        double fImageWidth_ = fImageWidth, fImageHeight_ = fImageHeight;
512
 
        gchar *cImagePath;
513
 
        if (*cImageFile == '/')
514
 
                cImagePath = (gchar *)cImageFile;
515
 
        else
516
 
                cImagePath = cairo_dock_generate_file_path (cImageFile);
517
 
                
518
 
        cairo_surface_t *pSurface = cairo_dock_create_surface_from_image (cImagePath,
519
 
                pSourceContext,
520
 
                1.,
521
 
                fImageWidth,
522
 
                fImageHeight,
523
 
                CAIRO_DOCK_FILL_SPACE,
524
 
                &fImageWidth_,
525
 
                &fImageHeight_,
526
 
                NULL,
527
 
                NULL);
528
 
        if (cImagePath != cImageFile)
529
 
                g_free (cImagePath);
530
 
        return pSurface;
531
 
}
532
 
 
533
 
cairo_surface_t *cairo_dock_create_surface_from_icon (const gchar *cImageFile, cairo_t* pSourceContext, double fImageWidth, double fImageHeight)
534
 
{
535
 
        g_return_val_if_fail (cImageFile != NULL, NULL);
536
 
        double fImageWidth_ = fImageWidth, fImageHeight_ = fImageHeight;
537
 
        gchar *cIconPath;
538
 
        if (*cImageFile == '/')
539
 
                cIconPath = (gchar *)cImageFile;
540
 
        else
541
 
                cIconPath = cairo_dock_search_icon_s_path (cImageFile);
542
 
                
543
 
        cairo_surface_t *pSurface = cairo_dock_create_surface_from_image (cIconPath,
544
 
                pSourceContext,
545
 
                1.,
546
 
                fImageWidth,
547
 
                fImageHeight,
548
 
                CAIRO_DOCK_FILL_SPACE,
549
 
                &fImageWidth_,
550
 
                &fImageHeight_,
551
 
                NULL,
552
 
                NULL);
553
 
        if (cIconPath != cImageFile)
554
 
                g_free (cIconPath);
555
 
        return pSurface;
556
 
}
557
 
 
558
 
cairo_surface_t *cairo_dock_create_surface_from_pattern (const gchar *cImageFile, cairo_t *pSourceContext, double fImageWidth, double fImageHeight, double fAlpha)
559
 
{
560
 
        g_return_val_if_fail (cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
561
 
        cairo_surface_t *pNewSurface = NULL;
562
 
 
563
 
        if (cImageFile != NULL)
564
 
        {
565
 
                gchar *cImagePath = cairo_dock_generate_file_path (cImageFile);
566
 
                double fImageWidth, fImageHeight;
567
 
                cairo_surface_t *pPatternSurface = cairo_dock_create_surface_from_image (cImagePath,
568
 
                        pSourceContext,
569
 
                        1.,
570
 
                        0,  // pas de contrainte sur
571
 
                        0,  // la taille du motif initialement.
572
 
                        CAIRO_DOCK_FILL_SPACE,
573
 
                        &fImageWidth,
574
 
                        &fImageHeight,
575
 
                        NULL, NULL);
576
 
                g_free (cImagePath);
577
 
                if (pPatternSurface == NULL)
578
 
                        return NULL;
579
 
                
580
 
                pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
581
 
                        fImageWidth,
582
 
                        fImageHeight);
583
 
                cairo_t *pCairoContext = cairo_create (pNewSurface);
584
 
 
585
 
                cairo_pattern_t* pPattern = cairo_pattern_create_for_surface (pPatternSurface);
586
 
                g_return_val_if_fail (cairo_pattern_status (pPattern) == CAIRO_STATUS_SUCCESS, NULL);
587
 
                cairo_pattern_set_extend (pPattern, CAIRO_EXTEND_REPEAT);
588
 
 
589
 
                cairo_set_source (pCairoContext, pPattern);
590
 
                cairo_paint_with_alpha (pCairoContext, fAlpha);
591
 
                cairo_destroy (pCairoContext);
592
 
                cairo_pattern_destroy (pPattern);
593
 
                
594
 
                cairo_surface_destroy (pPatternSurface);
595
 
        }
596
 
        
597
 
        return pNewSurface;
598
 
}
599
 
 
600
 
 
601
 
 
602
 
cairo_surface_t * cairo_dock_rotate_surface (cairo_surface_t *pSurface, cairo_t *pSourceContext, double fImageWidth, double fImageHeight, double fRotationAngle)
603
 
{
604
 
        g_return_val_if_fail (pSourceContext != NULL && cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS && pSurface != NULL, NULL);
605
 
        if (fRotationAngle != 0)
606
 
        {
607
 
                cairo_surface_t *pNewSurfaceRotated;
608
 
                cairo_t *pCairoContext;
609
 
                if (fabs (fRotationAngle) > G_PI / 2)
610
 
                {
611
 
                        pNewSurfaceRotated = _cairo_dock_create_blank_surface (pSourceContext,
612
 
                                fImageWidth,
613
 
                                fImageHeight);
614
 
                        pCairoContext = cairo_create (pNewSurfaceRotated);
615
 
 
616
 
                        cairo_translate (pCairoContext, 0, fImageHeight);
617
 
                        cairo_scale (pCairoContext, 1, -1);
618
 
                }
619
 
                else
620
 
                {
621
 
                        pNewSurfaceRotated = _cairo_dock_create_blank_surface (pSourceContext,
622
 
                                fImageHeight,
623
 
                                fImageWidth);
624
 
                        pCairoContext = cairo_create (pNewSurfaceRotated);
625
 
 
626
 
                        if (fRotationAngle < 0)
627
 
                        {
628
 
                                cairo_move_to (pCairoContext, fImageHeight, 0);
629
 
                                cairo_rotate (pCairoContext, fRotationAngle);
630
 
                                cairo_translate (pCairoContext, - fImageWidth, 0);
631
 
                        }
632
 
                        else
633
 
                        {
634
 
                                cairo_move_to (pCairoContext, 0, 0);
635
 
                                cairo_rotate (pCairoContext, fRotationAngle);
636
 
                                cairo_translate (pCairoContext, 0, - fImageHeight);
637
 
                        }
638
 
                }
639
 
                cairo_set_source_surface (pCairoContext, pSurface, 0, 0);
640
 
                cairo_paint (pCairoContext);
641
 
 
642
 
                cairo_destroy (pCairoContext);
643
 
                return pNewSurfaceRotated;
644
 
        }
645
 
        else
646
 
        {
647
 
                return NULL;
648
 
        }
649
 
}
650
 
 
651
 
 
652
 
static cairo_surface_t * cairo_dock_create_reflection_surface_horizontal (cairo_surface_t *pSurface, cairo_t *pSourceContext, double fImageWidth, double fImageHeight, double fReflectSize, double fAlbedo, gboolean bDirectionUp)
653
 
{
654
 
        g_return_val_if_fail (pSourceContext != NULL && cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
655
 
        //g_print ("%s (%d)\n", __func__, bDirectionUp);
656
 
 
657
 
        //\_______________ On cree la surface d'une fraction hauteur de l'image originale.
658
 
        if (pSurface == NULL || fReflectSize == 0 || fAlbedo == 0)
659
 
                return NULL;
660
 
        cairo_surface_t *pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
661
 
                fImageWidth,
662
 
                fReflectSize);
663
 
        cairo_t *pCairoContext = cairo_create (pNewSurface);
664
 
        
665
 
        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
666
 
        cairo_set_source_rgba (pCairoContext, 0., 0., 0., 0.);
667
 
        
668
 
        //\_______________ On dessine l'image originale inversee.
669
 
        cairo_translate (pCairoContext, 0, fImageHeight);
670
 
        cairo_scale (pCairoContext, 1., -1.);
671
 
        cairo_set_source_surface (pCairoContext, pSurface, 0, (bDirectionUp ? 0 : fImageHeight - fReflectSize));
672
 
        
673
 
        //\_______________ On applique un degrade en transparence.
674
 
        /**cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (0.,
675
 
                2*fReflectHeight,
676
 
                0.,
677
 
                fReflectHeight);  // de haut en bas.*/
678
 
        cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (0.,
679
 
                fImageHeight,
680
 
                0.,
681
 
                fImageHeight - fReflectSize);  // de haut en bas.
682
 
        g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, NULL);
683
 
 
684
 
        cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
685
 
        cairo_pattern_add_color_stop_rgba (pGradationPattern,
686
 
                0.,
687
 
                0.,
688
 
                0.,
689
 
                0.,
690
 
                (bDirectionUp ? fAlbedo : 0.));
691
 
        cairo_pattern_add_color_stop_rgba (pGradationPattern,
692
 
                1.,
693
 
                0.,
694
 
                0.,
695
 
                0.,
696
 
                (bDirectionUp ? 0 : fAlbedo));
697
 
 
698
 
        cairo_mask (pCairoContext, pGradationPattern);
699
 
 
700
 
        cairo_pattern_destroy (pGradationPattern);
701
 
        cairo_destroy (pCairoContext);
702
 
        return pNewSurface;
703
 
}
704
 
 
705
 
static cairo_surface_t * cairo_dock_create_reflection_surface_vertical (cairo_surface_t *pSurface, cairo_t *pSourceContext, double fImageWidth, double fImageHeight, double fReflectSize, double fAlbedo, gboolean bDirectionUp)
706
 
{
707
 
        g_return_val_if_fail (pSurface != NULL && pSourceContext != NULL && cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
708
 
 
709
 
        //\_______________ On cree la surface d'une fraction hauteur de l'image originale.
710
 
        if (fReflectSize == 0 || fAlbedo == 0)
711
 
                return NULL;
712
 
        cairo_surface_t *pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
713
 
                fReflectSize,
714
 
                fImageHeight);
715
 
        cairo_t *pCairoContext = cairo_create (pNewSurface);
716
 
 
717
 
        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
718
 
        cairo_set_source_rgba (pCairoContext, 0., 0., 0., 0.);
719
 
        
720
 
        //\_______________ On dessine l'image originale inversee.
721
 
        cairo_translate (pCairoContext, fImageWidth, 0);
722
 
        cairo_scale (pCairoContext, -1., 1.);
723
 
        cairo_set_source_surface (pCairoContext, pSurface, (bDirectionUp ? 0. : fImageHeight - fReflectSize), 0.);
724
 
        
725
 
        //\_______________ On applique un degrade en transparence.
726
 
        cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (0,
727
 
                0.,
728
 
                fImageHeight - fReflectSize,
729
 
                0.);  // de gauche a droite.
730
 
        g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, NULL);
731
 
 
732
 
        cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_REPEAT);
733
 
        cairo_pattern_add_color_stop_rgba (pGradationPattern,
734
 
                0.,
735
 
                0.,
736
 
                0.,
737
 
                0.,
738
 
                (bDirectionUp ? fAlbedo : 0.));
739
 
        cairo_pattern_add_color_stop_rgba (pGradationPattern,
740
 
                1.,
741
 
                0.,
742
 
                0.,
743
 
                0.,
744
 
                (bDirectionUp ? 0. : fAlbedo));
745
 
 
746
 
        cairo_mask (pCairoContext, pGradationPattern);
747
 
 
748
 
        cairo_pattern_destroy (pGradationPattern);
749
 
        cairo_destroy (pCairoContext);
750
 
        return pNewSurface;
751
 
}
752
 
 
753
 
cairo_surface_t * cairo_dock_create_reflection_surface (cairo_surface_t *pSurface, cairo_t *pSourceContext, double fImageWidth, double fImageHeight, double fReflectSize, double fAlbedo, gboolean bIsHorizontal, gboolean bDirectionUp)
754
 
{
755
 
        if (bIsHorizontal)
756
 
                return cairo_dock_create_reflection_surface_horizontal (pSurface, pSourceContext, fImageWidth, fImageHeight, fReflectSize, fAlbedo, bDirectionUp);
757
 
        else
758
 
                return cairo_dock_create_reflection_surface_vertical (pSurface, pSourceContext, fImageWidth, fImageHeight, fReflectSize, fAlbedo, bDirectionUp);
759
 
}
760
 
 
761
 
 
762
 
cairo_surface_t *cairo_dock_create_surface_from_text_full (const gchar *cText, cairo_t* pSourceContext, CairoDockLabelDescription *pLabelDescription, double fMaxScale, int iMaxWidth, int *iTextWidth, int *iTextHeight, double *fTextXOffset, double *fTextYOffset)
763
 
{
764
 
        g_return_val_if_fail (cText != NULL && pLabelDescription != NULL && pSourceContext != NULL && cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
765
 
        
766
 
        //\_________________ On ecrit le texte dans un calque Pango.
767
 
        PangoLayout *pLayout = pango_cairo_create_layout (pSourceContext);
768
 
        
769
 
        PangoFontDescription *pDesc = pango_font_description_new ();
770
 
        pango_font_description_set_absolute_size (pDesc, fMaxScale * pLabelDescription->iSize * PANGO_SCALE);
771
 
        pango_font_description_set_family_static (pDesc, pLabelDescription->cFont);
772
 
        pango_font_description_set_weight (pDesc, pLabelDescription->iWeight);
773
 
        pango_font_description_set_style (pDesc, pLabelDescription->iStyle);
774
 
        pango_layout_set_font_description (pLayout, pDesc);
775
 
        pango_font_description_free (pDesc);
776
 
        
777
 
        pango_layout_set_text (pLayout, cText, -1);
778
 
        
779
 
        //\_________________ On cree une surface aux dimensions du texte.
780
 
        PangoRectangle ink, log;
781
 
        pango_layout_get_pixel_extents (pLayout, &ink, &log);
782
 
        
783
 
        int iOutlineMargin = 2*pLabelDescription->iMargin + (pLabelDescription->bOutlined ? 2 : 0);  // outlined => +1 tout autour des lettres.
784
 
        double fZoomX = ((iMaxWidth != 0 && ink.width + iOutlineMargin > iMaxWidth) ? 1.*iMaxWidth / (ink.width + iOutlineMargin) : 1.);
785
 
        
786
 
        *iTextWidth = (ink.width + iOutlineMargin) * fZoomX;
787
 
        *iTextHeight = ink.height + iOutlineMargin + 0; // +1 car certaines polices "debordent".
788
 
        //Test du zoom en W ET H *iTextHeight = (ink.height + 2 + 1) * fZoom; 
789
 
        
790
 
        cairo_surface_t* pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
791
 
                *iTextWidth,
792
 
                *iTextHeight);
793
 
        cairo_t* pCairoContext = cairo_create (pNewSurface);
794
 
        
795
 
        //\_________________ On dessine le fond.
796
 
        if (pLabelDescription->fBackgroundColor != NULL && pLabelDescription->fBackgroundColor[3] > 0)  // non transparent.
797
 
        {
798
 
                cairo_save (pCairoContext);
799
 
                double fRadius = fMaxScale * MAX (pLabelDescription->iMargin, MIN (6, pLabelDescription->iSize/3));  // permet d'avoir un rayon meme si on n'a pas de marge.
800
 
                double fLineWidth = 0.;
801
 
                double fFrameWidth = *iTextWidth - 2 * fRadius - fLineWidth;
802
 
                double fFrameHeight = *iTextHeight - fLineWidth;
803
 
                cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, fFrameWidth, fFrameHeight);
804
 
                cairo_set_source_rgba (pCairoContext, pLabelDescription->fBackgroundColor[0], pLabelDescription->fBackgroundColor[1], pLabelDescription->fBackgroundColor[2], pLabelDescription->fBackgroundColor[3]);
805
 
                cairo_fill (pCairoContext);
806
 
                cairo_restore(pCairoContext);
807
 
        }
808
 
        
809
 
        //g_print ("%s : ink = %d;%d\n", cText, (int) ink.x, (int) ink.y);
810
 
        cairo_translate (pCairoContext, -ink.x*fZoomX + iOutlineMargin/2, -ink.y + iOutlineMargin/2);  // meme remarque pour le +1.
811
 
        
812
 
        //\_________________ On dessine les contours du texte.
813
 
        if (pLabelDescription->bOutlined)
814
 
        {
815
 
                cairo_save (pCairoContext);
816
 
                if (fZoomX != 1)
817
 
                        cairo_scale (pCairoContext, fZoomX, 1.);
818
 
                cairo_push_group (pCairoContext);
819
 
                cairo_set_source_rgb (pCairoContext, 0.2, 0.2, 0.2);
820
 
                int i;
821
 
                for (i = 0; i < 2; i++)
822
 
                {
823
 
                        cairo_move_to (pCairoContext, 0, 2*i-1);
824
 
                        pango_cairo_show_layout (pCairoContext, pLayout);
825
 
                }
826
 
                for (i = 0; i < 2; i++)
827
 
                {
828
 
                        cairo_move_to (pCairoContext, 2*i-1, 0);
829
 
                        pango_cairo_show_layout (pCairoContext, pLayout);
830
 
                }
831
 
                cairo_pop_group_to_source (pCairoContext);
832
 
                //cairo_paint_with_alpha (pCairoContext, .75);
833
 
                cairo_paint (pCairoContext);
834
 
                cairo_restore(pCairoContext);
835
 
        }
836
 
 
837
 
        //\_________________ On remplit l'interieur du texte.
838
 
        cairo_pattern_t *pGradationPattern = NULL;
839
 
        if (pLabelDescription->fColorStart != pLabelDescription->fColorStop)
840
 
        {
841
 
                if (pLabelDescription->bVerticalPattern)
842
 
                        pGradationPattern = cairo_pattern_create_linear (0.,
843
 
                                ink.y + 0,  // meme remarque pour le +1.
844
 
                                0.,
845
 
                                ink.y + 0 + ink.height);
846
 
                else
847
 
                        pGradationPattern = cairo_pattern_create_linear (ink.x + 0,
848
 
                                0.,
849
 
                                ink.x + 0 + ink.width,
850
 
                                0.);
851
 
                g_return_val_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS, NULL);
852
 
                cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
853
 
                cairo_pattern_add_color_stop_rgba (pGradationPattern,
854
 
                        0.,
855
 
                        pLabelDescription->fColorStart[0],
856
 
                        pLabelDescription->fColorStart[1],
857
 
                        pLabelDescription->fColorStart[2],
858
 
                        1.);
859
 
                cairo_pattern_add_color_stop_rgba (pGradationPattern,
860
 
                        1.,
861
 
                        pLabelDescription->fColorStop[0],
862
 
                        pLabelDescription->fColorStop[1],
863
 
                        pLabelDescription->fColorStop[2],
864
 
                        1.);
865
 
                cairo_set_source (pCairoContext, pGradationPattern);
866
 
        }
867
 
        else
868
 
                cairo_set_source_rgb (pCairoContext, pLabelDescription->fColorStart[0], pLabelDescription->fColorStart[1], pLabelDescription->fColorStart[2]);
869
 
        cairo_move_to (pCairoContext, 0, 0);
870
 
        if (fZoomX != 1)
871
 
                cairo_scale (pCairoContext, fZoomX, 1.);
872
 
        //if (pLabelDescription->bOutlined)
873
 
        //      cairo_move_to (pCairoContext, 1,1);
874
 
        pango_cairo_show_layout (pCairoContext, pLayout);
875
 
        cairo_pattern_destroy (pGradationPattern);
876
 
        
877
 
        cairo_destroy (pCairoContext);
878
 
        
879
 
        /* set_device_offset is buggy, doesn't work for positive offsets. so we use explicit offsets... so unfortunate.
880
 
        cairo_surface_set_device_offset (pNewSurface,
881
 
                                         log.width / 2. - ink.x,
882
 
                                         log.height     - ink.y);*/
883
 
        if (fTextXOffset != NULL)
884
 
                *fTextXOffset = (log.width * fZoomX / 2. - ink.x) / fMaxScale;
885
 
        if (fTextYOffset != NULL)
886
 
                *fTextYOffset = - (pLabelDescription->iSize - (log.height - ink.y)) / fMaxScale ;  // en tenant compte de l'ecart du bas du texte.
887
 
        // *fTextYOffset = - (ink.y) / fMaxScale;  // pour tenir compte de l'ecart du bas du texte.
888
 
        
889
 
        *iTextWidth = *iTextWidth / fMaxScale;
890
 
        *iTextHeight = *iTextHeight / fMaxScale;
891
 
        
892
 
        g_object_unref (pLayout);
893
 
        return pNewSurface;
894
 
}
895
 
 
896
 
 
897
 
cairo_surface_t * cairo_dock_duplicate_surface (cairo_surface_t *pSurface, cairo_t *pSourceContext, double fWidth, double fHeight, double fDesiredWidth, double fDesiredHeight)
898
 
{
899
 
        g_return_val_if_fail (pSurface != NULL && pSourceContext != NULL && cairo_status (pSourceContext) == CAIRO_STATUS_SUCCESS, NULL);
900
 
 
901
 
        //\_______________ On cree la surface de la taille desiree.
902
 
        if (fDesiredWidth == 0)
903
 
                fDesiredWidth = fWidth;
904
 
        if (fDesiredHeight == 0)
905
 
                fDesiredHeight = fHeight;
906
 
        
907
 
        //g_print ("%s (%.2fx%.2f -> %.2fx%.2f)\n", __func__, fWidth, fHeight, fDesiredWidth, fDesiredHeight);
908
 
        cairo_surface_t *pNewSurface = _cairo_dock_create_blank_surface (pSourceContext,
909
 
                fDesiredWidth,
910
 
                fDesiredHeight);
911
 
        cairo_t *pCairoContext = cairo_create (pNewSurface);
912
 
 
913
 
        //\_______________ On plaque la surface originale dessus.
914
 
        cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
915
 
        cairo_scale (pCairoContext,
916
 
                fDesiredWidth / fWidth,
917
 
                fDesiredHeight / fHeight);
918
 
        
919
 
        cairo_set_source_surface (pCairoContext, pSurface, 0., 0.);
920
 
        cairo_paint (pCairoContext);
921
 
        cairo_destroy (pCairoContext);
922
 
        
923
 
        return pNewSurface;
924
 
}