~ubuntu-branches/ubuntu/oneiric/cairo-dock-plug-ins/oneiric-updates

« back to all changes in this revision

Viewing changes to dock-rendering/src/rendering-rainbow.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2009-08-26 21:07:39 UTC
  • Revision ID: james.westby@ubuntu.com-20090826210739-gyjuuqezrzuluao4
Tags: upstream-2.0.8.1
ImportĀ upstreamĀ versionĀ 2.0.8.1

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
/*********************************************************************************
 
21
 
 
22
This file is a part of the cairo-dock program, 
 
23
released under the terms of the GNU General Public License.
 
24
 
 
25
Written by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
 
26
 
 
27
*********************************************************************************/
 
28
#include <math.h>
 
29
#include <string.h>
 
30
#include <stdio.h>
 
31
#include <stdlib.h>
 
32
 
 
33
#include <gtk/gtk.h>
 
34
 
 
35
#include <cairo.h>
 
36
 
 
37
#include "rendering-rainbow.h"
 
38
 
 
39
extern int my_iSpaceBetweenRows;
 
40
extern int my_iSpaceBetweenIcons;
 
41
extern double my_fRainbowMagnitude;
 
42
extern int my_iRainbowNbIconsMin;
 
43
extern double my_fRainbowConeOffset;
 
44
extern double my_fRainbowColor[4];
 
45
extern double my_fRainbowLineColor[4];
 
46
 
 
47
void cd_rendering_calculate_max_dock_size_rainbow (CairoDock *pDock)
 
48
{
 
49
        pDock->fMagnitudeMax = my_fRainbowMagnitude;
 
50
        pDock->pFirstDrawnElement = cairo_dock_calculate_icons_positions_at_rest_linear (pDock->icons, pDock->fFlatDockWidth, pDock->iScrollOffset);
 
51
        
 
52
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
53
        int iMaxIconWidth = pDock->iMaxIconHeight + my_iSpaceBetweenIcons;
 
54
        double fCone = G_PI - 2 * my_fRainbowConeOffset;
 
55
        int iNbIcons = g_list_length (pDock->icons);
 
56
        int iMinRadius = MIN (my_iRainbowNbIconsMin, iNbIcons) * iMaxIconWidth * fMaxScale / fCone;
 
57
        
 
58
        int iNbRows = (int) ceil (sqrt (2 * iNbIcons / fCone / fMaxScale) + .5);  /// approximation, utiliser la formule complete...
 
59
        
 
60
        pDock->iMaxDockHeight = iNbRows * (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale + iMinRadius;
 
61
        pDock->iMaxDockWidth = 2 * (pDock->iMaxDockHeight * cos (my_fRainbowConeOffset));
 
62
        cd_debug ("iNbRows : %d => %dx%d (iMaxIconHeight = %d ; iMinRadius = %d ; fMaxScale = %.2f)\n", iNbRows, pDock->iMaxDockWidth, pDock->iMaxDockHeight, pDock->iMaxIconHeight, iMinRadius, fMaxScale);
 
63
        
 
64
        pDock->iDecorationsWidth = 0;
 
65
        pDock->iDecorationsHeight = 0;
 
66
        
 
67
        pDock->iMinDockWidth = pDock->fFlatDockWidth;
 
68
        pDock->iMinDockHeight = pDock->iMaxIconHeight;
 
69
}
 
70
 
 
71
 
 
72
void cd_rendering_render_rainbow (cairo_t *pCairoContext, CairoDock *pDock)
 
73
{
 
74
        //g_print ("pDock->fFoldingFactor : %.2f\n", pDock->fFoldingFactor);
 
75
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
76
        double fRadius=0;
 
77
        if (my_fRainbowColor[3] != 0)
 
78
        {
 
79
                cairo_save (pCairoContext);
 
80
                if (! pDock->bHorizontalDock)
 
81
                {
 
82
                        cairo_translate (pCairoContext, pDock->iCurrentHeight/2, pDock->iCurrentWidth/2);
 
83
                        cairo_rotate (pCairoContext, -G_PI/2);
 
84
                        cairo_translate (pCairoContext, -pDock->iCurrentWidth/2, -pDock->iCurrentHeight/2);
 
85
                }
 
86
                if (!pDock->bDirectionUp)
 
87
                {
 
88
                        cairo_translate (pCairoContext, 0., pDock->iCurrentHeight);
 
89
                        cairo_scale (pCairoContext, 1., -1.);
 
90
                }
 
91
                //\____________________ On trace le cadre.
 
92
                cairo_move_to (pCairoContext, 0., pDock->iCurrentHeight * (1 - sin (my_fRainbowConeOffset)));
 
93
                cairo_line_to (pCairoContext, pDock->iCurrentWidth/2, pDock->iCurrentHeight);
 
94
                cairo_line_to (pCairoContext, pDock->iCurrentWidth, pDock->iCurrentHeight * (1 - sin (my_fRainbowConeOffset)));
 
95
                cairo_line_to (pCairoContext, pDock->iCurrentWidth, 0.);
 
96
                cairo_line_to (pCairoContext, 0., 0.);
 
97
                cairo_close_path (pCairoContext);
 
98
                cairo_clip (pCairoContext);
 
99
                
 
100
                //\____________________ On dessine les decorations dedans.
 
101
                cairo_pattern_t *pGradationPattern = cairo_pattern_create_radial (pDock->iCurrentWidth/2,
 
102
                        pDock->iCurrentHeight,
 
103
                        0.,
 
104
                        pDock->iCurrentWidth/2,
 
105
                        pDock->iCurrentHeight,
 
106
                        pDock->iCurrentHeight);
 
107
                g_return_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS);
 
108
                
 
109
                cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
 
110
                cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
111
                        0.,
 
112
                        0.,
 
113
                        0.,
 
114
                        0.,
 
115
                        0.);
 
116
                
 
117
                GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
118
                GList *ic = pFirstDrawnElement;
 
119
                Icon *pFirstIcon = pFirstDrawnElement->data;
 
120
                double fCurrentRadius=0;
 
121
                Icon *icon;
 
122
                do
 
123
                {
 
124
                        icon = ic->data;
 
125
                        fRadius = icon->fX - (pDock->bDirectionUp ? pDock->iMaxIconHeight * fMaxScale : 0);
 
126
                        if (fRadius != fCurrentRadius)
 
127
                        {
 
128
                                if (fCurrentRadius == 0)  // 1er coup.
 
129
                                {
 
130
                                        cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
131
                                                (fRadius - my_iSpaceBetweenRows/2)/ pDock->iCurrentHeight,
 
132
                                                0.,
 
133
                                                0.,
 
134
                                                0.,
 
135
                                                0.);
 
136
                                }
 
137
                                
 
138
                                cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
139
                                        (fRadius + .5 * pDock->iMaxIconHeight * fMaxScale)/ pDock->iCurrentHeight,
 
140
                                        my_fRainbowColor[0],
 
141
                                        my_fRainbowColor[1],
 
142
                                        my_fRainbowColor[2],
 
143
                                        my_fRainbowColor[3]);
 
144
                                cairo_pattern_add_color_stop_rgba (pGradationPattern,
 
145
                                        (fRadius + pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2)/ pDock->iCurrentHeight,
 
146
                                        0.,
 
147
                                        0.,
 
148
                                        0.,
 
149
                                        0.);
 
150
                                fCurrentRadius = fRadius;
 
151
                        }
 
152
                        ic = cairo_dock_get_next_element (ic, pDock->icons);
 
153
                } while (ic != pFirstDrawnElement);
 
154
                
 
155
                cairo_set_source (pCairoContext, pGradationPattern);
 
156
                cairo_paint (pCairoContext);
 
157
                cairo_pattern_destroy (pGradationPattern);
 
158
                cairo_restore (pCairoContext);
 
159
        }
 
160
        
 
161
        //\____________________ On dessine le cadre.
 
162
        if (fRadius == 0)
 
163
        {
 
164
                Icon *icon = cairo_dock_get_last_drawn_icon (pDock);
 
165
                if (icon)
 
166
                        fRadius = icon->fX - (pDock->bDirectionUp ? pDock->iMaxIconHeight * fMaxScale : 0);
 
167
        }
 
168
        fRadius += .5 * pDock->iMaxIconHeight * fMaxScale;
 
169
        if (my_fRainbowLineColor[3] != 0)
 
170
        {
 
171
                cairo_save (pCairoContext);
 
172
                if (! pDock->bHorizontalDock)
 
173
                {
 
174
                        cairo_translate (pCairoContext, pDock->iCurrentHeight/2, pDock->iCurrentWidth/2);
 
175
                        cairo_rotate (pCairoContext, -G_PI/2);
 
176
                        cairo_translate (pCairoContext, -pDock->iCurrentWidth/2, -pDock->iCurrentHeight/2);
 
177
                }
 
178
                if (!pDock->bDirectionUp)
 
179
                {
 
180
                        cairo_translate (pCairoContext, 0., pDock->iCurrentHeight);
 
181
                        cairo_scale (pCairoContext, 1., -1.);
 
182
                }
 
183
                cairo_set_line_width (pCairoContext, myBackground.iDockLineWidth);
 
184
                cairo_move_to (pCairoContext, pDock->iCurrentWidth/2 - fRadius * cos (my_fRainbowConeOffset), pDock->iCurrentHeight - fRadius * sin (my_fRainbowConeOffset));
 
185
                cairo_line_to (pCairoContext, pDock->iCurrentWidth/2, pDock->iCurrentHeight);
 
186
                cairo_line_to (pCairoContext, pDock->iCurrentWidth/2 + fRadius * cos (my_fRainbowConeOffset), pDock->iCurrentHeight - fRadius * sin (my_fRainbowConeOffset));
 
187
                cairo_set_source_rgba (pCairoContext,
 
188
                        my_fRainbowLineColor[0],
 
189
                        my_fRainbowLineColor[1],
 
190
                        my_fRainbowLineColor[2],
 
191
                        my_fRainbowLineColor[3]);
 
192
                cairo_stroke (pCairoContext);
 
193
                cairo_restore (pCairoContext);
 
194
        }
 
195
        
 
196
        //\____________________ On dessine la ficelle qui les joint.
 
197
        
 
198
        //\____________________ On dessine les icones avec leurs etiquettes.
 
199
        ///cairo_dock_render_icons_linear (pCairoContext, pDock, fRatio);
 
200
        GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
 
201
        if (pFirstDrawnElement == NULL)
 
202
                return;
 
203
 
 
204
        double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex)/** * pDock->fMagnitudeMax*/;
 
205
        Icon *icon;
 
206
        int iWidth = pDock->iCurrentWidth;
 
207
        gboolean bHorizontalDock = pDock->bHorizontalDock;
 
208
        GList *ic = pFirstDrawnElement;
 
209
        do
 
210
        {
 
211
                icon = ic->data;
 
212
 
 
213
                cairo_save (pCairoContext);
 
214
                
 
215
                cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
 
216
                
 
217
                cairo_restore (pCairoContext);
 
218
 
 
219
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
220
        } while (ic != pFirstDrawnElement);
 
221
}
 
222
 
 
223
 
 
224
static void cd_rendering_get_polar_coords (CairoDock *pDock, double *fRadius, double *fTheta)
 
225
{
 
226
        double x = pDock->iMouseX - pDock->iCurrentWidth / 2, y = (pDock->bDirectionUp ? pDock->iCurrentHeight - pDock->iMouseY : pDock->iMouseY);
 
227
        
 
228
        *fRadius = sqrt (x * x + y * y);
 
229
        *fTheta = atan2 (x, y);
 
230
}
 
231
 
 
232
static double _calculate_wave_offset (int x_abs, int iMaxIconHeight, double fMagnitude, double fFlatDockWidth, int iWidth, double fAlign, double fFoldingFactor, double fRatio)
 
233
{
 
234
        int iIconNumber = (x_abs + .5*my_iSpaceBetweenRows) / (iMaxIconHeight + my_iSpaceBetweenRows);
 
235
        
 
236
        int x_cumulated = iIconNumber * (iMaxIconHeight + my_iSpaceBetweenRows);
 
237
        cd_debug (" iIconNumber : %d ; x_cumulated : %d\n", iIconNumber, x_cumulated);
 
238
        double fXMiddle = x_cumulated + iMaxIconHeight / 2;
 
239
        double fPhase = (fXMiddle - x_abs) / myIcons.iSinusoidWidth / fRatio * G_PI + G_PI / 2;
 
240
        if (fPhase < 0)
 
241
        {
 
242
                fPhase = 0;
 
243
        }
 
244
        else if (fPhase > G_PI)
 
245
        {
 
246
                fPhase = G_PI;
 
247
        }
 
248
        double fScale = 1 + fMagnitude * g_fAmplitude * sin (fPhase);
 
249
        double fX = x_cumulated - 0*(fFlatDockWidth - iWidth) / 2 + (1 - fScale) * (x_abs - x_cumulated + .5*my_iSpaceBetweenRows);
 
250
        fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
251
        
 
252
        while (iIconNumber > 0)
 
253
        {
 
254
                iIconNumber --;
 
255
                x_cumulated = iIconNumber * (iMaxIconHeight + my_iSpaceBetweenRows);
 
256
                //cd_debug ("  %d) x_cumulated = %d\n", iIconNumber, x_cumulated);
 
257
                fXMiddle = x_cumulated + iMaxIconHeight / 2;
 
258
                fPhase = (fXMiddle - x_abs) / myIcons.iSinusoidWidth / fRatio * G_PI + G_PI / 2;
 
259
                if (fPhase < 0)
 
260
                {
 
261
                        fPhase = 0;
 
262
                }
 
263
                else if (fPhase > G_PI)
 
264
                {
 
265
                        fPhase = G_PI;
 
266
                }
 
267
                fScale = 1 + fMagnitude * g_fAmplitude * sin (fPhase);
 
268
                
 
269
                fX = fX - (iMaxIconHeight + my_iSpaceBetweenRows) * fScale;
 
270
                fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
271
        }
 
272
        return -fX;
 
273
}
 
274
static double cd_rendering_calculate_wave_position (CairoDock *pDock, double fCurvilignAbscisse, double fMagnitude)
 
275
{
 
276
        cd_debug ("%s (%.2f)\n", __func__, fCurvilignAbscisse);
 
277
        
 
278
        if (pDock->icons == NULL || fCurvilignAbscisse <= 0)
 
279
                return 0;
 
280
        double fWaveOffset, fWaveExtrema;
 
281
        double x_abs = fCurvilignAbscisse;
 
282
        int nb_iter = 0;
 
283
        double fRatio = pDock->fRatio;
 
284
        
 
285
        do
 
286
        {
 
287
                //cd_debug ("  x_abs : %.2f\n", x_abs);
 
288
                fWaveOffset = _calculate_wave_offset (x_abs, pDock->iMaxIconHeight, fMagnitude, pDock->fFlatDockWidth, pDock->fFlatDockWidth, 0*pDock->fAlign, pDock->fFoldingFactor, fRatio);
 
289
                
 
290
                fWaveExtrema = fWaveOffset + x_abs;
 
291
                if (fWaveExtrema >= 0)
 
292
                        x_abs += (fCurvilignAbscisse - fWaveExtrema) / 2;
 
293
                else
 
294
                        x_abs = MAX (0, x_abs - (fCurvilignAbscisse - fWaveExtrema) / 2);
 
295
                if (x_abs > (int) pDock->fFlatDockWidth)
 
296
                {
 
297
                        x_abs = (int) pDock->fFlatDockWidth;
 
298
                        break ;
 
299
                }
 
300
                //cd_debug ("  -> fWaveOffset : %.2f, fWaveExtrema : %.2f\n", fWaveOffset, fWaveExtrema);
 
301
                
 
302
                nb_iter ++;
 
303
        }
 
304
        while (fabs (fWaveExtrema - fCurvilignAbscisse) > 1 && nb_iter < 15);
 
305
        
 
306
        return x_abs;
 
307
}
 
308
 
 
309
static int cd_rendering_calculate_wave_on_each_lines (int x_abs, int iMaxIconHeight, double fMagnitude, double fFlatDockWidth, int iWidth, double fAlign, double fFoldingFactor, double fRatio, int iNbRows, double *pScales)  // (fScale,fX)
 
310
{
 
311
        if (iNbRows == 0)
 
312
                return 0;
 
313
        cd_debug ("%s (%d, %.2f, %.2f, %d)\n", __func__, x_abs, fMagnitude, fFoldingFactor, iNbRows);
 
314
        if (x_abs < 0 && iWidth > 0)  // ces cas limite sont la pour empecher les icones de retrecir trop rapidement quend on sort par les cotes.
 
315
                x_abs = -1;
 
316
        else if (x_abs > fFlatDockWidth && iWidth > 0)
 
317
                x_abs = fFlatDockWidth+1;
 
318
        
 
319
        float x_cumulated = 0, fXMiddle, fDeltaExtremum;
 
320
        double fPhase, fScale, fX;
 
321
        int iNumRow, iPointedRow=-1;
 
322
        for (iNumRow = 0; iNumRow < iNbRows; iNumRow ++)
 
323
        {
 
324
                //cd_debug (" ligne %d\n", iNumRow);
 
325
                fXMiddle = x_cumulated + .5*iMaxIconHeight;
 
326
                
 
327
                fPhase = (fXMiddle - x_abs) / myIcons.iSinusoidWidth / fRatio * G_PI + G_PI / 2;
 
328
                if (fPhase < 0)
 
329
                        fPhase = 0;
 
330
                else if (fPhase > G_PI)
 
331
                        fPhase = G_PI;
 
332
                fScale = 1 + fMagnitude * g_fAmplitude * sin (fPhase);
 
333
                pScales[2*iNumRow] = fScale;
 
334
                //cd_debug ("  fScale : %.2f\n", fScale);
 
335
                
 
336
                if (iPointedRow != -1)
 
337
                {
 
338
                        fX = pScales[2*(iNumRow-1)+1] + (iMaxIconHeight + my_iSpaceBetweenRows) * pScales[2*(iNumRow-1)];
 
339
                        fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
340
                        pScales[2*iNumRow+1] = fX;
 
341
                        //cd_debug ("  fX : %.2f (prev : %.2f , %.2f)\n", fX, pScales[2*(iNumRow-1)+1], pScales[2*(iNumRow-1)]);
 
342
                }
 
343
                
 
344
                if (x_cumulated + iMaxIconHeight + .5*my_iSpaceBetweenRows >= x_abs && x_cumulated - .5*my_iSpaceBetweenRows <= x_abs && iPointedRow == -1)  // on a trouve la ligne sur laquelle on pointe.
 
345
                {
 
346
                        iPointedRow = iNumRow;
 
347
                        fX = x_cumulated - 0*(fFlatDockWidth - iWidth) / 2 + (1 - fScale) * (x_abs - x_cumulated + .5*my_iSpaceBetweenRows);
 
348
                        fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
349
                        //cd_debug ("  ligne pointee : %d\n", iPointedRow);
 
350
                        pScales[2*iNumRow+1] = fX;
 
351
                        //cd_debug ("  fX : %.2f\n", fX);
 
352
                }
 
353
                
 
354
                x_cumulated += iMaxIconHeight;
 
355
        }
 
356
        
 
357
        if (iPointedRow == -1)  // on est en dehors du disque.
 
358
        {
 
359
                iPointedRow = iNbRows - 1;
 
360
                
 
361
                fX = x_cumulated - (fFlatDockWidth - iWidth) / 2 + (1 - fScale) * (iMaxIconHeight + .5*my_iSpaceBetweenRows);
 
362
                fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1 - fFoldingFactor);
 
363
                pScales[2*iNumRow+1] = fX;
 
364
                //cd_debug ("  fX : %.2f\n", fX);
 
365
        }
 
366
        
 
367
        for (iNumRow = iPointedRow-1; iNumRow >= 0; iNumRow --)
 
368
        {
 
369
                fX = pScales[2*(iNumRow+1)+1] - (iMaxIconHeight + my_iSpaceBetweenRows) * pScales[2*iNumRow];
 
370
                fX = fAlign * iWidth + (fX - fAlign * iWidth) * (1. - fFoldingFactor);
 
371
                pScales[2*iNumRow+1] = fX;
 
372
                //cd_debug ("  fX : %.2f\n", fX);
 
373
        }
 
374
        
 
375
        fX = pScales[1];
 
376
        for (iNumRow = 0; iNumRow < iNbRows; iNumRow ++)
 
377
        {
 
378
                pScales[2*iNumRow+1] -= fX;
 
379
        }
 
380
        
 
381
        return iPointedRow;
 
382
}
 
383
 
 
384
Icon *cd_rendering_calculate_icons_rainbow (CairoDock *pDock)
 
385
{
 
386
        if (pDock->icons == NULL)
 
387
                return NULL;
 
388
        
 
389
        //\____________________ On se place en coordonnees polaires.
 
390
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
391
        int iMaxIconWidth = pDock->iMaxIconHeight + my_iSpaceBetweenIcons;
 
392
        double fCone = G_PI - 2 * my_fRainbowConeOffset;
 
393
        int iNbIcons = g_list_length (pDock->icons);
 
394
        int iMinRadius = MIN (my_iRainbowNbIconsMin, iNbIcons) * iMaxIconWidth * fMaxScale / fCone;
 
395
        double fRatio = pDock->fRatio;
 
396
        double w = pDock->iCurrentWidth;
 
397
        double h = pDock->iCurrentHeight;
 
398
        double fRadius, fTheta;
 
399
        cd_debug (" mouse : (%d ; %d)\n", pDock->iMouseX, pDock->iMouseY);
 
400
        cd_rendering_get_polar_coords (pDock, &fRadius, &fTheta);
 
401
        cd_debug (" polar : (%.2f ; %.2f)\n", fRadius, fTheta/G_PI*180.);
 
402
        
 
403
        double fCurvilignAbscisse = (fTheta > -G_PI/2 && fTheta < G_PI/2 ? MAX (0, fRadius - iMinRadius): 0);
 
404
        
 
405
        //\____________________ On en deduit ou appliquer la vague pour que la crete soit a la position du curseur.
 
406
        Icon *pPointedIcon = NULL;
 
407
        double fMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex) * pDock->fMagnitudeMax;
 
408
        int x_abs = (int) round (cd_rendering_calculate_wave_position (pDock, fCurvilignAbscisse, fMagnitude));
 
409
        cd_debug (" => x_abs : %d (fMagnitude:%.2f ; fFoldingFactor:%.2f)\n", x_abs, fMagnitude, pDock->fFoldingFactor);
 
410
        
 
411
        //\_______________ On en deduit l'amplitude de chaque ligne.
 
412
        int iNbRows = round ((pDock->iMaxDockHeight- iMinRadius) / ((pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale));
 
413
        cd_debug ("iNbRows : %d\n", iNbRows);
 
414
        double fFlatDockWidth = iNbRows * (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale;
 
415
        double *pScales = g_new0 (double, 2*iNbRows+2);
 
416
        cd_rendering_calculate_wave_on_each_lines (x_abs, pDock->iMaxIconHeight, fMagnitude, fFlatDockWidth, fFlatDockWidth, 0*pDock->fAlign, pDock->fFoldingFactor, fRatio, iNbRows, pScales);
 
417
        
 
418
        //\____________________ On en deduit les position/etirements/alpha des icones.
 
419
        Icon* icon, *prev_icon;
 
420
        GList* ic;
 
421
        
 
422
        GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
423
        ic = pFirstDrawnElement;
 
424
        Icon *pFirstIcon = pFirstDrawnElement->data;
 
425
        
 
426
        int iNbRow = -1, iNbIconsOnRow = 0, iNbInsertedIcons = 0;
 
427
        double fCurrentRadius=0, fNormalRadius=0, fCurrentTheta, fThetaStart, fDeltaTheta, fCurrentScale;
 
428
        do
 
429
        {
 
430
                icon = ic->data;
 
431
                
 
432
                if (iNbInsertedIcons == iNbIconsOnRow)
 
433
                {
 
434
                        iNbRow ++;
 
435
                        if (iNbRow == iNbRows)
 
436
                                break ;
 
437
                        iNbInsertedIcons = 0;
 
438
                        fCurrentRadius = iMinRadius * (1 - pDock->fFoldingFactor) + pScales[2*iNbRow+1];
 
439
                        fCurrentScale = pScales[2*iNbRow] * (1 - pDock->fFoldingFactor);
 
440
                        fNormalRadius = iMinRadius + iNbRow * (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fMaxScale;
 
441
                        fDeltaTheta = 2 * atan (iMaxIconWidth * fMaxScale / 2 / fNormalRadius);
 
442
                        iNbIconsOnRow = (int) (fCone / fDeltaTheta);
 
443
                        fThetaStart = - G_PI/2 + my_fRainbowConeOffset + (fCone - iNbIconsOnRow * fDeltaTheta) / 2 + fDeltaTheta / 2;
 
444
                        cd_debug ("on passe a la ligne %d (%d icones, fThetaStart = %.2fdeg, fCurrentRadius = %.2f(%.2f), fDeltaTheta = %.2f, fCurrentScale = %.2f)\n", iNbRow, iNbIconsOnRow, fThetaStart/G_PI*180, fCurrentRadius, fNormalRadius, fDeltaTheta/G_PI*180, fCurrentScale);
 
445
                }
 
446
                
 
447
                icon->fX = fCurrentRadius + (pDock->bDirectionUp ? pDock->iMaxIconHeight * fCurrentScale : 0);
 
448
                
 
449
                fCurrentTheta = fThetaStart + iNbInsertedIcons * fDeltaTheta;
 
450
                icon->fOrientation = (pDock->bDirectionUp ? fCurrentTheta : - fCurrentTheta);
 
451
                if (! pDock->bHorizontalDock)
 
452
                {
 
453
                        icon->fOrientation = -icon->fOrientation + 0;
 
454
                }
 
455
                if (pPointedIcon == NULL && fRadius < fCurrentRadius + (pDock->iMaxIconHeight + my_iSpaceBetweenRows) * fCurrentScale && fRadius > fCurrentRadius && fTheta > fCurrentTheta - fDeltaTheta/2 && fTheta < fCurrentTheta + fDeltaTheta/2)
 
456
                {
 
457
                        icon->bPointed = TRUE;
 
458
                        pPointedIcon = icon;
 
459
                        cd_debug (" POINTED ICON : %s\n", pPointedIcon->acName);
 
460
                }
 
461
                else
 
462
                        icon->bPointed = FALSE;
 
463
                
 
464
                //if (pDock->bHorizontalDock)
 
465
                {
 
466
                        icon->fDrawY = icon->fX * cos (fCurrentTheta) + icon->fWidth/2 * fCurrentScale * sin (fCurrentTheta);
 
467
                        if (pDock->bDirectionUp)
 
468
                                icon->fDrawY = pDock->iCurrentHeight - icon->fDrawY;
 
469
                        icon->fDrawX = icon->fX * sin (fCurrentTheta) - icon->fWidth/2 * fCurrentScale * cos (fCurrentTheta) + pDock->iCurrentWidth / 2;
 
470
                }
 
471
                /*else
 
472
                {
 
473
                        icon->fDrawX = icon->fX * cos (fCurrentTheta) + icon->fWidth/2 * fCurrentScale * sin (fCurrentTheta);
 
474
                        if (!pDock->bDirectionUp)
 
475
                                icon->fDrawX = pDock->iCurrentWidth - icon->fDrawX;
 
476
                        icon->fDrawY = icon->fX * sin (fCurrentTheta) - icon->fWidth/2 * fCurrentScale * cos (fCurrentTheta) + pDock->iCurrentHeight / 2;
 
477
                }*/
 
478
                
 
479
                cd_debug (" %.2fdeg ; (%.2f;%.2f)\n", fCurrentTheta/G_PI*180, icon->fDrawX, icon->fDrawY);
 
480
                
 
481
                icon->fScale = fCurrentScale;
 
482
                icon->fAlpha = 1;
 
483
                icon->fWidthFactor = 1.;
 
484
                icon->fHeightFactor = 1.;
 
485
                
 
486
                prev_icon = icon;
 
487
                
 
488
                iNbInsertedIcons ++;
 
489
                
 
490
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
491
        } while (ic != pFirstDrawnElement);
 
492
        g_free (pScales);
 
493
        
 
494
        //g_print ("fRadius : %.2f ; limite : %.2f\n", fRadius, fCurrentRadius + pDock->iMaxIconHeight * fCurrentScale);
 
495
        if (! pDock->bInside ||
 
496
                fRadius > fCurrentRadius + pDock->iMaxIconHeight * fCurrentScale + myLabels.iLabelSize - (pDock->fFoldingFactor > 0 ? 20 : 0) ||
 
497
                (fTheta < - G_PI/2 + my_fRainbowConeOffset || fTheta > G_PI/2 - my_fRainbowConeOffset) && fRadius > iMinRadius + .5 * pDock->iMaxIconHeight * fMaxScale)
 
498
        {
 
499
                cd_debug ("<<< on sort du demi-disque >>>\n");
 
500
                pDock->iMousePositionType = CAIRO_DOCK_MOUSE_OUTSIDE;
 
501
                if (pDock->bIsDragging)
 
502
                        pDock->bCanDrop = TRUE;
 
503
        }
 
504
        else
 
505
        {
 
506
                pDock->iMousePositionType = CAIRO_DOCK_MOUSE_INSIDE;
 
507
                pDock->bCanDrop = FALSE;
 
508
        }
 
509
        
 
510
        return pPointedIcon;
 
511
}
 
512
 
 
513
 
 
514
static double *_generate_cos_sin (double fConeOffset, double fDelta, double *pTabValues)
 
515
{
 
516
        int i, n = (int) ceil ((G_PI/2 - fConeOffset) / fDelta);
 
517
        pTabValues[2*n] = 0.;  // point au milieu.
 
518
        pTabValues[2*n+1] = 1.;
 
519
        
 
520
        double fTheta;
 
521
        for (i = 0; i < n; i ++)
 
522
        {
 
523
                fTheta = (i == 0 ? G_PI/2 - fConeOffset : (n - i) * fDelta);
 
524
                pTabValues[2*i] = sin (fTheta);
 
525
                pTabValues[2*i+1] = cos (fTheta);
 
526
                
 
527
                pTabValues[2*(2*n-i)] = - pTabValues[2*i];
 
528
                pTabValues[2*(2*n-i)+1] = pTabValues[2*i+1];
 
529
        }
 
530
        return pTabValues;
 
531
}
 
532
static GLfloat *_generate_sector_path (double fConeOffset, double fRadius1, double fRadius2, double fDelta, double *pCosSinTab, GLfloat *pTabValues)
 
533
{
 
534
        int i, n = (int) ceil ((G_PI/2 - fConeOffset) / fDelta), N = (2*n+1) * 2;
 
535
        for (i = 0; i < 2*n+1; i ++)
 
536
        {
 
537
                pTabValues[3*(2*i)] = fRadius1 * pCosSinTab[2*i+0];
 
538
                pTabValues[3*(2*i)+1] = fRadius1 * pCosSinTab[2*i+1];
 
539
                pTabValues[3*(2*i+1)] = fRadius2 * pCosSinTab[2*i+0];
 
540
                pTabValues[3*(2*i+1)+1] = fRadius2 * pCosSinTab[2*i+1];
 
541
                //g_print ("%.2f;%.2f\n", pTabValues[3*i], pTabValues[3*i+1]);
 
542
        }
 
543
        pTabValues[3*N] = pTabValues[3*0];
 
544
        pTabValues[3*N+1] = pTabValues[3*0+1];
 
545
        pTabValues[3*(N+1)] = pTabValues[3*1];
 
546
        pTabValues[3*(N+1)+1] = pTabValues[3*1+1];
 
547
        
 
548
        return pTabValues;
 
549
}
 
550
 
 
551
static double *pCosSinTab = NULL;
 
552
static GLfloat *pVertexTab = NULL;
 
553
static GLfloat* pColorTab = NULL;
 
554
void cd_rendering_reload_rainbow_buffers (void)
 
555
{
 
556
        g_free (pColorTab);
 
557
        pColorTab = NULL;
 
558
        g_free (pCosSinTab);
 
559
        pCosSinTab = NULL;
 
560
}
 
561
 
 
562
void cd_rendering_render_rainbow_opengl (CairoDock *pDock)
 
563
{
 
564
        static double fDelta = 1.;
 
565
        if (pCosSinTab == NULL)
 
566
        {
 
567
                pCosSinTab = g_new0 (double, (180./fDelta+1) * 2);
 
568
                _generate_cos_sin (my_fRainbowConeOffset, fDelta/180.*G_PI, pCosSinTab);
 
569
        }
 
570
        if (pVertexTab == NULL)
 
571
                pVertexTab = g_new0 (GLfloat, ((180./fDelta+1) * 2) * 3);
 
572
        if (pColorTab == NULL)
 
573
        {
 
574
                pColorTab = g_new0 (GLfloat, ((180./fDelta+1) * 2) * 4);
 
575
                int i;
 
576
                for (i = 0; i < (180./fDelta+1); i ++)
 
577
                {
 
578
                        pColorTab[4*2*i+0] = my_fRainbowColor[0];
 
579
                        pColorTab[4*2*i+1] = my_fRainbowColor[1];
 
580
                        pColorTab[4*2*i+2] = my_fRainbowColor[2];
 
581
                        pColorTab[4*2*i+3] = my_fRainbowColor[3];
 
582
                }
 
583
        }
 
584
        
 
585
        double fMaxScale =  1. + my_fRainbowMagnitude * g_fAmplitude;
 
586
        double fRadius=0;
 
587
        if (my_fRainbowColor[3] != 0)
 
588
        {
 
589
                //\____________________ On trace le cadre.
 
590
                //\____________________ On dessine les decorations dedans.
 
591
                glEnable (GL_LINE_SMOOTH);
 
592
                glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
 
593
                ///_cairo_dock_set_blend_alpha ();  // qqch cloche ...
 
594
                _cairo_dock_set_blend_over ();
 
595
                glEnable(GL_BLEND);
 
596
                
 
597
                glPolygonMode(GL_FRONT, GL_FILL);  // GL_FILL
 
598
                glEnableClientState(GL_VERTEX_ARRAY);
 
599
                glEnableClientState(GL_COLOR_ARRAY);
 
600
                glLineWidth (1);
 
601
                
 
602
                int i, n = (int) ceil ((G_PI/2 - my_fRainbowConeOffset) / (fDelta/180.*G_PI)), N = (2*n+1) * 2;
 
603
                
 
604
                glPushMatrix ();
 
605
                if (! pDock->bHorizontalDock)
 
606
                {
 
607
                        glTranslatef (pDock->iCurrentHeight/2, pDock->iCurrentWidth/2, 0.);
 
608
                        glRotatef (90., 0., 0., 1.);
 
609
                        glTranslatef (0., -pDock->iCurrentHeight/2, 0.);
 
610
                }
 
611
                else
 
612
                        glTranslatef (pDock->iCurrentWidth/2, 0., 0.);
 
613
                if (!pDock->bDirectionUp)
 
614
                {
 
615
                        glTranslatef (0., pDock->iCurrentHeight, 0.);
 
616
                        glScalef (1., -1., 1.);
 
617
                }
 
618
                
 
619
                GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
 
620
                GList *ic = pFirstDrawnElement;
 
621
                Icon *pFirstIcon = pFirstDrawnElement->data;
 
622
                double fCurrentRadius=0;
 
623
                Icon *icon;
 
624
                do
 
625
                {
 
626
                        //if (fRadius > 0)
 
627
                        //      break ;
 
628
                        icon = ic->data;
 
629
                        fRadius = icon->fX - (pDock->bDirectionUp ? pDock->iMaxIconHeight * icon->fScale : 0);
 
630
                        if (fRadius != fCurrentRadius)
 
631
                        {
 
632
                                _generate_sector_path (my_fRainbowConeOffset,
 
633
                                        fRadius + .5 * pDock->iMaxIconHeight * fMaxScale,
 
634
                                        fRadius - my_iSpaceBetweenRows/2,
 
635
                                        
 
636
                                        fDelta/180.*G_PI, pCosSinTab, pVertexTab);
 
637
                                
 
638
                                glVertexPointer(3, GL_FLOAT, 0, pVertexTab);
 
639
                                glColorPointer(4, GL_FLOAT, 0, pColorTab);
 
640
                                glDrawArrays(GL_QUAD_STRIP, 0, N);
 
641
                                
 
642
                                _generate_sector_path (my_fRainbowConeOffset,
 
643
                                        fRadius + .5 * pDock->iMaxIconHeight * fMaxScale,
 
644
                                        fRadius + pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2,
 
645
                                        fDelta/180.*G_PI, pCosSinTab, pVertexTab);
 
646
                                
 
647
                                glVertexPointer(3, GL_FLOAT, 0, pVertexTab);
 
648
                                glColorPointer(4, GL_FLOAT, 0, pColorTab);
 
649
                                glDrawArrays(GL_QUAD_STRIP, 0, N);
 
650
                                
 
651
                                fCurrentRadius = fRadius;
 
652
                        }
 
653
                        ic = cairo_dock_get_next_element (ic, pDock->icons);
 
654
                } while (ic != pFirstDrawnElement);
 
655
                
 
656
                glPopMatrix ();
 
657
                glDisableClientState(GL_VERTEX_ARRAY);
 
658
                glDisableClientState(GL_COLOR_ARRAY);
 
659
                glDisable(GL_POLYGON_SMOOTH);
 
660
                glDisable(GL_BLEND);
 
661
        }
 
662
        
 
663
        //\____________________ On dessine le cadre.
 
664
        if (fRadius == 0)
 
665
        {
 
666
                Icon *icon = cairo_dock_get_last_drawn_icon (pDock);
 
667
                if (icon)
 
668
                        fRadius = icon->fX - (pDock->bDirectionUp ? pDock->iMaxIconHeight * fMaxScale : 0);
 
669
        }
 
670
        fRadius += .5 * pDock->iMaxIconHeight * fMaxScale;
 
671
        if (my_fRainbowLineColor[3] != 0)
 
672
        {
 
673
                glPushMatrix ();
 
674
                if (! pDock->bHorizontalDock)
 
675
                {
 
676
                        glTranslatef (pDock->iCurrentHeight/2, pDock->iCurrentWidth/2, 0.);
 
677
                        glRotatef (90., 0., 0., 1.);
 
678
                        glTranslatef (0., -pDock->iCurrentHeight/2, 0.);
 
679
                }
 
680
                else
 
681
                        glTranslatef (pDock->iCurrentWidth/2, 0., 0.);
 
682
                if (!pDock->bDirectionUp)
 
683
                {
 
684
                        glTranslatef (0., pDock->iCurrentHeight, 0.);
 
685
                        glScalef (1., -1., 1.);
 
686
                }
 
687
                GLfloat color[4*5] = {my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], 0.,
 
688
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], my_fRainbowLineColor[3],
 
689
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], my_fRainbowLineColor[3],
 
690
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], my_fRainbowLineColor[3],
 
691
                my_fRainbowLineColor[0], my_fRainbowLineColor[1], my_fRainbowLineColor[2], 0.};
 
692
                glEnableClientState(GL_COLOR_ARRAY);
 
693
                glColorPointer(4, GL_FLOAT, 0, color);
 
694
                glVertexPointer(3, GL_FLOAT, 0, pVertexTab);
 
695
                
 
696
                pVertexTab[3*0+0] = - (fRadius + .5 * pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2) * pCosSinTab[2*0];
 
697
                pVertexTab[3*0+1] = (fRadius + .5 * pDock->iMaxIconHeight * fMaxScale + my_iSpaceBetweenRows/2) * pCosSinTab[2*0+1];
 
698
                pVertexTab[3*1+0] = - fRadius * cos (my_fRainbowConeOffset);
 
699
                pVertexTab[3*1+1] = fRadius * sin (my_fRainbowConeOffset);
 
700
                pVertexTab[3*2+0] = 0.;
 
701
                pVertexTab[3*2+1] = 0.;
 
702
                pVertexTab[3*3+0] = - pVertexTab[3*1+0];
 
703
                pVertexTab[3*3+1] = pVertexTab[3*1+1];
 
704
                pVertexTab[3*4+0] = - pVertexTab[3*0+0];
 
705
                pVertexTab[3*4+1] = pVertexTab[3*0+1];
 
706
                
 
707
                cairo_dock_draw_current_path_opengl (myBackground.iDockLineWidth, my_fRainbowLineColor, 5);
 
708
                
 
709
                glDisableClientState(GL_COLOR_ARRAY);
 
710
                glPopMatrix ();
 
711
        }
 
712
        
 
713
        //\____________________ On dessine les icones.
 
714
        GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
 
715
        if (pFirstDrawnElement == NULL)
 
716
                return;
 
717
 
 
718
        double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex)/** * pDock->fMagnitudeMax*/;
 
719
        Icon *icon;
 
720
        int iWidth = pDock->iCurrentWidth;
 
721
        gboolean bHorizontalDock = pDock->bHorizontalDock;
 
722
        GList *ic = pFirstDrawnElement;
 
723
        do
 
724
        {
 
725
                icon = ic->data;
 
726
                
 
727
                glPushMatrix ();
 
728
                cairo_dock_render_one_icon_opengl (icon, pDock, fDockMagnitude, TRUE);  // ! mySystem.bTextAlwaysHorizontal
 
729
                glPopMatrix ();
 
730
                
 
731
                ic = cairo_dock_get_next_element (ic, pDock->icons);
 
732
        } while (ic != pFirstDrawnElement);
 
733
}
 
734
 
 
735
 
 
736
void cd_rendering_register_rainbow_renderer (const gchar *cRendererName)
 
737
{
 
738
        CairoDockRenderer *pRenderer = g_new0 (CairoDockRenderer, 1);
 
739
        pRenderer->cReadmeFilePath = g_strdup_printf ("%s/readme-rainbow-view", MY_APPLET_SHARE_DATA_DIR);
 
740
        pRenderer->cPreviewFilePath = g_strdup_printf ("%s/preview-rainbow.jpg", MY_APPLET_SHARE_DATA_DIR);
 
741
        pRenderer->calculate_max_dock_size = cd_rendering_calculate_max_dock_size_rainbow;
 
742
        pRenderer->calculate_icons = cd_rendering_calculate_icons_rainbow;
 
743
        pRenderer->render = cd_rendering_render_rainbow;
 
744
        pRenderer->render_optimized = NULL;
 
745
        pRenderer->render_opengl = cd_rendering_render_rainbow_opengl;
 
746
        pRenderer->set_subdock_position = cairo_dock_set_subdock_position_linear;
 
747
        pRenderer->cDisplayedName = D_ (cRendererName);
 
748
        
 
749
        cairo_dock_register_renderer (cRendererName, pRenderer);
 
750
}