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 <math.h>
21 #include <GL/gl.h>
22 
23 #include "cairo-dock-struct.h"
24 #include "cairo-dock-icon-facility.h"  // cairo_dock_generate_string_path_opengl
25 #include "cairo-dock-dock-factory.h"
26 #include "cairo-dock-separator-manager.h"
27 #include "cairo-dock-opengl-path.h"
28 
29 #define _CD_PATH_DIM 2
30 #define _cd_gl_path_set_nth_vertex_x(pPath, _x, i) pPath->pVertices[_CD_PATH_DIM*(i)] = _x
31 #define _cd_gl_path_set_nth_vertex_y(pPath, _y, i) pPath->pVertices[_CD_PATH_DIM*(i)+1] = _y
32 #define _cd_gl_path_set_vertex_x(pPath, _x) _cd_gl_path_set_nth_vertex_x (pPath, _x, pPath->iCurrentPt)
33 #define _cd_gl_path_set_vertex_y(pPath, _y) _cd_gl_path_set_nth_vertex_y (pPath, _y, pPath->iCurrentPt)
34 #define _cd_gl_path_set_current_vertex(pPath, _x, _y) do {\
35 	_cd_gl_path_set_vertex_x(pPath, _x);\
36 	_cd_gl_path_set_vertex_y(pPath, _y); } while (0)
37 #define _cd_gl_path_get_nth_vertex_x(pPath, i) pPath->pVertices[_CD_PATH_DIM*(i)]
38 #define _cd_gl_path_get_nth_vertex_y(pPath, i) pPath->pVertices[_CD_PATH_DIM*(i)+1]
39 #define _cd_gl_path_get_current_vertex_x(pPath) _cd_gl_path_get_nth_vertex_x (pPath, pPath->iCurrentPt-1)
40 #define _cd_gl_path_get_current_vertex_y(pPath) _cd_gl_path_get_nth_vertex_y (pPath, pPath->iCurrentPt-1)
41 
cairo_dock_new_gl_path(int iNbVertices,double x0,double y0,int iWidth,int iHeight)42 CairoDockGLPath *cairo_dock_new_gl_path (int iNbVertices, double x0, double y0, int iWidth, int iHeight)
43 {
44 	CairoDockGLPath *pPath = g_new0 (CairoDockGLPath, 1);
45 	pPath->pVertices = g_new0 (GLfloat, (iNbVertices+1) * _CD_PATH_DIM);  // +1 = securite
46 	pPath->iNbPoints = iNbVertices;
47 	_cd_gl_path_set_current_vertex (pPath, x0, y0);
48 	pPath->iCurrentPt ++;
49 	pPath->iWidth = iWidth;
50 	pPath->iHeight = iHeight;
51 	return pPath;
52 }
53 
cairo_dock_free_gl_path(CairoDockGLPath * pPath)54 void cairo_dock_free_gl_path (CairoDockGLPath *pPath)
55 {
56 	if (!pPath)
57 		return;
58 	g_free (pPath->pVertices);
59 	g_free (pPath);
60 }
61 
cairo_dock_gl_path_move_to(CairoDockGLPath * pPath,double x0,double y0)62 void cairo_dock_gl_path_move_to (CairoDockGLPath *pPath, double x0, double y0)
63 {
64 	pPath->iCurrentPt = 0;
65 	_cd_gl_path_set_current_vertex (pPath, x0, y0);
66 	pPath->iCurrentPt ++;
67 }
68 
cairo_dock_gl_path_set_extent(CairoDockGLPath * pPath,int iWidth,int iHeight)69 void cairo_dock_gl_path_set_extent (CairoDockGLPath *pPath, int iWidth, int iHeight)
70 {
71 	pPath->iWidth = iWidth;
72 	pPath->iHeight = iHeight;
73 }
74 
cairo_dock_gl_path_line_to(CairoDockGLPath * pPath,GLfloat x,GLfloat y)75 void cairo_dock_gl_path_line_to (CairoDockGLPath *pPath, GLfloat x, GLfloat y)
76 {
77 	g_return_if_fail (pPath->iCurrentPt < pPath->iNbPoints);
78 	_cd_gl_path_set_current_vertex (pPath, x, y);
79 	pPath->iCurrentPt ++;
80 }
81 
cairo_dock_gl_path_rel_line_to(CairoDockGLPath * pPath,GLfloat dx,GLfloat dy)82 void cairo_dock_gl_path_rel_line_to (CairoDockGLPath *pPath, GLfloat dx, GLfloat dy)
83 {
84 	cairo_dock_gl_path_line_to (pPath,
85 		_cd_gl_path_get_current_vertex_x (pPath) + dx,
86 		_cd_gl_path_get_current_vertex_y (pPath) + dy);
87 }
88 
89 // OM(t) = sum ([k=0..n] Bn,k(t)*OAk)
90 // Bn,k(x) = Cn,k*x^k*(1-x)^(n-k)
91 #define B0(t) (1-t)*(1-t)*(1-t)
92 #define B1(t) 3*t*(1-t)*(1-t)
93 #define B2(t) 3*t*t*(1-t)
94 #define B3(t) t*t*t
95 #define Bezier(x0,x1,x2,x3,t) (B0(t)*x0 + B1(t)*x1 + B2(t)*x2 + B3(t)*x3)
cairo_dock_gl_path_curve_to(CairoDockGLPath * pPath,int iNbPoints,GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat x3,GLfloat y3)96 void cairo_dock_gl_path_curve_to (CairoDockGLPath *pPath, int iNbPoints, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3)
97 {
98 	g_return_if_fail (pPath->iCurrentPt + iNbPoints <= pPath->iNbPoints);
99 	GLfloat x0, y0;
100 	x0 = _cd_gl_path_get_current_vertex_x (pPath);
101 	y0 = _cd_gl_path_get_current_vertex_y (pPath);
102 	double t;
103 	int i;
104 	for (i = 0; i < iNbPoints; i ++)
105 	{
106 		t = (double)(i+1)/iNbPoints;  // [0;1]
107 		_cd_gl_path_set_nth_vertex_x (pPath, Bezier (x0, x1, x2, x3, t), pPath->iCurrentPt + i);
108 		_cd_gl_path_set_nth_vertex_y (pPath, Bezier (y0, y1, y2, y3, t), pPath->iCurrentPt + i);
109 	}
110 	pPath->iCurrentPt += iNbPoints;
111 }
112 
cairo_dock_gl_path_rel_curve_to(CairoDockGLPath * pPath,int iNbPoints,GLfloat dx1,GLfloat dy1,GLfloat dx2,GLfloat dy2,GLfloat dx3,GLfloat dy3)113 void cairo_dock_gl_path_rel_curve_to (CairoDockGLPath *pPath, int iNbPoints, GLfloat dx1, GLfloat dy1, GLfloat dx2, GLfloat dy2, GLfloat dx3, GLfloat dy3)
114 {
115 	GLfloat x0, y0;
116 	x0 = _cd_gl_path_get_current_vertex_x (pPath);
117 	y0 = _cd_gl_path_get_current_vertex_y (pPath);
118 	cairo_dock_gl_path_curve_to (pPath, iNbPoints, x0 + dx1, y0 + dy1, x0 + dx2, y0 + dy2, x0 + dx3, y0 + dy3);
119 }
120 
121 #define Bezier2(p,q,s,t) ((1-t) * (1-t) * p + 2 * t * (1-t) * q + t * t * s)
cairo_dock_gl_path_simple_curve_to(CairoDockGLPath * pPath,int iNbPoints,GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)122 void cairo_dock_gl_path_simple_curve_to (CairoDockGLPath *pPath, int iNbPoints, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
123 {
124 	g_return_if_fail (pPath->iCurrentPt + iNbPoints <= pPath->iNbPoints);
125 	GLfloat x0, y0;
126 	x0 = _cd_gl_path_get_current_vertex_x (pPath);
127 	y0 = _cd_gl_path_get_current_vertex_y (pPath);
128 	double t;
129 	int i;
130 	for (i = 0; i < iNbPoints; i ++)
131 	{
132 		t = (double)(i+1)/iNbPoints;  // [0;1]
133 		_cd_gl_path_set_nth_vertex_x (pPath, Bezier2 (x0, x1, x2, t), pPath->iCurrentPt + i);
134 		_cd_gl_path_set_nth_vertex_y (pPath, Bezier2 (y0, y1, y2, t), pPath->iCurrentPt + i);
135 	}
136 	pPath->iCurrentPt += iNbPoints;
137 }
138 
cairo_dock_gl_path_rel_simple_curve_to(CairoDockGLPath * pPath,int iNbPoints,GLfloat dx1,GLfloat dy1,GLfloat dx2,GLfloat dy2)139 void cairo_dock_gl_path_rel_simple_curve_to (CairoDockGLPath *pPath, int iNbPoints, GLfloat dx1, GLfloat dy1, GLfloat dx2, GLfloat dy2)
140 {
141 	GLfloat x0, y0;
142 	x0 = _cd_gl_path_get_current_vertex_x (pPath);
143 	y0 = _cd_gl_path_get_current_vertex_y (pPath);
144 	cairo_dock_gl_path_simple_curve_to (pPath, iNbPoints, x0 + dx1, y0 + dy1, x0 + dx2, y0 + dy2);
145 }
146 
cairo_dock_gl_path_arc(CairoDockGLPath * pPath,int iNbPoints,GLfloat xc,GLfloat yc,double r,double teta0,double cone)147 void cairo_dock_gl_path_arc (CairoDockGLPath *pPath, int iNbPoints, GLfloat xc, GLfloat yc, double r, double teta0, double cone)
148 {
149 	g_return_if_fail (pPath->iCurrentPt + iNbPoints <= pPath->iNbPoints);
150 	double t;
151 	int i;
152 	for (i = 0; i < iNbPoints; i ++)
153 	{
154 		t = teta0 + (double)i/(iNbPoints-1) * cone;  // [teta0, teta0+cone]
155 		_cd_gl_path_set_nth_vertex_x (pPath, xc + r * cos (t), pPath->iCurrentPt + i);
156 		_cd_gl_path_set_nth_vertex_y (pPath, yc + r * sin (t), pPath->iCurrentPt + i);
157 	}
158 	pPath->iCurrentPt += iNbPoints;
159 }
160 
_draw_current_path(int iNbPoints,gboolean bClosePath)161 static inline void _draw_current_path (int iNbPoints, gboolean bClosePath)
162 {
163 	//\__________________ On active l'antialiasing.
164 	glPolygonMode (GL_FRONT, GL_LINE);
165 	glEnable (GL_LINE_SMOOTH);
166 	glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
167 	glEnable (GL_BLEND);  // On active le blend pour l'antialiasing.
168 	//glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
169 	//glLineWidth(fLineWidth);
170 	//glColor4f (fLineColor[0], fLineColor[1], fLineColor[2], fLineColor[3]); // Et sa couleur.
171 
172 	//\__________________ On dessine le cadre.
173 	glEnableClientState (GL_VERTEX_ARRAY);
174 	glDrawArrays (bClosePath ? GL_LINE_LOOP : GL_LINE_STRIP, 0, iNbPoints);
175 	glDisableClientState (GL_VERTEX_ARRAY);
176 
177 	//\__________________ On desactive l'antialiasing.
178 	glDisable (GL_LINE_SMOOTH);
179 	glDisable (GL_BLEND);
180 }
cairo_dock_stroke_gl_path(const CairoDockGLPath * pPath,gboolean bClosePath)181 void cairo_dock_stroke_gl_path (const CairoDockGLPath *pPath, gboolean bClosePath)
182 {
183 	glVertexPointer (_CD_PATH_DIM, GL_FLOAT, 0, pPath->pVertices);
184 	_draw_current_path (pPath->iCurrentPt, bClosePath);
185 }
186 
cairo_dock_fill_gl_path(const CairoDockGLPath * pPath,GLuint iTexture)187 void cairo_dock_fill_gl_path (const CairoDockGLPath *pPath, GLuint iTexture)
188 {
189 	//\__________________ On active l'antialiasing.
190 	glPolygonMode (GL_FRONT, GL_FILL);
191 	//glEnable (GL_POLYGON_SMOOTH);  // makes horrible white lines where the triangles overlaps :-/
192 	//glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
193 	glEnable (GL_BLEND);  // On active le blend pour l'antialiasing.
194 
195 	//\__________________ On mappe la texture dans le cadre.
196 	if (iTexture != 0)
197 	{
198 		// on active le texturing.
199 		glColor4f(1., 1., 1., 1.); // Couleur a fond
200 		glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
201 		glEnable(GL_TEXTURE_2D); // Je veux de la texture
202 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
203 		glBindTexture(GL_TEXTURE_2D, iTexture); // allez on bind la texture
204 		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR ); // ok la on selectionne le type de generation des coordonnees de la texture
205 		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
206 		glEnable(GL_TEXTURE_GEN_S); // oui je veux une generation en S
207 		glEnable(GL_TEXTURE_GEN_T); // Et en T aussi
208 		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
209 		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
210 
211 		// on met la texture a sa place.
212 		glMatrixMode(GL_TEXTURE);
213 		glPushMatrix ();
214 		glTranslatef (.5, .5, 0.);
215 		if (pPath->iWidth != 0 && pPath->iHeight != 0)
216 			glScalef (1./pPath->iWidth, -1./pPath->iHeight, 1.);
217 		glMatrixMode (GL_MODELVIEW);
218 
219 	}
220 
221 	//\__________________ On dessine le cadre.
222 	glEnableClientState (GL_VERTEX_ARRAY);
223 	glVertexPointer (_CD_PATH_DIM, GL_FLOAT, 0, pPath->pVertices);
224 	glDrawArrays (GL_TRIANGLE_FAN, 0, pPath->iCurrentPt);  // GL_POLYGON / GL_TRIANGLE_FAN
225 	glDisableClientState (GL_VERTEX_ARRAY);
226 
227 	//\__________________ On desactive l'antialiasing et la texture.
228 	if (iTexture != 0)
229 	{
230 		glDisable(GL_TEXTURE_GEN_S);
231 		glDisable(GL_TEXTURE_GEN_T);
232 		glDisable(GL_TEXTURE_2D); // Plus de texture merci
233 
234 		glMatrixMode(GL_TEXTURE);
235 		glPopMatrix ();
236 		glMatrixMode (GL_MODELVIEW);
237 	}
238 	//glDisable (GL_POLYGON_SMOOTH);
239 	glDisable (GL_BLEND);
240 }
241 
242 
243 // HELPER FUNCTIONS //
244 
245 #define DELTA_ROUND_DEGREE 3
cairo_dock_generate_rectangle_path(double fFrameWidth,double fTotalHeight,double fRadius,gboolean bRoundedBottomCorner)246 const CairoDockGLPath *cairo_dock_generate_rectangle_path (double fFrameWidth, double fTotalHeight, double fRadius, gboolean bRoundedBottomCorner)
247 {
248 	static CairoDockGLPath *pPath = NULL;
249 	double fTotalWidth = fFrameWidth + 2 * fRadius;
250 	double fFrameHeight = MAX (0, fTotalHeight - 2 * fRadius);
251 	double w = fFrameWidth / 2;
252 	double h = fFrameHeight / 2;
253 	double r = fRadius;
254 
255 	int iNbPoins1Round = 90/10;
256 	if (pPath == NULL)
257 	{
258 		pPath = cairo_dock_new_gl_path ((iNbPoins1Round+1)*4+1, w+r, h, fTotalWidth, fTotalHeight);  // on commence au centre droit pour avoir une bonne triangulation du polygone, et en raisonnant par rapport au centre du rectangle.
259 		///pPath = cairo_dock_new_gl_path ((iNbPoins1Round+1)*4+1, 0, 0, fTotalWidth, fTotalHeight);  // on commence au centre pour avoir une bonne triangulation
260 	}
261 	else
262 	{
263 		cairo_dock_gl_path_move_to (pPath, w+r, h);
264 		///cairo_dock_gl_path_move_to (pPath, 0, 0);
265 		cairo_dock_gl_path_set_extent (pPath, fTotalWidth, fTotalHeight);
266 	}
267 	//cairo_dock_gl_path_move_to (pPath, 0., h+r);
268 	//cairo_dock_gl_path_rel_line_to (pPath, -w, 0.);
269 
270 	cairo_dock_gl_path_arc (pPath, iNbPoins1Round, w, h, r, 0.,     +G_PI/2);  // coin haut droit.
271 
272 	cairo_dock_gl_path_arc (pPath, iNbPoins1Round, -w,  h, r, G_PI/2,  +G_PI/2);  // coin haut gauche.
273 
274 	if (bRoundedBottomCorner)
275 	{
276 		cairo_dock_gl_path_arc (pPath, iNbPoins1Round, -w, -h, r, G_PI,    +G_PI/2);  // coin bas gauche.
277 
278 		cairo_dock_gl_path_arc (pPath, iNbPoins1Round,  w, -h, r, -G_PI/2, +G_PI/2);  // coin bas droit.
279 	}
280 	else
281 	{
282 		cairo_dock_gl_path_rel_line_to (pPath, 0., - (fFrameHeight + r));
283 		cairo_dock_gl_path_rel_line_to (pPath, fTotalWidth, 0.);
284 	}
285 	//cairo_dock_gl_path_arc (pPath, iNbPoins1Round, w, h, r, 0.,     +G_PI/2);  // coin haut droit.
286 
287 	return pPath;
288 }
289 
290 
cairo_dock_generate_trapeze_path(double fUpperFrameWidth,double fTotalHeight,double fRadius,gboolean bRoundedBottomCorner,double fInclination,double * fExtraWidth)291 const CairoDockGLPath *cairo_dock_generate_trapeze_path (double fUpperFrameWidth, double fTotalHeight, double fRadius, gboolean bRoundedBottomCorner, double fInclination, double *fExtraWidth)
292 {
293 	static CairoDockGLPath *pPath = NULL;
294 
295 	double a = atan (fInclination);  // /|
296 	double cosa = 1. / sqrt (1 + fInclination * fInclination);
297 	double sina = cosa * fInclination;
298 
299 	double fFrameHeight = MAX (0, fTotalHeight - 2 * fRadius);
300 	*fExtraWidth = fInclination * (fTotalHeight - (bRoundedBottomCorner ? 2 : 1-sina) * fRadius) + fRadius * (bRoundedBottomCorner ? 1 : cosa);
301 	double fTotalWidth = fUpperFrameWidth + 2*(*fExtraWidth);
302 	double dw = *fExtraWidth;
303 	double r = fRadius;
304 	double w = fUpperFrameWidth / 2;
305 	double h = fFrameHeight / 2;
306 	double w_ = w + dw - (bRoundedBottomCorner ? r : 0);
307 
308 	int iNbPoins1Round = 70/DELTA_ROUND_DEGREE;  // pour une inclinaison classique (~30deg), les coins du haut feront moins d'1/4 de tour.
309 	int iNbPoins1Curve = 10;
310 	if (pPath == NULL)
311 		pPath = cairo_dock_new_gl_path ((iNbPoins1Round+1)*2 + (iNbPoins1Curve+1)*2 + 1, 0., fTotalHeight/2, fTotalWidth, fTotalHeight);
312 	else
313 	{
314 		cairo_dock_gl_path_move_to (pPath, 0., fTotalHeight/2);
315 		cairo_dock_gl_path_set_extent (pPath, fTotalWidth, fTotalHeight);
316 	}
317 	cairo_dock_gl_path_arc (pPath, iNbPoins1Round, -w, h, r, G_PI/2, G_PI/2 - a);  // coin haut gauche. 90 -> 180-a
318 
319 	if (bRoundedBottomCorner)
320 	{
321 		double t = G_PI-a;
322 		double x0 = -w_ + r * cos (t);
323 		double y0 = -h + r * sin (t);
324 		double x1 = x0 - fInclination * r * (1+sina);
325 		double y1 = -h - r;
326 		double x2 = -w_;
327 		double y2 = y1;
328 		cairo_dock_gl_path_line_to (pPath, x0, y0);
329 		cairo_dock_gl_path_simple_curve_to (pPath, iNbPoins1Curve, x1, y1, x2, y2);  // coin bas gauche.
330 
331 		double x3 = x0, y3 = y0;  // temp.
332 		x0 = - x2;
333 		y0 = y2;
334 		x1 = - x1;
335 		x2 = - x3;
336 		y2 = y3;
337 		cairo_dock_gl_path_line_to (pPath, x0, y0);
338 		cairo_dock_gl_path_simple_curve_to (pPath, iNbPoins1Curve, x1, y1, x2, y2);  // coin bas droit.
339 	}
340 	else
341 	{
342 		cairo_dock_gl_path_line_to (pPath,
343 			-w_,
344 			-h - r);  // bas gauche.
345 		cairo_dock_gl_path_line_to (pPath,
346 			w_,
347 			-h - r);  // bas droit.
348 	}
349 
350 	cairo_dock_gl_path_arc (pPath, iNbPoins1Round, w, h, r, a, G_PI/2 - a);  // coin haut droit. a -> 90
351 
352 	return pPath;
353 }
354 
355 
356 #define _get_icon_center_x(icon) (icon->fDrawX + icon->fWidth * icon->fScale/2)
357 #define _get_icon_center_y(icon) (icon->fDrawY + (bForceConstantSeparator && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon) ? icon->fHeight * (icon->fScale - .5) : icon->fHeight * icon->fScale/2))
358 #define _get_icon_center(icon,x,y) do {\
359 	if (pDock->container.bIsHorizontal) {\
360 		x = _get_icon_center_x (icon);\
361 		y = pDock->container.iHeight - _get_icon_center_y (icon); }\
362 	else {\
363 		 y = _get_icon_center_x (icon);\
364 		 x = pDock->container.iWidth - _get_icon_center_y (icon); } } while (0)
365 #define _calculate_slope(x0,y0,x1,y1,dx,dy) do {\
366 	dx = x1 - x0;\
367 	dy = y1 - y0;\
368 	norme = sqrt (dx*dx + dy*dy);\
369 	dx /= norme;\
370 	dy /= norme; } while (0)
371 #define NB_VERTEX_PER_ICON_PAIR 10
cairo_dock_generate_string_path_opengl(CairoDock * pDock,gboolean bIsLoop,gboolean bForceConstantSeparator)372 const CairoDockGLPath *cairo_dock_generate_string_path_opengl (CairoDock *pDock, gboolean bIsLoop, gboolean bForceConstantSeparator)
373 {
374 	static CairoDockGLPath *pPath = NULL;
375 	if (pPath == NULL)
376 		pPath = cairo_dock_new_gl_path (100*NB_VERTEX_PER_ICON_PAIR + 1, 0., 0., 0., 0.);
377 
378 	GList *ic, *next_ic, *next2_ic, *pFirstDrawnElement = pDock->icons;
379 	Icon *pIcon, *pNextIcon, *pNext2Icon;
380 	double x0,y0, x1,y1, x2,y2;  // centres des icones P0, P1, P2, en coordonnees opengl.
381 	double norme;  // pour normaliser les pentes.
382 	double dx, dy;  // direction au niveau de l'icone courante P0.
383 	double dx_, dy_;  // direction au niveau de l'icone suivante P1.
384 	double x0_,y0_, x1_,y1_;  // points de controle entre P0 et P1.
385 	if (pFirstDrawnElement == NULL)
386 	{
387 		return pPath;
388 	}
389 
390 	// direction initiale.
391 	ic = pFirstDrawnElement;
392 	pIcon = ic->data;
393 	_get_icon_center (pIcon,x0,y0);
394 	next_ic = cairo_dock_get_next_element (ic, pDock->icons);
395 	pNextIcon = next_ic->data;
396 	_get_icon_center (pNextIcon,x1,y1);
397 	if (! bIsLoop)
398 	{
399 		_calculate_slope (x0,y0, x1,y1, dx,dy);
400 	}
401 	else
402 	{
403 		next2_ic = cairo_dock_get_previous_element (ic, pDock->icons);  // icone precedente dans la boucle.
404 		pNext2Icon = next2_ic->data;
405 		_get_icon_center (pNext2Icon,x2,y2);
406 		_calculate_slope (x2,y2, x0,y0, dx,dy);
407 	}
408 	// point suivant.
409 	next2_ic = cairo_dock_get_next_element (next_ic, pDock->icons);
410 	pNext2Icon = next2_ic->data;
411 	_get_icon_center (pNext2Icon,x2,y2);
412 
413 	cairo_dock_gl_path_move_to (pPath, x0, y0);
414 	if (pDock->container.bIsHorizontal)
415 		cairo_dock_gl_path_set_extent (pPath, pDock->container.iWidth, pDock->container.iHeight);
416 	else
417 		cairo_dock_gl_path_set_extent (pPath, pDock->container.iHeight, pDock->container.iWidth);
418 
419 	// on parcourt les icones.
420 	do
421 	{
422 		// l'icone courante, la suivante, et celle d'apres.
423 		pIcon = ic->data;
424 		pNextIcon = next_ic->data;
425 		pNext2Icon = next2_ic->data;
426 
427 		// on va tracer de (x0,y0) a (x1,y1)
428 		_get_icon_center (pIcon,x0,y0);
429 		_get_icon_center (pNextIcon,x1,y1);
430 		_get_icon_center (pNext2Icon,x2,y2);
431 
432 		// la pente au point (x1,y1)
433 		_calculate_slope (x0,y0, x2,y2, dx_,dy_);
434 
435 		// points de controle.
436 		norme = sqrt ((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0))/2;  // distance de prolongation suivant la pente.
437 		x0_ = x0 + dx * norme;
438 		y0_ = y0 + dy * norme;
439 		x1_ = x1 - dx_ * norme;
440 		y1_ = y1 - dy_ * norme;
441 
442 		cairo_dock_gl_path_curve_to (pPath, NB_VERTEX_PER_ICON_PAIR,
443 			x0_, y0_,
444 			x1_, y1_,
445 			x1,  y1);
446 
447 		// on decale tout d'un cran.
448 		ic = next_ic;
449 		next_ic = next2_ic;
450 		next2_ic = cairo_dock_get_next_element (next_ic, pDock->icons);
451 		dx = dx_;
452 		dy = dy_;
453 		if (next_ic == pFirstDrawnElement && ! bIsLoop)
454 			break ;
455 	}
456 	while (ic != pFirstDrawnElement);
457 
458 	return pPath;
459 }
460 
461 
cairo_dock_draw_current_path_opengl(double fLineWidth,double * fLineColor,int iNbVertex)462 void cairo_dock_draw_current_path_opengl (double fLineWidth, double *fLineColor, int iNbVertex)
463 {
464 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
465 	glLineWidth(fLineWidth); // Ici on choisit l'epaisseur du contour du polygone.
466 	if (fLineColor != NULL)
467 		glColor4f (fLineColor[0], fLineColor[1], fLineColor[2], fLineColor[3]); // Et sa couleur.
468 
469 	_draw_current_path (iNbVertex, FALSE);
470 }
471 
472 
cairo_dock_draw_rounded_rectangle_opengl(double fFrameWidth,double fFrameHeight,double fRadius,double fLineWidth,double * fLineColor)473 void cairo_dock_draw_rounded_rectangle_opengl (double fFrameWidth, double fFrameHeight, double fRadius, double fLineWidth, double *fLineColor)
474 {
475 	const CairoDockGLPath *pPath = cairo_dock_generate_rectangle_path (fFrameWidth, fFrameHeight, fRadius, TRUE);
476 
477 	if (fLineColor != NULL)
478 		glColor4f (fLineColor[0], fLineColor[1], fLineColor[2], fLineColor[3]);
479 	if (fLineWidth == 0)
480 	{
481 		cairo_dock_fill_gl_path (pPath, 0);
482 	}
483 	else
484 	{
485 		glLineWidth (fLineWidth);
486 		cairo_dock_stroke_gl_path (pPath, TRUE);
487 	}
488 }
489 
cairo_dock_draw_string_opengl(CairoDock * pDock,double fStringLineWidth,gboolean bIsLoop,gboolean bForceConstantSeparator)490 void cairo_dock_draw_string_opengl (CairoDock *pDock, double fStringLineWidth, gboolean bIsLoop, gboolean bForceConstantSeparator)
491 {
492 	const CairoDockGLPath *pPath = cairo_dock_generate_string_path_opengl (pDock, bIsLoop, bForceConstantSeparator);
493 	if (pPath == NULL || pPath->iCurrentPt < 2)
494 		return;
495 
496 	glLineWidth (fStringLineWidth);
497 	///glColor4f (myIconsParam.fStringColor[0], myIconsParam.fStringColor[1], myIconsParam.fStringColor[2], myIconsParam.fStringColor[3]);
498 	cairo_dock_stroke_gl_path (pPath, FALSE);
499 }
500