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-icon-facility.h"
24 #include "cairo-dock-log.h"
25 #include "cairo-dock-dock-facility.h"  // cairo_dock_get_first_drawn_element_linear
26 #include "cairo-dock-applications-manager.h"  // myTaskbarParam.fVisibleAppliAlpha
27 #include "cairo-dock-windows-manager.h"
28 #include "cairo-dock-separator-manager.h"
29 #include "cairo-dock-applet-manager.h"
30 #include "cairo-dock-dock-manager.h"
31 #include "cairo-dock-animations.h"
32 #include "cairo-dock-overlay.h"
33 #include "cairo-dock-style-manager.h"
34 #include "cairo-dock-opengl-path.h"
35 
36 #include "cairo-dock-draw-opengl.h"
37 
38 #include "texture-gradation.h"
39 #define RADIAN (G_PI / 180.0)  // Conversion Radian/Degres
40 #define DELTA_ROUND_DEGREE 3
41 
42 extern GLuint g_pGradationTexture[2];
43 
44 extern GldiContainer *g_pPrimaryContainer;
45 
46 extern CairoDockImageBuffer g_pVisibleZoneBuffer;
47 
48 extern gboolean g_bUseOpenGL;
49 extern CairoDockGLConfig g_openglConfig;
50 
51 extern gboolean g_bEasterEggs;
52 
53 
cairo_dock_set_icon_scale(Icon * pIcon,GldiContainer * pContainer,double fZoomFactor)54 void cairo_dock_set_icon_scale (Icon *pIcon, GldiContainer *pContainer, double fZoomFactor)
55 {
56 	double fSizeX, fSizeY;
57 	cairo_dock_get_current_icon_size (pIcon, pContainer, &fSizeX, &fSizeY);
58 	glScalef (fSizeX * fZoomFactor, fSizeY * fZoomFactor, fSizeY * fZoomFactor);
59 }
60 
cairo_dock_set_container_orientation_opengl(GldiContainer * pContainer)61 void cairo_dock_set_container_orientation_opengl (GldiContainer *pContainer)
62 {
63 	if (pContainer->bIsHorizontal)
64 	{
65 		if (! pContainer->bDirectionUp)
66 		{
67 			glTranslatef (0., pContainer->iHeight, 0.);
68 			glScalef (1., -1., 1.);
69 		}
70 	}
71 	else
72 	{
73 		glTranslatef (pContainer->iHeight/2, pContainer->iWidth/2, 0.);
74 		glRotatef (-90., 0., 0., 1.);
75 		if (pContainer->bDirectionUp)
76 			glScalef (1., -1., 1.);
77 		glTranslatef (-pContainer->iWidth/2, -pContainer->iHeight/2, 0.);
78 	}
79 }
80 
81 
cairo_dock_combine_argb_argb(void)82 void cairo_dock_combine_argb_argb (void)  // taken from glitz 0.5.6
83 {
84 	glEnable(GL_BLEND);
85 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
86 
87 	glActiveTexture (GL_TEXTURE0);
88 	glEnable(GL_TEXTURE_2D);
89 	glColor4f(0., 0., 0., 1.);
90 	glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
91 
92 	glActiveTexture (GL_TEXTURE1);
93 	glEnable(GL_TEXTURE_2D);
94 	glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
95 
96 	glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
97 	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
98 	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
99 	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
100 	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
101 
102 	glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
103 	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
104 	glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
105 	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
106 	glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
107 }
108 
cairo_dock_draw_icon_reflect_opengl(Icon * pIcon,CairoDock * pDock)109 void cairo_dock_draw_icon_reflect_opengl (Icon *pIcon, CairoDock *pDock)
110 {
111 	if (pDock->container.bUseReflect)
112 	{
113 		if (pDock->pRenderer->bUseStencil && g_openglConfig.bStencilBufferAvailable)
114 		{
115 			glEnable (GL_STENCIL_TEST);
116 			glStencilFunc (GL_EQUAL, 1, 1);
117 			glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
118 		}
119 		glPushMatrix ();
120 		double x0, y0, x1, y1;
121 		double fScale = ((myIconsParam.bConstantSeparatorSize && GLDI_OBJECT_IS_SEPARATOR_ICON (pIcon)) ? 1. : pIcon->fScale);
122 		///double fReflectSize = MIN (myIconsParam.fReflectSize, pIcon->fHeight/pDock->container.fRatio*fScale);
123 		double fReflectSize = pIcon->fHeight * myIconsParam.fReflectHeightRatio * fScale;
124 		///double fReflectRatio = fReflectSize * pDock->container.fRatio / pIcon->fHeight / fScale  / pIcon->fHeightFactor;
125 		double fReflectRatio = myIconsParam.fReflectHeightRatio;
126 		double fOffsetY = pIcon->fHeight * fScale/2 + fReflectSize/** * pDock->container.fRatio*/ / 2 + pIcon->fDeltaYReflection;
127 		if (pDock->container.bIsHorizontal)
128 		{
129 			if (pDock->container.bDirectionUp)
130 			{
131 				glTranslatef (0., - fOffsetY, 0.);
132 				glScalef (pIcon->fWidth * pIcon->fWidthFactor * fScale, - fReflectSize/** * pDock->container.fRatio*/, 1.);  // taille du reflet et on se retourne.
133 				x0 = 0.;
134 				y0 = 1. - fReflectRatio;
135 				x1 = 1.;
136 				y1 = 1.;
137 			}
138 			else
139 			{
140 				glTranslatef (0., fOffsetY, 0.);
141 				glScalef (pIcon->fWidth * pIcon->fWidthFactor * fScale, fReflectSize/** * pDock->container.fRatio*/, 1.);
142 				x0 = 0.;
143 				y0 = fReflectRatio;
144 				x1 = 1.;
145 				y1 = 0.;
146 			}
147 		}
148 		else
149 		{
150 			if (pDock->container.bDirectionUp)
151 			{
152 				glTranslatef (fOffsetY, 0., 0.);
153 				glScalef (- fReflectSize/** * pDock->container.fRatio*/, pIcon->fWidth * pIcon->fWidthFactor * fScale, 1.);
154 				x0 = 1. - fReflectRatio;
155 				y0 = 0.;
156 				x1 = 1.;
157 				y1 = 1.;
158 			}
159 			else
160 			{
161 				glTranslatef (- fOffsetY, 0., 0.);
162 				glScalef (fReflectSize/** * pDock->container.fRatio*/, pIcon->fWidth * pIcon->fWidthFactor * fScale, 1.);
163 				x0 = fReflectRatio;
164 				y0 = 0.;
165 				x1 = 0.;
166 				y1 = 1.;
167 			}
168 		}
169 
170 		glEnable(GL_TEXTURE_2D);
171 		glBindTexture(GL_TEXTURE_2D, pIcon->image.iTexture);
172 		glEnable(GL_BLEND);
173 		_cairo_dock_set_blend_alpha ();
174 		glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
175 
176 		//glBlendColor(1., 1., 1., 1.);  // utile ?
177 
178 		glPolygonMode (GL_FRONT, GL_FILL);
179 		glColor4f(1., 1., 1., 1.);
180 
181 		glBegin(GL_QUADS);
182 
183 		double fReflectAlpha = myIconsParam.fAlbedo * pIcon->fAlpha;
184 		if (pDock->container.bIsHorizontal)
185 		{
186 			glTexCoord2f (x0, y0);
187 			glColor4f (1., 1., 1., fReflectAlpha * pIcon->fReflectShading);
188 			glVertex3f (-.5, .5, 0.);  // Bottom Left Of The Texture and Quad
189 
190 			glTexCoord2f (x1, y0);
191 			glColor4f (1., 1., 1., fReflectAlpha * pIcon->fReflectShading);
192 			glVertex3f (.5, .5, 0.);  // Bottom Right Of The Texture and Quad
193 
194 			glTexCoord2f (x1, y1);
195 			glColor4f (1., 1., 1., fReflectAlpha);
196 			glVertex3f (.5, -.5, 0.);  // Top Right Of The Texture and Quad
197 
198 			glTexCoord2f (x0, y1);
199 			glColor4f (1., 1., 1., fReflectAlpha);
200 			glVertex3f (-.5, -.5, 0.);  // Top Left Of The Texture and Quad
201 		}
202 		else
203 		{
204 			glTexCoord2f (x0, y0);
205 			glColor4f (1., 1., 1., fReflectAlpha * pIcon->fReflectShading);
206 			glVertex3f (-.5, .5, 0.);  // Bottom Left Of The Texture and Quad
207 
208 			glTexCoord2f (x1, y0);
209 			glColor4f (1., 1., 1., fReflectAlpha);
210 			glVertex3f (.5, .5, 0.);  // Bottom Right Of The Texture and Quad
211 
212 			glTexCoord2f (x1, y1);
213 			glColor4f (1., 1., 1., fReflectAlpha);
214 			glVertex3f (.5, -.5, 0.);  // Top Right Of The Texture and Quad
215 
216 			glTexCoord2f (x0, y1);
217 			glColor4f (1., 1., 1., fReflectAlpha * pIcon->fReflectShading);
218 			glVertex3f (-.5, -.5, 0.);  // Top Left Of The Texture and Quad
219 		}
220 		glEnd();
221 
222 		glPopMatrix ();
223 		if (pDock->pRenderer->bUseStencil && g_openglConfig.bStencilBufferAvailable)
224 		{
225 			glDisable (GL_STENCIL_TEST);
226 		}
227 	}
228 }
229 
cairo_dock_draw_icon_opengl(Icon * pIcon,CairoDock * pDock)230 void cairo_dock_draw_icon_opengl (Icon *pIcon, CairoDock *pDock)
231 {
232 	//\_____________________ On dessine l'icone.
233 	double fSizeX, fSizeY;
234 	cairo_dock_get_current_icon_size (pIcon, CAIRO_CONTAINER (pDock), &fSizeX, &fSizeY);
235 
236 	_cairo_dock_enable_texture ();
237 	if (pIcon->fAlpha == 1)
238 		_cairo_dock_set_blend_pbuffer ();
239 	else
240 		_cairo_dock_set_blend_alpha ();
241 	_cairo_dock_apply_texture_at_size_with_alpha (pIcon->image.iTexture, fSizeX, fSizeY, pIcon->fAlpha);
242 	//if (g_strcmp0 (pIcon->cName, "Calculatrice") == 0)
243 		//g_print ("%s: %.2f\n", pIcon->cName, pIcon->fAlpha);
244 	//\_____________________ On dessine son reflet.
245 	cairo_dock_draw_icon_reflect_opengl (pIcon, pDock);
246 
247 	_cairo_dock_disable_texture ();
248 }
249 
250 
_compute_icon_coordinate(Icon * icon,GldiContainer * pContainer,double fDockMagnitude,double * pX,double * pY)251 static inline void _compute_icon_coordinate (Icon *icon, GldiContainer *pContainer, double fDockMagnitude, double *pX, double *pY)
252 {
253 	double fX=0, fY=0;
254 	double fRatio = pContainer->fRatio;
255 	double fGlideScale;
256 	if (icon->fGlideOffset != 0)
257 	{
258 		double fPhase =  icon->fPhase + icon->fGlideOffset * icon->fWidth / fRatio / myIconsParam.iSinusoidWidth * G_PI;
259 		if (fPhase < 0)
260 		{
261 			fPhase = 0;
262 		}
263 		else if (fPhase > G_PI)
264 		{
265 			fPhase = G_PI;
266 		}
267 		fGlideScale = (1 + fDockMagnitude * myIconsParam.fAmplitude * sin (fPhase)) / icon->fScale;  // c'est un peu hacky ... il faudrait passer l'icone precedente en parametre ...
268 		if (! pContainer->bDirectionUp)
269 		{
270 			if (pContainer->bIsHorizontal)
271 				fY = (1-fGlideScale)*icon->fHeight*icon->fScale;
272 			else
273 				fX = (1-fGlideScale)*icon->fHeight*icon->fScale;
274 		}
275 	}
276 	else
277 		fGlideScale = 1;
278 	icon->fGlideScale = fGlideScale;
279 
280 	if (pContainer->bIsHorizontal)
281 	{
282 		fY += pContainer->iHeight - icon->fDrawY;  // ordonnee du haut de l'icone.
283 		fX += icon->fDrawX + icon->fWidth * icon->fScale/2 + icon->fGlideOffset * icon->fWidth * icon->fScale * (icon->fGlideOffset < 0 ? fGlideScale : 1);  // abscisse du milieu de l'icone.
284 	}
285 	else
286 	{
287 		fY += icon->fDrawY;  // ordonnee du haut de l'icone.
288 		fX +=  pContainer->iWidth - (icon->fDrawX + icon->fWidth * icon->fScale/2 + icon->fGlideOffset * icon->fWidth * icon->fScale * (icon->fGlideOffset < 0 ? fGlideScale : 1));
289 	}
290 	*pX = fX;
291 	*pY = fY;
292 }
293 
cairo_dock_translate_on_icon_opengl(Icon * icon,GldiContainer * pContainer,double fDockMagnitude)294 void cairo_dock_translate_on_icon_opengl (Icon *icon, GldiContainer *pContainer, double fDockMagnitude)
295 {
296 	double fX=0, fY=0;
297 	_compute_icon_coordinate (icon, pContainer, fDockMagnitude, &fX, &fY);
298 	double fMaxScale = cairo_dock_get_icon_max_scale (icon);
299 
300 	if (pContainer->bIsHorizontal)
301 		glTranslatef ( (fX),  (fY - icon->fHeight * icon->fScale * (1 - icon->fGlideScale/2)), - icon->fHeight * fMaxScale);
302 	else
303 		glTranslatef ( (fY + icon->fHeight * icon->fScale * (1 - icon->fGlideScale/2)),  (fX), - icon->fHeight * fMaxScale);
304 }
305 
cairo_dock_render_one_icon_opengl(Icon * icon,CairoDock * pDock,double fDockMagnitude,gboolean bUseText)306 void cairo_dock_render_one_icon_opengl (Icon *icon, CairoDock *pDock, double fDockMagnitude, gboolean bUseText)
307 {
308 	if (icon->image.iTexture == 0)
309 		return ;
310 	double fRatio = pDock->container.fRatio;
311 
312 	if (g_pGradationTexture[pDock->container.bIsHorizontal] == 0)
313 	{
314 		//g_pGradationTexture[pDock->container.bIsHorizontal] = cairo_dock_load_local_texture (pDock->container.bIsHorizontal ? "texture-gradation-vert.png" : "texture-gradation-horiz.png", GLDI_SHARE_DATA_DIR);
315 		g_pGradationTexture[pDock->container.bIsHorizontal] = cairo_dock_create_texture_from_raw_data (gradationTex,
316 			pDock->container.bIsHorizontal ? 1:48,
317 			pDock->container.bIsHorizontal ? 48:1);
318 		cd_debug ("g_pGradationTexture(%d) <- %d", pDock->container.bIsHorizontal, g_pGradationTexture[pDock->container.bIsHorizontal]);
319 	}
320 	if (CAIRO_DOCK_IS_APPLI (icon) && myTaskbarParam.fVisibleAppliAlpha != 0 && ! GLDI_OBJECT_IS_APPLET_ICON (icon) && !(myTaskbarParam.iMinimizedWindowRenderType == 1 && icon->pAppli->bIsHidden))
321 	{
322 		double fAlpha = (icon->pAppli->bIsHidden ? MIN (1 - myTaskbarParam.fVisibleAppliAlpha, 1) : MIN (myTaskbarParam.fVisibleAppliAlpha + 1, 1));
323 		if (fAlpha != 1)
324 			icon->fAlpha = fAlpha;  // astuce bidon pour pas multiplier 2 fois.
325 	}
326 
327 	//\_____________________ On se place au centre de l'icone.
328 	double fX=0, fY=0;
329 	_compute_icon_coordinate (icon, CAIRO_CONTAINER (pDock), fDockMagnitude * pDock->fMagnitudeMax, &fX, &fY);
330 
331 	glPushMatrix ();
332 	if (pDock->container.bIsHorizontal)
333 		glTranslatef (fX, fY - icon->fHeight * icon->fScale * (1 - icon->fGlideScale/2), - icon->fHeight * icon->fScale);
334 	else
335 		glTranslatef (fY + icon->fHeight * icon->fScale * (1 - icon->fGlideScale/2), fX, - icon->fHeight * icon->fScale);
336 
337 	//\_____________________ On positionne l'icone.
338 	glPushMatrix ();
339 	if (myIconsParam.bConstantSeparatorSize && GLDI_OBJECT_IS_SEPARATOR_ICON (icon))
340 	{
341 		if (pDock->container.bIsHorizontal)
342 		{
343 			glTranslatef (0., (pDock->container.bDirectionUp ? icon->fHeight * (- icon->fScale + 1)/2 : icon->fHeight * (icon->fScale - 1)/2), 0.);
344 		}
345 		else
346 		{
347 			glTranslatef ((!pDock->container.bDirectionUp ? icon->fHeight * (- icon->fScale + 1)/2 : icon->fHeight * (icon->fScale - 1)/2), 0., 0.);
348 		}
349 	}
350 	if (icon->fOrientation != 0)
351 	{
352 		glTranslatef (-icon->fWidth * icon->fScale/2, icon->fHeight * icon->fScale/2, 0.);
353 		glRotatef (-icon->fOrientation/G_PI*180., 0., 0., 1.);
354 		glTranslatef (icon->fWidth * icon->fScale/2, -icon->fHeight * icon->fScale/2, 0.);
355 	}
356 	if (GLDI_OBJECT_IS_SEPARATOR_ICON (icon) && myIconsParam.bRevolveSeparator)
357 	{
358 		if (pDock->container.bIsHorizontal)
359 		{
360 			if (! pDock->container.bDirectionUp)
361 			{
362 				glScalef (1., -1., 1.);
363 			}
364 		}
365 		else
366 		{
367 			glMatrixMode(GL_TEXTURE);
368 			glRotatef (-90., 0., 0., 1.);
369 			glMatrixMode (GL_MODELVIEW);
370 			if (pDock->container.bDirectionUp)
371 				glScalef (1., -1., 1.);
372 		}
373 	}
374 	if (icon->iRotationX != 0)
375 		glRotatef (icon->iRotationX, 1., 0., 0.);
376 	if (icon->iRotationY != 0)
377 		glRotatef (icon->iRotationY, 0., 1., 0.);
378 
379 	//\_____________________ On dessine l'icone.
380 	gboolean bIconHasBeenDrawn = FALSE;
381 	gldi_object_notify (&myIconObjectMgr, NOTIFICATION_PRE_RENDER_ICON, icon, pDock, NULL);
382 	gldi_object_notify (&myIconObjectMgr, NOTIFICATION_RENDER_ICON, icon, pDock, &bIconHasBeenDrawn, NULL);
383 
384 	glPopMatrix ();  // retour juste apres la translation au milieu de l'icone.
385 
386 	if (GLDI_OBJECT_IS_SEPARATOR_ICON (icon) && myIconsParam.bRevolveSeparator && !pDock->container.bIsHorizontal)
387 	{
388 		glMatrixMode(GL_TEXTURE);
389 		glLoadIdentity ();
390 		glMatrixMode (GL_MODELVIEW);
391 	}
392 
393 	//\_____________________ Draw the overlays on top of that.
394 	cairo_dock_draw_icon_overlays_opengl (icon, fRatio);
395 
396 	//\_____________________ On dessine les etiquettes, avec un alpha proportionnel au facteur d'echelle de leur icone.
397 	glPopMatrix ();  // retour au debut de la fonction.
398 	if (bUseText && icon->label.iTexture != 0 && icon->iHideLabel == 0
399 	&& (icon->bPointed || (icon->fScale > 1.01 && ! myIconsParam.bLabelForPointedIconOnly)))  // 1.01 car sin(pi) = 1+epsilon :-/  //  && icon->iAnimationState < CAIRO_DOCK_STATE_CLICKED
400 	{
401 		glPushMatrix ();
402 		glLoadIdentity ();
403 
404 		_cairo_dock_enable_texture ();
405 		_cairo_dock_set_blend_over ();  // _cairo_dock_set_blend_alpha() makes the outline look bad when they have a light color :-/
406 		double fMagnitude;
407 		if (myIconsParam.bLabelForPointedIconOnly || pDock->fMagnitudeMax == 0. || myIconsParam.fAmplitude == 0.)
408 		{
409 			fMagnitude = fDockMagnitude;  // (icon->fScale - 1) / myIconsParam.fAmplitude / sin (icon->fPhase);  // sin (phi ) != 0 puisque fScale > 1.
410 		}
411 		else
412 		{
413 			fMagnitude = (icon->fScale - 1) / myIconsParam.fAmplitude;  /// il faudrait diviser par pDock->fMagnitudeMax ...
414 			fMagnitude = pow (fMagnitude, myIconsParam.fLabelAlphaThreshold);
415 			///fMagnitude *= (fMagnitude * myIconsParam.fLabelAlphaThreshold + 1) / (myIconsParam.fLabelAlphaThreshold + 1);
416 		}
417 
418 		double dx = .5 * (icon->label.iWidth & 1);  // on decale la texture pour la coller sur la grille des coordonnees entieres.
419 		double dy = .5 * (icon->label.iHeight & 1);
420 
421 		int gap = (myDocksParam.iDockLineWidth + myDocksParam.iFrameMargin) * (1 - pDock->fMagnitudeMax) + 1;  // gap between icon and label: let 1px between the icon or the dock's outline
422 
423 		if (pDock->container.bIsHorizontal)
424 		{
425 			if (fX + icon->label.iWidth/2 > pDock->container.iWidth)  // l'etiquette deborde a droite.
426 				fX = pDock->container.iWidth - icon->label.iWidth/2;
427 			if (fX - icon->label.iWidth/2 < 0)  // l'etiquette deborde a gauche.
428 				fX = icon->label.iWidth/2;
429 
430 			glTranslatef (floor (fX) + dx,
431 				pDock->container.bDirectionUp ?
432 					floor (fY + /**myIconsParam.iLabelSize - */icon->label.iHeight / 2) + gap + dy:
433 					floor (fY - icon->fHeight * icon->fScale - /**myIconsParam.iLabelSize + */icon->label.iHeight / 2) - gap - dy,
434 				0.);
435 
436 			_cairo_dock_set_alpha (fMagnitude);
437 			cairo_dock_apply_image_buffer_texture (&icon->label);
438 		}
439 		else  // horizontal label on a vertical dock -> draw them next to the icon, vertically centered (like the Parabolic view)
440 		{
441 			if (icon->pSubDock && gldi_container_is_visible (CAIRO_CONTAINER (icon->pSubDock)))
442 			{
443 				fMagnitude /= 3;
444 			}
445 
446 			const int pad = 0;
447 			int iXStick = (pDock->container.bDirectionUp ?
448 				floor (fY - gap - pad) :  // right border
449 				floor (fY + icon->fHeight * icon->fScale + gap + pad));  // left border
450 			int iMaxWidth = (pDock->container.bDirectionUp ?
451 				iXStick :
452 				pDock->container.iHeight - iXStick);
453 
454 			int w;
455 			if (icon->label.iWidth > iMaxWidth)
456 			{
457 				w = iMaxWidth;
458 				dx = .5 * (w & 1);
459 			}
460 			else
461 			{
462 				w = icon->label.iWidth;
463 			}
464 			glTranslatef ((pDock->container.bDirectionUp ?
465 					floor (iXStick - w/2) - dx :
466 					floor (iXStick + w/2) + dx),
467 				floor (fX) + dy,
468 				0.);
469 
470 			if (icon->label.iWidth > iMaxWidth)  // draw with an alpha gradation on the last part.
471 			{
472 				cairo_dock_apply_image_buffer_texture_with_limit (&icon->label, fMagnitude, iMaxWidth);
473 			}
474 			else
475 			{
476 				_cairo_dock_set_alpha (fMagnitude);
477 				cairo_dock_apply_image_buffer_texture_with_offset (&icon->label, 0, 0);
478 			}
479 		}
480 		_cairo_dock_disable_texture ();
481 
482 		glPopMatrix ();
483 	}
484 }
485 
486 
cairo_dock_render_hidden_dock_opengl(CairoDock * pDock)487 void cairo_dock_render_hidden_dock_opengl (CairoDock *pDock)
488 {
489 	//g_print ("%s (%d, %x)\n", __func__, pDock->bIsMainDock, g_pVisibleZoneSurface);
490 	//\_____________________ on dessine la zone de rappel.
491 	if (g_pVisibleZoneBuffer.iTexture != 0)
492 	{
493 		_cairo_dock_enable_texture ();
494 		_cairo_dock_set_blend_over ();
495 		int w = MIN (myDocksParam.iZoneWidth, pDock->container.iWidth);
496 		int h = MIN (myDocksParam.iZoneHeight, pDock->container.iHeight);
497 		cd_debug ("%s (%dx%d)", __func__, w, h);
498 
499 		if (pDock->container.bIsHorizontal)
500 		{
501 			if (pDock->container.bDirectionUp)
502 				glTranslatef ((pDock->container.iWidth)/2, h/2, 0.);
503 			else
504 				glTranslatef ((pDock->container.iWidth)/2, pDock->container.iHeight - h/2, 0.);
505 		}
506 		else
507 		{
508 			if (!pDock->container.bDirectionUp)
509 				glTranslatef (h/2, (pDock->container.iWidth)/2, 0.);
510 			else
511 				glTranslatef (pDock->container.iHeight - h/2, (pDock->container.iWidth)/2, 0.);
512 		}
513 
514 		if (! pDock->container.bIsHorizontal)
515 			glRotatef (90., 0, 0, 1);
516 		if (! pDock->container.bDirectionUp)  // reverse image with dock.
517 			glScalef (1., -1., 1.);
518 
519 		_cairo_dock_apply_texture_at_size (g_pVisibleZoneBuffer.iTexture, w, h);
520 
521 		_cairo_dock_disable_texture ();
522 	}
523 
524 	//\_____________________ on dessine les icones demandant l'attention.
525 	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
526 	if (pFirstDrawnElement == NULL)
527 		return;
528 	double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
529 
530 	double y;
531 	Icon *icon;
532 	GList *ic = pFirstDrawnElement;
533 	GldiColor *pHiddenBgColor;
534 	GldiColor bg_color;
535 	const double r = 4; // corner radius of the background
536 	const double gap = 2;  // gap to the screen
537 	double dw = (myIconsParam.iIconGap > 2 ? 2 : 0);  // 1px margin around the icons for a better readability (only if icons won't be stuck togather then).
538 	double w, h;
539 	_cairo_dock_set_blend_alpha ();
540 	do
541 	{
542 		icon = ic->data;
543 		if (icon->bIsDemandingAttention || icon->bAlwaysVisible)
544 		{
545 			//g_print ("%s : %d (%d)\n", icon->cName, icon->bIsDemandingAttention, icon->Xid);
546 			y = icon->fDrawY;
547 			icon->fDrawY = (pDock->container.bDirectionUp ? pDock->container.iHeight - icon->fHeight * icon->fScale - gap : gap);
548 
549 			if (icon->bHasHiddenBg)
550 			{
551 				/// TODO: handle default style bg ...
552 
553 				if (icon->pHiddenBgColor)  // custom bg color
554 					pHiddenBgColor = icon->pHiddenBgColor;
555 				else if (! myDocksParam.bUseDefaultColors)  // default bg color
556 					pHiddenBgColor = &myDocksParam.fHiddenBg;
557 				else
558 				{
559 					gldi_style_color_get (GLDI_COLOR_BG, &bg_color);
560 					pHiddenBgColor = &bg_color;
561 				}
562 				//if (pHiddenBgColor[3] != 0)
563 				{
564 					_cairo_dock_set_blend_alpha ();
565 					glColor4f (pHiddenBgColor->rgba.red, pHiddenBgColor->rgba.green, pHiddenBgColor->rgba.blue, pHiddenBgColor->rgba.alpha * pDock->fPostHideOffset);
566 
567 					glPushMatrix ();
568 					w = icon->fWidth * icon->fScale;
569 					h = icon->fHeight * icon->fScale;
570 					if (pDock->container.bIsHorizontal)
571 					{
572 						glTranslatef (icon->fDrawX + w/2,
573 							pDock->container.iHeight - icon->fDrawY - h/2,
574 							0.);
575 						cairo_dock_draw_rounded_rectangle_opengl (w - 2*r + dw, h, r, 0, NULL);
576 					}
577 					else
578 					{
579 						glTranslatef (icon->fDrawY + h/2,
580 							pDock->container.iWidth - icon->fDrawX - w/2,
581 							0.);
582 						cairo_dock_draw_rounded_rectangle_opengl (h - 2*r + dw, w, r, 0, NULL);
583 					}
584 					glPopMatrix ();
585 				}
586 			}
587 
588 			glPushMatrix ();
589 			icon->fAlpha = pDock->fPostHideOffset * pDock->fPostHideOffset;
590 			cairo_dock_render_one_icon_opengl (icon, pDock, fDockMagnitude, TRUE);
591 			glPopMatrix ();
592 			icon->fDrawY = y;
593 		}
594 		ic = cairo_dock_get_next_element (ic, pDock->icons);
595 	} while (ic != pFirstDrawnElement);
596 }
597 
598 
cairo_dock_create_texture_from_surface(cairo_surface_t * pImageSurface)599 GLuint cairo_dock_create_texture_from_surface (cairo_surface_t *pImageSurface)
600 {
601 	if (! g_bUseOpenGL || pImageSurface == NULL)
602 		return 0;
603 	GLuint iTexture = 0;
604 	int w = cairo_image_surface_get_width (pImageSurface);
605 	int h = cairo_image_surface_get_height (pImageSurface);
606 	//g_print ("%s (%dx%d)\n", __func__, w, h);
607 
608 	cairo_surface_t *pPowerOfwoSurface = pImageSurface;
609 
610 	int iMaxTextureWidth = 4096, iMaxTextureHeight = 4096;  // il faudrait le recuperer de glInfo ...
611 	if (! g_openglConfig.bNonPowerOfTwoAvailable)  // cas des vieilles cartes comme la GeForce5.
612 	{
613 		double log2_w = log (w) / log (2);
614 		double log2_h = log (h) / log (2);
615 		int w_ = MIN (iMaxTextureWidth, pow (2, ceil (log2_w)));
616 		int h_ = MIN (iMaxTextureHeight, pow (2, ceil (log2_h)));
617 		cd_debug ("%dx%d --> %dx%d", w, h, w_, h_);
618 
619 		if (w != w_ || h != h_)
620 		{
621 			pPowerOfwoSurface = cairo_dock_create_blank_surface (w_, h_);
622 			cairo_t *pCairoContext = cairo_create (pPowerOfwoSurface);
623 			cairo_scale (pCairoContext, (double) w_ / w, (double) h_ / h);
624 			cairo_set_source_surface (pCairoContext, pImageSurface, 0., 0.);
625 			cairo_paint (pCairoContext);
626 			cairo_destroy (pCairoContext);
627 			w = w_;
628 			h = h_;
629 		}
630 	}
631 
632 	_cairo_dock_enable_texture ();
633 	_cairo_dock_set_blend_source ();
634 	_cairo_dock_set_alpha (1.);  // full white
635 	glGenTextures (1, &iTexture);
636 	//g_print ("+ texture %d generee (%p, %dx%d)\n", iTexture, cairo_image_surface_get_data (pImageSurface), w, h);
637 	glBindTexture (GL_TEXTURE_2D, iTexture);
638 
639 	glTexParameteri (GL_TEXTURE_2D,
640 		GL_TEXTURE_MIN_FILTER,
641 		g_bEasterEggs ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
642 	if (g_bEasterEggs)
643 		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
644 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
645 
646 	if (g_bEasterEggs)
647 		gluBuild2DMipmaps (GL_TEXTURE_2D,  /// see for automatic mipmaps generation, or at least how to update the mipmaps...
648 			4,
649 			w,
650 			h,
651 			GL_BGRA,
652 			GL_UNSIGNED_BYTE,
653 			cairo_image_surface_get_data (pPowerOfwoSurface));
654 	else
655 		glTexImage2D (GL_TEXTURE_2D,
656 			0,
657 			4,  // GL_ALPHA / GL_BGRA
658 			w,
659 			h,
660 			0,
661 			GL_BGRA,  // GL_ALPHA / GL_BGRA
662 			GL_UNSIGNED_BYTE,
663 			cairo_image_surface_get_data (pPowerOfwoSurface));
664 	if (pPowerOfwoSurface != pImageSurface)
665 		cairo_surface_destroy (pPowerOfwoSurface);
666 	glDisable(GL_TEXTURE_2D);
667 	glDisable(GL_BLEND);
668 	return iTexture;
669 }
670 
cairo_dock_create_texture_from_raw_data(const guchar * pTextureRaw,int iWidth,int iHeight)671 GLuint cairo_dock_create_texture_from_raw_data (const guchar *pTextureRaw, int iWidth, int iHeight)
672 {
673 	/*cd_debug ("%dx%d", iWidth, iHeight);
674 	int i;
675 	guint pixel, alpha, red, green, blue;
676 	float fAlphaFactor;
677 	guint *pPixelBuffer = (guint *) pTextureRaw;
678 	guint *pPixelBuffer2 = g_new (guint, iHeight * iWidth);
679 	for (i = 0; i < iHeight * iWidth; i ++)
680 	{
681 		pixel = (gint) pPixelBuffer[i];
682 		alpha = (pixel & 0xFF000000) >> 24;
683 		red = (pixel & 0x00FF0000) >> 16;
684 		green = (pixel & 0x0000FF00) >> 8;
685 		blue  = (pixel & 0x000000FF);
686 		fAlphaFactor = (float) alpha / 255.;
687 		red *= fAlphaFactor;
688 		green *= fAlphaFactor;
689 		blue *= fAlphaFactor;
690 		pPixelBuffer2[i] = (pixel & 0xFF000000) + (red << 16) + (green << 8) + (blue << 0);
691 		cd_debug ("\\%o\\%o\\%o\\%o", red, green, blue, alpha);
692 	}
693 	pTextureRaw = pPixelBuffer2;*/
694 	GLuint iTexture = 0;
695 
696 	_cairo_dock_enable_texture ();
697 	_cairo_dock_set_blend_source ();
698 	glColor4f (1., 1., 1., 1.);
699 	glGenTextures(1, &iTexture);
700 	glBindTexture(GL_TEXTURE_2D, iTexture);
701 
702 	glTexParameteri (GL_TEXTURE_2D,
703 		GL_TEXTURE_MIN_FILTER,
704 		g_bEasterEggs ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
705 	if (g_bEasterEggs)
706 		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
707 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
708 
709 	if (g_bEasterEggs && pTextureRaw)
710 		gluBuild2DMipmaps (GL_TEXTURE_2D,
711 			4,
712 			iWidth,
713 			iHeight,
714 			GL_RGBA,
715 			GL_UNSIGNED_BYTE,
716 			pTextureRaw);
717 	else
718 		glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, iWidth, iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTextureRaw);
719 	glBindTexture (GL_TEXTURE_2D, 0);
720 	glDisable(GL_TEXTURE_2D);
721 	return iTexture;
722 }
723 
cairo_dock_create_texture_from_image_full(const gchar * cImageFile,double * fImageWidth,double * fImageHeight)724 GLuint cairo_dock_create_texture_from_image_full (const gchar *cImageFile, double *fImageWidth, double *fImageHeight)
725 {
726 	g_return_val_if_fail (gtk_widget_get_realized (g_pPrimaryContainer->pWidget), 0);
727 	double fWidth=0, fHeight=0;
728 	if (cImageFile == NULL)
729 		return 0;
730 	gchar *cImagePath;
731 	if (*cImageFile == '/')
732 		cImagePath = (gchar *)cImageFile;
733 	else
734 		cImagePath = cairo_dock_search_image_s_path (cImageFile);
735 
736 	cairo_surface_t *pSurface = cairo_dock_create_surface_from_image (cImagePath,
737 		1.,
738 		0., 0.,
739 		CAIRO_DOCK_KEEP_RATIO,
740 		&fWidth,
741 		&fHeight,
742 		NULL, NULL);
743 	//cd_debug ("texture genere (%x, %.2fx%.2f)", pSurface, fWidth, fHeight);
744 
745 	if (fImageWidth != NULL)
746 		*fImageWidth = fWidth;
747 	if (fImageHeight != NULL)
748 		*fImageHeight = fHeight;
749 	GLuint iTexture = cairo_dock_create_texture_from_surface (pSurface);
750 	cairo_surface_destroy (pSurface);
751 	if (cImagePath != cImageFile)
752 		g_free (cImagePath);
753 	return iTexture;
754 }
755 
756 
cairo_dock_update_icon_texture(Icon * pIcon)757 void cairo_dock_update_icon_texture (Icon *pIcon)
758 {
759 	if (pIcon != NULL && pIcon->image.pSurface != NULL)
760 	{
761 		_cairo_dock_enable_texture ();
762 		_cairo_dock_set_blend_source ();
763 		_cairo_dock_set_alpha (1.);  // full white
764 
765 		if (pIcon->image.iTexture == 0)
766 			glGenTextures (1, &pIcon->image.iTexture);
767 		int w = cairo_image_surface_get_width (pIcon->image.pSurface);
768 		int h = cairo_image_surface_get_height (pIcon->image.pSurface);
769 		glBindTexture (GL_TEXTURE_2D, pIcon->image.iTexture);
770 
771 		glTexParameteri (GL_TEXTURE_2D,
772 			GL_TEXTURE_MIN_FILTER,
773 			g_bEasterEggs ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
774 		if (g_bEasterEggs)
775 			glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
776 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
777 
778 		if (g_bEasterEggs)
779 			gluBuild2DMipmaps (GL_TEXTURE_2D,
780 				4,
781 				w,
782 				h,
783 				GL_BGRA,
784 				GL_UNSIGNED_BYTE,
785 				cairo_image_surface_get_data (pIcon->image.pSurface));
786 		else
787 			glTexImage2D (GL_TEXTURE_2D,
788 				0,
789 				4,  // GL_ALPHA / GL_BGRA
790 				w,
791 				h,
792 				0,
793 				GL_BGRA,  // GL_ALPHA / GL_BGRA
794 				GL_UNSIGNED_BYTE,
795 				cairo_image_surface_get_data (pIcon->image.pSurface));
796 		glDisable (GL_TEXTURE_2D);
797 	}
798 }
799 
800 
801 
cairo_dock_draw_texture_with_alpha(GLuint iTexture,int iWidth,int iHeight,double fAlpha)802 void cairo_dock_draw_texture_with_alpha (GLuint iTexture, int iWidth, int iHeight, double fAlpha)
803 {
804 	_cairo_dock_enable_texture ();
805 	//~ if (fAlpha == 1)
806 		//~ _cairo_dock_set_blend_over ();
807 	//~ else
808 		///_cairo_dock_set_blend_alpha ();
809 	_cairo_dock_set_blend_over ();  // gives the best result, at least with fAlpha=1
810 
811 	_cairo_dock_apply_texture_at_size_with_alpha (iTexture, iWidth, iHeight, fAlpha);
812 
813 	_cairo_dock_disable_texture ();
814 }
815 
cairo_dock_draw_texture(GLuint iTexture,int iWidth,int iHeight)816 void cairo_dock_draw_texture (GLuint iTexture, int iWidth, int iHeight)
817 {
818 	cairo_dock_draw_texture_with_alpha (iTexture, iWidth, iHeight, 1.);
819 }
820 
cairo_dock_apply_icon_texture_at_current_size(Icon * pIcon,GldiContainer * pContainer)821 void cairo_dock_apply_icon_texture_at_current_size (Icon *pIcon, GldiContainer *pContainer)
822 {
823 	double fSizeX, fSizeY;
824 	cairo_dock_get_current_icon_size (pIcon, pContainer, &fSizeX, &fSizeY);
825 
826 	_cairo_dock_apply_texture_at_size (pIcon->image.iTexture, fSizeX, fSizeY);
827 }
828 
cairo_dock_draw_icon_texture(Icon * pIcon,GldiContainer * pContainer)829 void cairo_dock_draw_icon_texture (Icon *pIcon, GldiContainer *pContainer)
830 {
831 	double fSizeX, fSizeY;
832 	cairo_dock_get_current_icon_size (pIcon, pContainer, &fSizeX, &fSizeY);
833 
834 	cairo_dock_draw_texture_with_alpha (pIcon->image.iTexture,
835 		fSizeX,
836 		fSizeY,
837 		pIcon->fAlpha);
838 }
839 
_draw_icon_bent_backwards(Icon * pIcon,GldiContainer * pContainer,GLuint iOriginalTexture,double f)840 static inline void  _draw_icon_bent_backwards (Icon *pIcon, GldiContainer *pContainer, GLuint iOriginalTexture, double f)
841 {
842 	gldi_gl_container_set_perspective_view_for_icon (pIcon);
843 
844 	int iWidth, iHeight;
845 	cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
846 	glScalef (1., -1., 1.);
847 	glTranslatef (0., -iHeight/2, 0.);  // rotation de 50° sur l'axe des X a la base de l'icone.
848 	glRotatef (-50.*f, 1., 0., 0.);
849 	glTranslatef (0., iHeight/2, 0.);
850 
851 	_cairo_dock_enable_texture ();
852 	_cairo_dock_set_blend_source ();
853 	glBindTexture (GL_TEXTURE_2D, iOriginalTexture);
854 	double a=.25, b=.1;
855 	//double a=.0, b=.0;
856 	_cairo_dock_apply_current_texture_at_size_with_offset (iWidth*(1+b*f),
857 		iHeight*(1+a*f),
858 		0.,
859 		iHeight*(a/2*f));  // on elargit un peu la texture, car avec l'effet de profondeur elle parait trop petite.
860 	_cairo_dock_disable_texture ();
861 
862 	gldi_gl_container_set_ortho_view (pContainer);
863 }
_transition_step(Icon * pIcon,gpointer data)864 static gboolean _transition_step (Icon *pIcon, gpointer data)
865 {
866 	CairoDock *pDock = gldi_dock_get (pIcon->cParentDockName);
867 	if (pDock == NULL)
868 		return FALSE;
869 
870 	GLuint iOriginalTexture = GPOINTER_TO_INT (data);
871 	double f = cairo_dock_get_transition_fraction (pIcon);
872 	if (!pIcon->pAppli->bIsHidden)
873 		f = 1 - f;
874 
875 	_draw_icon_bent_backwards (pIcon, CAIRO_CONTAINER (pDock), iOriginalTexture, f);
876 	return TRUE;
877 }
_free_transition_data(gpointer data)878 static void _free_transition_data (gpointer data)
879 {
880 	GLuint iOriginalTexture = GPOINTER_TO_INT (data);
881 	_cairo_dock_delete_texture (iOriginalTexture);
882 }
cairo_dock_draw_hidden_appli_icon(Icon * pIcon,GldiContainer * pContainer,gboolean bStateChanged)883 void cairo_dock_draw_hidden_appli_icon (Icon *pIcon, GldiContainer *pContainer, gboolean bStateChanged)
884 {
885 	if (bStateChanged)
886 	{
887 		cairo_dock_remove_transition_on_icon (pIcon);
888 
889 		GLuint iOriginalTexture;
890 		if (pIcon->pAppli->bIsHidden)
891 		{
892 			iOriginalTexture = pIcon->image.iTexture;
893 			pIcon->image.iTexture = cairo_dock_create_texture_from_surface (pIcon->image.pSurface);
894 			/// Using FBOs copies the texture data (pixels) within VRAM only:
895 			/// - setup & bind FBO
896 			/// - setup destination texture (using glTexImage() w/ pixels = 0)
897 			/// - add (blank but sized) destination texture as color attachment
898 			/// - bind source texture to texture target
899 			/// - draw quad w/ glTexCoors describing src area, projection/modelview matrices & glVertexes describing dst area
900 		}
901 		else
902 		{
903 			iOriginalTexture = cairo_dock_create_texture_from_surface (pIcon->image.pSurface);
904 		}
905 
906 		cairo_dock_set_transition_on_icon (pIcon, pContainer,
907 			(CairoDockTransitionRenderFunc) NULL,
908 			(CairoDockTransitionGLRenderFunc) _transition_step,
909 			TRUE,  // slow
910 			500,  // ms
911 			TRUE,  // remove when finished
912 			GINT_TO_POINTER (iOriginalTexture),
913 			_free_transition_data);
914 	}
915 	else if (pIcon->pAppli->bIsHidden)
916 	{
917 		if (!cairo_dock_begin_draw_icon (pIcon, 2))
918 			return ;
919 		_draw_icon_bent_backwards (pIcon, pContainer, pIcon->image.iTexture, 1.);
920 		cairo_dock_end_draw_icon (pIcon);
921 	}
922 }
923