~cairo-dock-team/ubuntu/oneiric/cairo-dock-plug-ins/2.3.0-2.1

1 by Didier Roche
Import upstream version 2.0.8.1
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
On definit une courbe de la forme y = f(x); on decide de prendre
22
    f : x |--> lambda * x ^ alpha.
23
On se ramene a un dock lineaire en passant aux coordonnees curvilignes par la formule :
24
    s = int (0, x, sqrt (1 + f'(x)^2)dx),
25
ce qui nous donne un systeme de 2 equations a 2 inconnnues (x et y)
26
En approximant l'integrale par une somme discrete, on se rend compte qu'on peut re-ecrire le probleme sous la forme d'une equa-diff du 1er ordre.
27
On utilise alors une méthode de Runge-Kutta d'ordre 4, ce qui pour un nombre d'icones N peu eleve donne un tres bon resultat.
28
Pour optimiser le calcul, on remarque par un changement de variable idoine que l'on a la relation :
29
    s_lambda(x) = s_lambda'(c*x) / c, avec c = (lambda / lambda')^(1 / (alpha - 1))
30
ce qui nous permet de calculer une parabole par interpolation lineaire sur une parabole de reference.
31
La vague se rajoute dans un 2eme temps. On cherche a ancrer la 1ere icone en (0,0).
32
Pour se faire, on calcule la position de la crete de la vague par une suite convergente :
33
    sn+1 = vague (sn)
34
La position sur la vague est deduite de la position du curseur par projection normale sur la courbe; on remarque qu'on peut borner s dans un intervalle de largeur moyenne egale a L/2. On procede alors par dichotomie sur ce segment en prolongeant en chaque point suivant grad(f) jusqu'a tomber sur le curseur.
35
Voila pour la petite explication :-)
36
*********************************************************************************/
37
#include <math.h>
38
#include <string.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
42
#include <gtk/gtk.h>
43
44
#include <cairo.h>
45
46
#ifdef HAVE_GLITZ
47
#include <gdk/gdkx.h>
48
#include <glitz-glx.h>
49
#include <cairo-glitz.h>
50
#endif
51
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
52
#include "rendering-commons.h"
53
#include "rendering-parabole.h"
1 by Didier Roche
Import upstream version 2.0.8.1
54
55
extern double my_fParaboleCurvature;  // puissance de x (alpha).
56
extern double my_fParaboleRatio;  // ratio hauteur / largeur fixe => coef de la parabole (lambda).
57
extern double my_fParaboleMagnitude;
58
extern int my_iParaboleTextGap;
59
extern gboolean my_bDrawTextWhileUnfolding;
1.1.3 by Matthieu Baerts (matttbe)
Import upstream version 2.1.3-6
60
extern gboolean my_bParaboleCurveOutside;
1 by Didier Roche
Import upstream version 2.0.8.1
61
62
static double *s_pReferenceParaboleS = NULL;
63
static double *s_pReferenceParaboleX = NULL;
64
static double *s_pReferenceParaboleY = NULL;
65
static double *s_pReferenceParaboleT = NULL;
66
67
#define fCurve(x, lambda, alpha) (lambda * pow (x, alpha))
68
#define fCurve_(x, lambda, alpha) (x != 0 ? lambda * alpha * pow (x, alpha - 1) : (alpha > 1 ? 0 : alpha < 1 ? 1e6 : alpha * lambda))
69
#define fCurveInv(y, lambda, alpha) pow (y / lambda, 1. / alpha)
70
#define fCurveInv_(y, lambda, alpha) (y != 0 ? alpha * y * pow (lambda / y, 1. / alpha) : (alpha > 1 ? 0 : alpha < 1 ? 1e6 : alpha * pow (lambda, 1. / alpha)))
71
72
#define PARABOLE_DISTANCE_OUT2 4900
73
#define PARABOLE_DISTANCE_EDGE2 2500
74
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
75
static void cd_rendering_set_subdock_position_parabole (Icon *pPointedIcon, CairoDock *pDock)
1 by Didier Roche
Import upstream version 2.0.8.1
76
{
77
	CairoDock *pSubDock = pPointedIcon->pSubDock;
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
78
	int iMouseX = pDock->container.iMouseX;
1 by Didier Roche
Import upstream version 2.0.8.1
79
	//int iX = iMouseX + (-iMouseX + pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2) / 2;
80
	int iX = iMouseX;
81
	
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
82
	if ((pDock->container.iWindowPositionX - (pDock->container.bIsHorizontal ? pDock->iScreenOffsetX : pDock->iScreenOffsetY) + pPointedIcon->fDrawX < g_desktopGeometry.iScreenWidth[pDock->container.bIsHorizontal] / 2) ^ my_bParaboleCurveOutside)
1 by Didier Roche
Import upstream version 2.0.8.1
83
	{
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
84
		///iX = iMouseX + MIN (0, -iMouseX + pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2);
85
		iX = pPointedIcon->fDrawX;
86
		if (pSubDock->icons != NULL)
87
		{
88
			Icon *icon = pSubDock->icons->data;
89
			iX += (pPointedIcon->fWidth * pPointedIcon->fScale - icon->fWidth) / 2;
90
		}
1 by Didier Roche
Import upstream version 2.0.8.1
91
		//cd_debug ("recalage : %.2f (%d)\n", -iMouseX + pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2, pSubDock->iMaxLabelWidth);
92
		pSubDock->fAlign = 0;
93
		pSubDock->iGapY = (pDock->iGapY + pDock->iMaxDockHeight);
1.1.3 by Matthieu Baerts (matttbe)
Import upstream version 2.1.3-6
94
		pSubDock->iGapX = iX + pDock->container.iWindowPositionX - (pDock->container.bIsHorizontal ? pDock->iScreenOffsetX : pDock->iScreenOffsetY) - pSubDock->iMaxLabelWidth;
1 by Didier Roche
Import upstream version 2.0.8.1
95
	}
96
	else
97
	{
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
98
		///iX = iMouseX + MAX (0, -iMouseX + pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2);
99
		iX = pPointedIcon->fDrawX;
100
		if (pSubDock->icons != NULL)
101
		{
102
			Icon *icon = pSubDock->icons->data;
103
			iX += icon->fWidth + (pPointedIcon->fWidth * pPointedIcon->fScale - icon->fWidth) / 2;
104
		}
1 by Didier Roche
Import upstream version 2.0.8.1
105
		pSubDock->fAlign = 1;
106
		pSubDock->iGapY = (pDock->iGapY + pDock->iMaxDockHeight);
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
107
		pSubDock->iGapX =  pDock->container.iWindowPositionX - (pDock->container.bIsHorizontal ? pDock->iScreenOffsetX : pDock->iScreenOffsetY) + iX - g_desktopGeometry.iScreenWidth[pDock->container.bIsHorizontal] + pSubDock->iMaxLabelWidth;
108
		
1 by Didier Roche
Import upstream version 2.0.8.1
109
	}
110
	//cd_debug ("pSubDock->iGapY : %d\n", pSubDock->iGapY);
111
}
112
113
114
static void cd_rendering_calculate_next_point (double xn, double yn, double ds, double lambda, double alpha, double *fXNext, double *fYNext, double *fOrientation)
115
{
116
	//g_print ("%s ((%.2f;%.2f), +%.2f\n", __func__, xn, yn, ds);
117
	if (ds <= 0)
118
	{
119
		return ;
120
	}
121
	double k1, k2, k3, k4, k;
122
	double Txn, Tyn, Tn;
123
	double Txnplus1_2, Tynplus1_2, Tnplus1_2, xnplus1_2, ynplus1_2;
124
	double  xnplus1, ynplus1;
125
	
126
	// k1.
127
	k1 = fCurve_ (xn, lambda, alpha);
128
	//g_print ("k1 : %.2f ; ", k1);
129
	
130
	// k2.
131
	Tn = sqrt (1 + k1 * k1);
132
	Txn = 1. / Tn;
133
	Tyn = k1 / Tn;
134
	*fOrientation = atan (Txn / Tyn);
135
	if (k1 > 1)
136
	{
137
		ynplus1_2 = yn + ds/2 * Tyn;
138
		k2 = fCurveInv_ (ynplus1_2, lambda, alpha);
139
	}
140
	else
141
	{
142
		xnplus1_2 = xn + ds/2 * Txn;
143
		k2 =fCurve_ (xnplus1_2, lambda, alpha);
144
	}
145
	//g_print ("k2 : %.2f ; ", k2);
146
	
147
	// k3.
148
	Tnplus1_2 = sqrt (1 + k2 * k2);
149
	if (k2 > 1)
150
	{
151
		Tynplus1_2 = k2 / Tnplus1_2;
152
		ynplus1_2 = yn + ds/2 * Tynplus1_2;
153
		k3 = fCurveInv_ (ynplus1_2, lambda, alpha);
154
	}
155
	else
156
	{
157
		Txnplus1_2 = 1. / Tnplus1_2;
158
		xnplus1_2 = xn + ds/2 * Txnplus1_2;
159
		k3 = fCurve_ (xnplus1_2, lambda, alpha);
160
	}
161
	//g_print ("k3 : %.2f ; ", k3);
162
	
163
	// k4.
164
	Tnplus1_2 = sqrt (1 + k3 * k3);
165
	if (k3 > 1)
166
	{
167
		Tynplus1_2 = k3 / Tnplus1_2;
168
		ynplus1 = yn + ds * Tynplus1_2;
169
		k4 = fCurveInv_ (ynplus1, lambda, alpha);
170
	}
171
	else
172
	{
173
		Txnplus1_2 = 1. / Tnplus1_2;
174
		xnplus1 = xn + ds * Txnplus1_2;
175
		k4 = fCurve_ (xnplus1, lambda, alpha);
176
	}
177
	//g_print ("k4 : %.2f \n", k4);
178
	
179
	// k.
180
	k = 1/(1/k1 + 2 / k2 + 2 / k3 + 1/k4) * 6;
181
	
182
	// (xn+1, yn+1).
183
	Tn = sqrt (1 + k * k);
184
	Txn = 1. / Tn;
185
	Tyn = k / Tn;
186
	*fXNext = xn+ ds * Txn;
187
	*fYNext = yn+ ds * Tyn;
188
	*fOrientation = atan (Txn / Tyn);
189
}
190
191
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
192
static void cd_rendering_calculate_reference_parabole (double alpha)
1 by Didier Roche
Import upstream version 2.0.8.1
193
{
194
	if (s_pReferenceParaboleS == NULL)
195
	{
196
		s_pReferenceParaboleS = g_new (double, RENDERING_INTERPOLATION_NB_PTS);
197
		s_pReferenceParaboleS[0] = 0;
198
	}
199
	
200
	if (s_pReferenceParaboleX == NULL)
201
	{
202
		s_pReferenceParaboleX = g_new (double, RENDERING_INTERPOLATION_NB_PTS);
203
		s_pReferenceParaboleX[0] = 0;
204
	}
205
	
206
	if (s_pReferenceParaboleY == NULL)
207
	{
208
		s_pReferenceParaboleY = g_new (double, RENDERING_INTERPOLATION_NB_PTS);
209
		s_pReferenceParaboleY[0] = 0;
210
	}
211
	
212
	if (s_pReferenceParaboleT == NULL)
213
	{
214
		s_pReferenceParaboleT = g_new (double, RENDERING_INTERPOLATION_NB_PTS);
215
		s_pReferenceParaboleT[0] = 0;
216
	}
217
	
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
218
	double w = g_desktopGeometry.iScreenHeight[CAIRO_DOCK_HORIZONTAL] / my_fParaboleRatio;
1 by Didier Roche
Import upstream version 2.0.8.1
219
	double lambda = my_fParaboleRatio * pow (w, 1 - alpha);
220
	double s=0, ds = 1;
221
	double x = 0, y = 0, theta = 0;
222
	double x_ = 0, y_ = 0, theta_ = G_PI/2 - atan (fCurve_(0, lambda, alpha));
223
	int i;
224
	for (i = 1; i < RENDERING_INTERPOLATION_NB_PTS; i ++)
225
	{
226
		s += ds;
227
		cd_rendering_calculate_next_point (x, y, ds, lambda, alpha, &x_, &y_, &theta_);
228
		//g_print ("ds = %.2f => (%.2f;%.2f), %.2fdeg\n", ds, x_, y_, theta_/G_PI*180);
229
		
230
		x = x_;
231
		y = y_;
232
		theta = theta_;
233
		s_pReferenceParaboleS[i] = s;
234
		s_pReferenceParaboleX[i] = x;
235
		s_pReferenceParaboleY[i] = y;
236
		s_pReferenceParaboleT[i] = theta;
237
		
238
		///s += ds;
239
	}
240
}
241
242
243
double cd_rendering_interpol_curvilign_abscisse (double x, double y, double lambda, double alpha)
244
{
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
245
	double w = g_desktopGeometry.iScreenHeight[CAIRO_DOCK_HORIZONTAL] / my_fParaboleRatio;  // aie, au changement de resolution ...
1 by Didier Roche
Import upstream version 2.0.8.1
246
	double lambda_reference = my_fParaboleRatio * pow (w, 1 - alpha);
247
	//cd_debug ("%s (%.2f / %.2f)\n", __func__, lambda, lambda_reference);
248
	if (my_fParaboleRatio < 1)
249
	{
250
		double coef = pow (lambda / lambda_reference, 1. / (alpha - 1));
251
		//cd_debug (" xcoef : %.2f\n", coef);
252
		return cd_rendering_interpol (x * coef, s_pReferenceParaboleX, s_pReferenceParaboleS) / coef;
253
	}
254
	else
255
	{
256
		double coef = pow (lambda / lambda_reference, - 1. / alpha);
257
		//cd_debug (" ycoef : %.2f\n", coef);
258
		return cd_rendering_interpol (y * coef, s_pReferenceParaboleY, s_pReferenceParaboleS) / coef;
259
	}
260
}
261
262
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
263
static void cd_rendering_calculate_max_dock_size_parabole (CairoDock *pDock)
1 by Didier Roche
Import upstream version 2.0.8.1
264
{
265
	static double fParaboleCurvature= 0;
266
	if (s_pReferenceParaboleS == NULL || my_fParaboleCurvature != fParaboleCurvature)
267
	{
268
		fParaboleCurvature = my_fParaboleCurvature;
269
		cd_rendering_calculate_reference_parabole (my_fParaboleCurvature);
270
	}
271
	
272
	pDock->fMagnitudeMax = my_fParaboleMagnitude;
273
	pDock->pFirstDrawnElement = cairo_dock_calculate_icons_positions_at_rest_linear (pDock->icons, pDock->fFlatDockWidth, pDock->iScrollOffset);
274
	
275
	int iMaxDockWidth = ceil (cairo_dock_calculate_max_dock_width (pDock, pDock->pFirstDrawnElement, pDock->fFlatDockWidth, 1., 0));
276
	GList* ic;
277
	Icon *icon;
278
	pDock->iMaxLabelWidth = 0;
279
	for (ic = pDock->icons; ic != NULL; ic = ic->next)
280
	{
281
		icon = ic->data;
282
		//cd_debug ("  fXAtRest : %.2f; [%.2f;%.2f]", icon->fXAtRest, icon->fXMin, icon->fXMax);
283
		icon->fXMax = icon->fXAtRest + 1e4;
284
		icon->fXMin = icon->fXAtRest - 1e4;
285
		pDock->iMaxLabelWidth = MAX (pDock->iMaxLabelWidth, icon->iTextWidth);
286
	}
287
	//cd_debug ("> iMaxLabelWidth : %d+%d", pDock->iMaxLabelWidth, my_iParaboleTextGap);
288
	pDock->iMaxLabelWidth += my_iParaboleTextGap;
289
	
290
	double alpha = my_fParaboleCurvature, lambda;
291
	double h=0, w=0, h_, w_;
292
	if (my_fParaboleRatio > 1)
293
	{
294
		h_ = iMaxDockWidth;
295
		do
296
		{
297
			h = h_;
298
			w = h / my_fParaboleRatio;
299
			lambda = h / pow (w, alpha);
300
			//cd_debug ("-> %.2fx%.2f , %.2f", w, h, lambda);
301
			
302
			h_ = cd_rendering_interpol (iMaxDockWidth, s_pReferenceParaboleS, s_pReferenceParaboleY);
303
			w_ = h_ / my_fParaboleRatio;
304
		}
305
		while (fabs (h - h_ >2));
306
		
307
		h = h_;
308
		w = w_;
309
		lambda = h / pow (w, alpha);
310
		//cd_debug ("=> %.2fx%.2f , %.2f", w, h, lambda);
311
	}
312
	
1.1.9 by Matthieu Baerts (matttbe)
Import upstream version 2.3.0~1
313
	pDock->iMaxDockHeight = h + pDock->iMaxIconHeight * sqrt (5./4.) * (1 + my_fParaboleMagnitude * myIconsParam.fAmplitude);
314
	pDock->iMaxDockWidth = w + pDock->iMaxIconHeight * (.5+sqrt(5./4.)) * (1 + my_fParaboleMagnitude * myIconsParam.fAmplitude);  // ce serait plutot MaxIconWidth mais bon ...
1 by Didier Roche
Import upstream version 2.0.8.1
315
	
316
	pDock->iMaxDockWidth += pDock->iMaxLabelWidth;  // theta(0) = 0 => texte horizontal.
317
	double fOrientationMax = G_PI/2 - atan (my_fParaboleRatio * my_fParaboleCurvature);  // fCurve_ (W) se simplifie ici.
318
	pDock->iMaxDockHeight += pDock->iMaxLabelWidth * sin (fOrientationMax);  // thetaMax est atteint en x=W.
319
	//cd_debug ("> fOrientationMax : %.2fdeg -> %dx%d", fOrientationMax/G_PI*180., pDock->iMaxDockWidth, pDock->iMaxDockHeight);
320
	
321
	pDock->iDecorationsWidth = 0;
322
	pDock->iDecorationsHeight = 0;
323
	
324
	pDock->iMinDockWidth = pDock->fFlatDockWidth;
325
	pDock->iMinDockHeight = pDock->iMaxIconHeight;
326
}
327
328
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
329
static void cd_rendering_render_parabole (cairo_t *pCairoContext, CairoDock *pDock)
1 by Didier Roche
Import upstream version 2.0.8.1
330
{
331
	//g_print ("pDock->fFoldingFactor : %.2f\n", pDock->fFoldingFactor);
332
	
333
	//\____________________ On trace le cadre.
334
	
335
	//\____________________ On dessine les decorations dedans.
336
	
337
	//\____________________ On dessine le cadre.
338
	
339
	//\____________________ On dessine la ficelle qui les joint.
1.1.9 by Matthieu Baerts (matttbe)
Import upstream version 2.3.0~1
340
	if (myIconsParam.iStringLineWidth > 0)
341
		cairo_dock_draw_string (pCairoContext, pDock, myIconsParam.iStringLineWidth, FALSE, FALSE);
1 by Didier Roche
Import upstream version 2.0.8.1
342
	
343
	
344
	//\____________________ On dessine les icones et leurs etiquettes, mais separement.
345
	GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
346
	if (pFirstDrawnElement == NULL)
347
		return;
348
	
349
	double fDockMagnitude = 1;  // pour le rendu des icones, on utilise la magnitude max.
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
350
	gboolean bHorizontal = pDock->container.bIsHorizontal;
1 by Didier Roche
Import upstream version 2.0.8.1
351
	Icon *icon;
352
	GList *ic = pFirstDrawnElement;
353
	do
354
	{
355
		icon = ic->data;
356
		
357
		cairo_save (pCairoContext);
358
		cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, FALSE);
359
		cairo_restore (pCairoContext);
360
		
361
		if (icon->pTextBuffer != NULL && (my_bDrawTextWhileUnfolding || pDock->fFoldingFactor == 0))
362
		{
363
			cairo_save (pCairoContext);
364
			if (bHorizontal)
365
				cairo_translate (pCairoContext, icon->fDrawX, icon->fDrawY);
366
			else
367
				cairo_translate (pCairoContext, icon->fDrawY, icon->fDrawX);
368
			cairo_rotate (pCairoContext, icon->fOrientation);
369
			if (pDock->fAlign == 1)
370
			{
371
				if (bHorizontal)
372
					cairo_set_source_surface (pCairoContext,
373
						icon->pTextBuffer,
374
						icon->fWidth * icon->fScale + my_iParaboleTextGap,
375
						(icon->fHeight * icon->fScale - icon->iTextHeight)/2);
376
				else
377
				{
378
					cairo_rotate (pCairoContext, G_PI/2);
379
					cairo_set_source_surface (pCairoContext,
380
						icon->pTextBuffer,
381
						icon->fWidth * icon->fScale + my_iParaboleTextGap,
382
						(-icon->fHeight * icon->fScale - icon->iTextHeight)/2);
383
				}
384
			}
385
			else
386
			{
387
				if (bHorizontal)
388
					cairo_set_source_surface (pCairoContext,
389
						icon->pTextBuffer,
390
						- (icon->iTextWidth + my_iParaboleTextGap),
391
						(icon->fHeight * icon->fScale - icon->iTextHeight)/2);
392
				else
393
				{
394
					cairo_rotate (pCairoContext, G_PI/2);
395
					cairo_set_source_surface (pCairoContext,
396
						icon->pTextBuffer,
397
						- (icon->iTextWidth + my_iParaboleTextGap),
398
						(-icon->fHeight * icon->fScale - icon->iTextHeight)/2);
399
				}
400
			}
401
			if (pDock->fFoldingFactor != 0)
402
				cairo_paint_with_alpha (pCairoContext, (1 - pDock->fFoldingFactor) * (1 - pDock->fFoldingFactor));
403
			else
404
				cairo_paint (pCairoContext);
405
			
406
			cairo_restore (pCairoContext);
407
		}
408
		
409
		
410
		ic = cairo_dock_get_next_element (ic, pDock->icons);
411
	} while (ic != pFirstDrawnElement);
412
}
413
414
415
static double cd_rendering_project_cursor_on_curve_x (double x0, double y0, double lambda, double alpha)
416
{
417
	//cd_debug ("%s (%.2f;%.2f)\n", __func__, x0, y0);
418
	if (y0 < 0)
419
		return 0;
420
	double xM, yM;  // M se balade sur la courbe.
421
	double x_inf = 0, x_max = fCurveInv (y0, lambda, alpha), x_sup = x_max;  // bornes de l'intervalle de xM.
422
	double nx, ny=1;  // vecteur normal a la courbe.
423
	double k;  // parametre de la droite normale a la courbe.
424
	double y_;
425
	do
426
	{
427
		xM = (x_inf + x_sup) / 2;
428
		
429
		yM = fCurve (xM, lambda, alpha);
430
		nx = - fCurve_ (xM, lambda, alpha);
431
		
432
		k = (x0 - xM) / nx;
433
		y_ = yM + k;
434
		
435
		if (y_ < y0)
436
		{
437
			x_inf = xM;
438
		}
439
		else
440
		{
441
			x_sup = xM;
442
		}
443
	}
444
	while (x_sup - x_inf > x_max/200);
445
	return (x_inf + x_sup) / 2;
446
}
447
static double cd_rendering_project_cursor_on_curve_y (double x0, double y0, double lambda, double alpha)
448
{
449
	//cd_debug ("%s (%.2f;%.2f ; %.2f ; %.2f)", __func__, x0, y0, lambda, alpha);
450
	if (y0 < 0)
451
		return 0;
452
	double xM, yM;  // M se balade sur la courbe.
453
	double y_inf = 0, y_sup = y0;  // bornes de l'intervalle de xM.
454
	xM = fCurveInv (y0, lambda, alpha);
455
	if (xM < x0)
456
	{
457
		y_inf = y0;
458
		y_sup = fCurve (x0, lambda, alpha);
459
	}
460
	else
461
	{
462
		y_sup = y0;
463
		y_inf = (x0 > 0 ? fCurve (x0, lambda, alpha) : 0);
464
	}
465
	double nx, ny=1;  // verteur normal a la courbe.
466
	double k;  // parametre de la droite normale a la courbe.
467
	double y_;
468
	//cd_debug ("  yM € [%.2f ; %.2f]", y_inf, y_sup);
469
	do
470
	{
471
		yM = (y_inf + y_sup) / 2;
472
		//g_print ("  yM <- %.2f\n", yM);
473
		
474
		xM = fCurveInv (yM, lambda, alpha);
475
		nx = - fCurve_ (xM, lambda, alpha);
476
		
477
		k = (x0 - xM) / nx;
478
		y_ = yM + k;
479
		
480
		if (y_ < y0)
481
		{
482
			y_inf = yM;
483
		}
484
		else
485
		{
486
			y_sup = yM;
487
		}
488
	}
489
	while (y_sup - y_inf > 1);
490
	return (y_inf + y_sup) / 2;
491
}
492
static double cd_rendering_project_cursor_on_curve (double x0, double y0, double lambda, double alpha, double *fXOnCurve, double *fYOnCurve)
493
{
494
	double xM, yM;
495
	if (my_fParaboleRatio > 1)
496
	{
497
		yM = cd_rendering_project_cursor_on_curve_y (x0, y0, lambda, alpha);
498
		xM = fCurveInv (yM, lambda, alpha);
499
	}
500
	else
501
	{
502
		xM = cd_rendering_project_cursor_on_curve_x (x0, y0, lambda, alpha);
503
		yM = fCurve (xM, lambda, alpha);
504
	}
505
	*fXOnCurve = xM;
506
	*fYOnCurve = yM;
507
}
508
509
static double cd_rendering_calculate_wave_position (CairoDock *pDock, double fCurvilignAbscisse, double fMagnitude)
510
{
511
	//cd_debug ("%s (%.2f)", __func__, fCurvilignAbscisse);
512
	
513
	Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
514
	if (pFirstIcon == NULL || fCurvilignAbscisse <= 0)
515
		return 0;
516
	double fWaveOffset, fWaveExtrema;
517
	double x_abs = fCurvilignAbscisse;
518
	int nb_iter = 0;
519
	
520
	do
521
	{
522
		//cd_debug ("  x_abs : %.2f / %.2f", x_abs, pDock->fFlatDockWidth);
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
523
		cairo_dock_calculate_wave_with_position_linear (pDock->icons, pDock->pFirstDrawnElement, x_abs, fMagnitude, pDock->fFlatDockWidth, pDock->fFlatDockWidth, pDock->container.iHeight, 0*pDock->fAlign, pDock->fFoldingFactor, pDock->container.bDirectionUp);
1 by Didier Roche
Import upstream version 2.0.8.1
524
		fWaveOffset = - pFirstIcon->fX;
525
		
526
		fWaveExtrema = fWaveOffset + x_abs;
527
		x_abs += (fCurvilignAbscisse - fWaveExtrema) / 2;
528
		if (x_abs > (int) pDock->fFlatDockWidth + fWaveOffset)
529
		{
530
			x_abs = (int) pDock->fFlatDockWidth;
531
			break ;
532
		}
533
		//cd_debug ("  -> fWaveExtrema : %.2f", fWaveExtrema);
534
		
535
		nb_iter ++;
536
	}
537
	while (fabs (fWaveExtrema - fCurvilignAbscisse) > 1 && nb_iter < 15);
538
	
539
	return x_abs;
540
}
541
542
Icon *cd_rendering_calculate_icons_parabole (CairoDock *pDock)
543
{
544
	if (pDock->icons == NULL)
545
		return NULL;
546
	
547
	//\____________________ On calcule la projection du curseur sur la courbe.
1.1.9 by Matthieu Baerts (matttbe)
Import upstream version 2.3.0~1
548
	double fMaxScale =  1. + my_fParaboleMagnitude * myIconsParam.fAmplitude;
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
549
	double w = MAX (1, pDock->container.iWidth - pDock->iMaxLabelWidth - pDock->iMaxIconHeight * (.5+sqrt(5./4.)) * fMaxScale);
1 by Didier Roche
Import upstream version 2.0.8.1
550
	double h = my_fParaboleRatio * w;
551
	double alpha = my_fParaboleCurvature, lambda = h / pow (w, alpha);
552
	//g_print ("> lambda = %.2f\n", lambda);
553
	double fXOnCurve, fYOnCurve;
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
554
	fXOnCurve = (pDock->fAlign == 0 ? pDock->container.iMouseX - pDock->iMaxLabelWidth - .5*pDock->iMaxIconHeight * fMaxScale : pDock->container.iWidth - pDock->container.iMouseX - pDock->iMaxLabelWidth - .5*pDock->iMaxIconHeight * fMaxScale);
555
	fYOnCurve = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->container.iMouseY : pDock->container.iMouseY);
556
	//cd_debug (" mouse : %d;%d", pDock->container.iMouseX, pDock->container.iMouseY);
1 by Didier Roche
Import upstream version 2.0.8.1
557
	cd_rendering_project_cursor_on_curve (fXOnCurve, fYOnCurve, lambda, alpha, &fXOnCurve, &fYOnCurve);
558
	//cd_debug (" on curve : %.2f;%.2f", fXOnCurve, fYOnCurve);
559
	
560
	double fCurvilignAbscisse = cd_rendering_interpol_curvilign_abscisse (fXOnCurve, fYOnCurve, lambda, alpha);
561
	//cd_debug ("  fCurvilignAbscisse : %.2f", fCurvilignAbscisse);
562
	
563
	if (pDock->fAlign == 0)
564
	{
565
		fXOnCurve = fXOnCurve + pDock->iMaxLabelWidth + .5*pDock->iMaxIconHeight * fMaxScale;
566
	}
567
	else
568
	{
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
569
		fXOnCurve = pDock->container.iWidth - fXOnCurve - pDock->iMaxLabelWidth - .5*pDock->iMaxIconHeight * fMaxScale;
1 by Didier Roche
Import upstream version 2.0.8.1
570
	}
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
571
	fYOnCurve = pDock->container.iHeight - fYOnCurve;
572
	//cd_debug (" => %.2f;%.2f (%d ; %d)", fXOnCurve, fYOnCurve, pDock->container.iMouseX, pDock->container.iMouseY);
1 by Didier Roche
Import upstream version 2.0.8.1
573
	
574
	//\____________________ On en deduit ou appliquer la vague pour que la crete soit a la position du curseur sur la courbe.
575
	Icon *pPointedIcon = NULL;
576
	double fMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex) * pDock->fMagnitudeMax;
577
	//int x_abs = fCurvilignAbscisse;  // ecart par rapport a la gauche du dock minimal  plat.
578
	int x_abs = (int) round (cd_rendering_calculate_wave_position (pDock, fCurvilignAbscisse, fMagnitude));
579
	//cd_debug (" => x_abs : %d (fMagnitude:%.2f ; fFoldingFactor:%.2f)", x_abs, fMagnitude, pDock->fFoldingFactor);
580
	
581
	//\_______________ On en deduit l'ensemble des parametres des icones.
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
582
	pPointedIcon = cairo_dock_calculate_wave_with_position_linear (pDock->icons, pDock->pFirstDrawnElement, x_abs, fMagnitude, (int) pDock->fFlatDockWidth, (int) pDock->fFlatDockWidth, pDock->container.iHeight, 0*pDock->fAlign, pDock->fFoldingFactor, pDock->container.bDirectionUp);
583
	//cd_debug (" => pPointedIcon : %s; %.2f", pPointedIcon->cName, pPointedIcon->fX);
1 by Didier Roche
Import upstream version 2.0.8.1
584
	
585
	
586
	//\____________________ On en deduit les position/etirements/alpha des icones.
587
	Icon* icon, *prev_icon;
588
	GList* ic;
589
	double ds, s=0;
590
	double x = 0, y = 0, theta = 0;
591
	double x_ = 0, y_ = 0, theta_ = G_PI/2 - atan (fCurve_(0, lambda, alpha));
592
	if (pDock->fAlign == 1)
593
		theta_ = -theta_;
594
	//g_print ("theta_ : %.2fdeg\n", theta_);
595
	
596
	GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
597
	ic = pFirstDrawnElement;
598
	Icon *pFirstIcon = pFirstDrawnElement->data;
599
	double fOrientationMax = G_PI/2 - atan (my_fParaboleRatio * my_fParaboleCurvature);
600
	double fTopMargin = pDock->iMaxLabelWidth * sin (fOrientationMax);
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
601
	gboolean bHorizontal = pDock->container.bIsHorizontal;
1 by Didier Roche
Import upstream version 2.0.8.1
602
	do
603
	{
604
		icon = ic->data;
605
		
606
		if (ic != pFirstDrawnElement)  // on ancre la 1ere icone a l'origine.
607
		{
608
			ds = icon->fX - prev_icon->fX;
609
			s = icon->fX - pFirstIcon->fX;
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
610
			//g_print (" %s : %.2f + %.2f (x %.2f)\n", icon->cName, s, ds, icon->fScale);
1 by Didier Roche
Import upstream version 2.0.8.1
611
			y_ = cd_rendering_interpol (s, s_pReferenceParaboleS, s_pReferenceParaboleY);
612
			x_ = fCurveInv (y_, lambda, alpha);
613
			theta_ = G_PI/2 - atan (fCurve_(x_, lambda, alpha));
614
		}
615
		
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
616
		icon->fDrawY = (pDock->container.bDirectionUp ? pDock->container.iHeight - (y_ + icon->fHeight * icon->fScale) * (1 - pDock->fFoldingFactor) : y_ * (1 - pDock->fFoldingFactor));
1 by Didier Roche
Import upstream version 2.0.8.1
617
		if (pDock->fAlign == 1)
618
		{
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
619
			icon->fDrawX = pDock->container.iWidth - (x_ + pDock->iMaxLabelWidth + .5 * pDock->iMaxIconHeight * fMaxScale + icon->fWidth * icon->fScale/2);
1 by Didier Roche
Import upstream version 2.0.8.1
620
			if (bHorizontal)
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
621
				icon->fOrientation = (pDock->container.bDirectionUp ? - theta_ : theta_);
1 by Didier Roche
Import upstream version 2.0.8.1
622
			else
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
623
				icon->fOrientation = (pDock->container.bDirectionUp ? theta_ : - theta_);
1 by Didier Roche
Import upstream version 2.0.8.1
624
		}
625
		else
626
		{
627
			icon->fDrawX = x_ + pDock->iMaxLabelWidth + .5 * pDock->iMaxIconHeight * fMaxScale - icon->fWidth * icon->fScale/2;
628
			if (bHorizontal)
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
629
				icon->fOrientation = (pDock->container.bDirectionUp ? theta_ : - theta_);
1 by Didier Roche
Import upstream version 2.0.8.1
630
			else
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
631
				icon->fOrientation = (pDock->container.bDirectionUp ? - theta_ : theta_);
1 by Didier Roche
Import upstream version 2.0.8.1
632
		}
633
		icon->fAlpha = 1;
634
		icon->fWidthFactor = 1.;
635
		icon->fHeightFactor = 1.;
636
		
637
		x = x_;
638
		y = y_;
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
639
		//g_print (" %s : (%.2f ; %.2f)\n", icon->cName, x, y);
1 by Didier Roche
Import upstream version 2.0.8.1
640
		theta = theta_;
641
		prev_icon = icon;
642
		
643
		ic = cairo_dock_get_next_element (ic, pDock->icons);
644
	} while (ic != pFirstDrawnElement);
645
	
646
	//cd_debug ("  derniere icone : %.2f (s:%.2f)", icon->fX + icon->fHeight * icon->fScale - pFirstIcon->fX, fCurvilignAbscisse);
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
647
	if (! pDock->container.bInside || fCurvilignAbscisse > icon->fX + icon->fHeight * icon->fScale - pFirstIcon->fX - (pDock->fFoldingFactor > 0 ? 20 : -30) || fCurvilignAbscisse <= 0)  // on laisse 30 pixels de rab pour ne pas etre trop sensible a l'extremite du dock.
1 by Didier Roche
Import upstream version 2.0.8.1
648
	{
649
		//cd_debug ("<<< on sort de la parabole >>>");
650
		pDock->iMousePositionType = CAIRO_DOCK_MOUSE_OUTSIDE;
651
	}
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
652
	else if ((pDock->fAlign == 0 && pDock->container.iMouseX > fXOnCurve) || (pDock->fAlign == 1 && pDock->container.iMouseX < fXOnCurve))
1 by Didier Roche
Import upstream version 2.0.8.1
653
	{
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
654
		int iMouseY = (pDock->container.bDirectionUp ? pDock->container.iMouseY : pDock->container.iHeight - pDock->container.iMouseY);
655
		double fDistanceToCurve2 = (fXOnCurve - pDock->container.iMouseX) * (fXOnCurve - pDock->container.iMouseX) + (fYOnCurve - iMouseY) * (fYOnCurve - iMouseY);
1 by Didier Roche
Import upstream version 2.0.8.1
656
		if (fDistanceToCurve2 > PARABOLE_DISTANCE_OUT2)
657
			pDock->iMousePositionType = CAIRO_DOCK_MOUSE_OUTSIDE;
658
		else if (fDistanceToCurve2 < PARABOLE_DISTANCE_EDGE2)
659
			pDock->iMousePositionType = CAIRO_DOCK_MOUSE_INSIDE;
660
		else
661
			pDock->iMousePositionType = CAIRO_DOCK_MOUSE_ON_THE_EDGE;
662
	}
663
	else
664
	{
665
		pDock->iMousePositionType = CAIRO_DOCK_MOUSE_INSIDE;
666
	}
667
	
668
	cairo_dock_check_can_drop_linear (pDock);  /// marche ?...
669
	
670
	return pPointedIcon;
671
}
672
673
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
674
static void cd_rendering_render_parabole_opengl (CairoDock *pDock)
1 by Didier Roche
Import upstream version 2.0.8.1
675
{
676
	//g_print ("pDock->fFoldingFactor : %.2f\n", pDock->fFoldingFactor);
677
	
678
	//\____________________ On trace le cadre.
679
	
680
	//\____________________ On dessine les decorations dedans.
681
	
682
	//\____________________ On dessine le cadre.
683
	
684
	//\____________________ On dessine la ficelle qui les joint.
1.1.9 by Matthieu Baerts (matttbe)
Import upstream version 2.3.0~1
685
	if (myIconsParam.iStringLineWidth > 0)
686
		cairo_dock_draw_string_opengl (pDock, myIconsParam.iStringLineWidth, FALSE, FALSE);
1 by Didier Roche
Import upstream version 2.0.8.1
687
	
688
	//\____________________ On dessine les icones et leurs etiquettes, mais separement.
689
	GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
690
	if (pFirstDrawnElement == NULL)
691
		return;
692
	
693
	glPushMatrix ();
694
	double fDockMagnitude = 1;  // pour le rendu des icones, on utilise la magnitude max.
1.1.2 by Julien Lavergne
Import upstream version 2.0.9
695
	gboolean bHorizontal = pDock->container.bIsHorizontal;
1 by Didier Roche
Import upstream version 2.0.8.1
696
	Icon *icon;
697
	GList *ic = pFirstDrawnElement;
698
	do
699
	{
700
		icon = ic->data;
701
		
1.1.3 by Matthieu Baerts (matttbe)
Import upstream version 2.1.3-6
702
		cairo_dock_render_one_icon_opengl (icon, pDock, fDockMagnitude, FALSE);
1 by Didier Roche
Import upstream version 2.0.8.1
703
		
1.1.9 by Matthieu Baerts (matttbe)
Import upstream version 2.3.0~1
704
		if (icon->iLabelTexture != 0)  // en opengl on dessine les etiquettes meme pendant le depliage.
1 by Didier Roche
Import upstream version 2.0.8.1
705
		{
1.1.3 by Matthieu Baerts (matttbe)
Import upstream version 2.1.3-6
706
			glPushMatrix ();
707
			cairo_dock_translate_on_icon_opengl (icon, CAIRO_CONTAINER (pDock), 1.);
708
			
1 by Didier Roche
Import upstream version 2.0.8.1
709
			glTranslatef (-icon->fWidth * icon->fScale/2, icon->fHeight * icon->fScale/2, 0.);
710
			glRotatef (-icon->fOrientation/G_PI*180., 0., 0., 1.);
711
			glTranslatef (icon->fWidth * icon->fScale/2, -icon->fHeight * icon->fScale/2, 0.);
712
			
713
			_cairo_dock_enable_texture ();
1.1.9 by Matthieu Baerts (matttbe)
Import upstream version 2.3.0~1
714
			///_cairo_dock_set_blend_over ();
715
			_cairo_dock_set_blend_alpha ();
1 by Didier Roche
Import upstream version 2.0.8.1
716
			_cairo_dock_set_alpha ((1 - pDock->fFoldingFactor) * (1 - pDock->fFoldingFactor));
717
			
718
			if (pDock->fAlign == 1)
719
			{
720
				if (bHorizontal)
721
				{
722
					glTranslatef (icon->fWidth * icon->fScale/2 + my_iParaboleTextGap + icon->iTextWidth/2,
723
						0.,
724
						0.);
725
				}
726
				else
727
				{
728
					glRotatef (-90., 0., 0., 1.);
729
					glTranslatef (icon->fWidth * icon->fScale/2 + my_iParaboleTextGap + icon->iTextWidth/2,
730
						0.,
731
						0.);
732
				}
733
			}
734
			else
735
			{
736
				if (bHorizontal)
737
				{
738
					glTranslatef (- (icon->fWidth * icon->fScale/2 + my_iParaboleTextGap + icon->iTextWidth/2),
739
						0.,
740
						0.);
741
				}
742
				else
743
				{
744
					glRotatef (-90., 0., 0., 1.);
745
					glTranslatef (- (icon->fWidth * icon->fScale/2 + my_iParaboleTextGap + icon->iTextWidth/2),
746
						0.,
747
						0.);
748
				}
749
			}
750
			cairo_dock_apply_texture_at_size (icon->iLabelTexture,
751
				icon->iTextWidth,
752
				icon->iTextHeight);
753
			
754
			_cairo_dock_disable_texture ();
1.1.3 by Matthieu Baerts (matttbe)
Import upstream version 2.1.3-6
755
			glPopMatrix ();
1 by Didier Roche
Import upstream version 2.0.8.1
756
		}
757
		
758
		ic = cairo_dock_get_next_element (ic, pDock->icons);
759
	} while (ic != pFirstDrawnElement);
760
	glPopMatrix ();
761
}
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
762
763
764
void cd_rendering_register_parabole_renderer (const gchar *cRendererName)
765
{
766
	CairoDockRenderer *pRenderer = g_new0 (CairoDockRenderer, 1);
1.1.6 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0rc1
767
	// interface
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
768
	pRenderer->compute_size = cd_rendering_calculate_max_dock_size_parabole;
769
	pRenderer->calculate_icons = cd_rendering_calculate_icons_parabole;
770
	pRenderer->render = cd_rendering_render_parabole;
771
	pRenderer->render_optimized = NULL;
772
	pRenderer->render_opengl = cd_rendering_render_parabole_opengl;
773
	pRenderer->set_subdock_position = cd_rendering_set_subdock_position_parabole;
1.1.6 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0rc1
774
	// parametres
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
775
	pRenderer->cDisplayedName = D_ (cRendererName);
1.1.6 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0rc1
776
	pRenderer->cReadmeFilePath = g_strdup (MY_APPLET_SHARE_DATA_DIR"/readme-parabolic-view");
777
	pRenderer->cPreviewFilePath = g_strdup (MY_APPLET_SHARE_DATA_DIR"/preview-parabolic.jpg");
1.1.5 by Matthieu Baerts (matttbe)
Import upstream version 2.2.0~0beta4
778
	
779
	cairo_dock_register_renderer (cRendererName, pRenderer);
780
}