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