void cd_do_select_prev_next_entry_in_listing (gboolean bNext)
{
	CDEntry *pEntry;
	myData.pListing->fPreviousOffset = myData.pListing->fCurrentOffset;
	GList *e = myData.pListing->pCurrentEntry;
	if (bNext)
	{
		do
		{
			e = cairo_dock_get_next_element (e, myData.pListing->pEntries);
			pEntry = e->data;
		} while (e != myData.pListing->pCurrentEntry && pEntry->bHidden);
		
	}
	else
	{
		do
		{
			e = cairo_dock_get_previous_element (e, myData.pListing->pEntries);
			pEntry = e->data;
		} while (e != myData.pListing->pCurrentEntry && pEntry->bHidden);
	}
	myData.pListing->pCurrentEntry = e;
	myData.pListing->fAimedOffset += (bNext ? 1:-1) * (myDialogs.dialogTextDescription.iSize + 2);
	
	myData.pListing->iCurrentEntryAnimationCount = NB_STEPS_FOR_CURRENT_ENTRY;
	myData.pListing->iScrollAnimationCount = NB_STEPS_FOR_SCROLL;
	myData.pListing->iTitleOffset = 0;
	myData.pListing->sens = 1;
	cairo_dock_launch_animation (CAIRO_CONTAINER (myData.pListing));
	cairo_dock_redraw_container (CAIRO_CONTAINER (myData.pListing));
}
void cd_do_select_previous_next_matching_icon (gboolean bNext)
{
	GList *pMatchingElement = myData.pCurrentMatchingElement;
	do
	{
		if (!bNext)
			myData.pCurrentMatchingElement = cairo_dock_get_previous_element (myData.pCurrentMatchingElement, myData.pMatchingIcons);
		else
			myData.pCurrentMatchingElement = cairo_dock_get_next_element (myData.pCurrentMatchingElement, myData.pMatchingIcons);
	} while (myData.pCurrentMatchingElement != pMatchingElement && ((Icon*)myData.pCurrentMatchingElement->data)->image.pSurface == NULL);
	
	if (myData.pCurrentMatchingElement != pMatchingElement)  // on complete le texte et on redessine.
	{
		Icon *pIcon = myData.pCurrentMatchingElement->data;
		if (pIcon->cCommand && *pIcon->cCommand != *myData.sCurrentText->str)  // cas d'une commande avec un tiret.
			myData.iNbValidCaracters = 0;
		cd_do_delete_invalid_caracters ();
		
		if (pIcon->cBaseURI != NULL)
		{
			gchar *cFile = g_path_get_basename (pIcon->cCommand);
			g_string_assign (myData.sCurrentText, cFile);
			g_free (cFile);
		}
		else
			g_string_assign (myData.sCurrentText, pIcon->cCommand);
		
		
		cd_do_load_pending_caracters ();
		
		// on arme l'animation de decalage.
		myData.iMatchingGlideCount = 10;  // on rembobine l'animation.
		myData.iPreviousMatchingOffset = myData.iCurrentMatchingOffset;  // on part du point courant.
		int iWidth, iHeight;
		cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
		if (iHeight != 0)
		{
			double fZoom = (double) g_pMainDock->container.iHeight/2 / iHeight;
			myData.iMatchingAimPoint += (bNext ? 1 : -1) * iWidth * fZoom;  // on cherche a atteindre le nouveau point.
		}
		
		// on repositionne les caracteres et on anime tout ca.
		cd_do_launch_appearance_animation ();
		cairo_dock_redraw_container (CAIRO_CONTAINER (g_pMainDock));
	}
}
void cd_rendering_render_3D_plane_opengl (CairoDock *pDock)
{
	//\____________________ On genere le cadre.
	_define_parameters (hi, h0, H, l, r, gamma, h, w, dw);
	h = pDock->iDecorationsHeight;
	if (h < 2 * r)
		r = h / 2;
	
	double dx, dy;
	if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
	{
		double Ws = pDock->iCurrentWidth;
		double W = Ws - 2 * r;
		double a = H + hi;
		double b = H + hi + h0 - W / 2;
		double c = - W / 2;
		gamma = (-b + sqrt (b * b - 4 * a * c)) / 2  / a;
		h = hi + h0 / (1 + gamma);
		//g_print ("h : %.2f (=) %d\n", h, pDock->iDecorationsHeight);
		w = 2 * H * gamma;
		dw = (Ws - w) / 2;
		//g_print ("dw : %.2f (=) %.2f\n", dw, h * gamma + r + (l+(r==0)*2)*sqrt(1+gamma*gamma));
		dx =dw;
	}
	else
	{
		w = cairo_dock_get_current_dock_width_linear (pDock);
		gamma = w / 2 / H;
		dw = h * gamma + r + (l+(r==0)*2)*sqrt(1+gamma*gamma);
		h = pDock->iDecorationsHeight;
		Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
		dx = (pFirstIcon != NULL ? pFirstIcon->fX - myBackground.iFrameMargin : r);
	}
	
	//\____________________ On trace le cadre.
	int sens;
	if ((pDock->bDirectionUp && pDock->bHorizontalDock) || (!pDock->bDirectionUp && !pDock->bHorizontalDock))
	{
		sens = 1;
		//dy = pDock->iCurrentHeight - pDock->iDecorationsHeight - 1.5 * l;
		dy = pDock->iDecorationsHeight + 1.5*l;
	}
	else
	{
		sens = -1;
		//dy = pDock->iDecorationsHeight + 1.5 * l;
		dy = pDock->iCurrentHeight - .5 * l;
	}
	
	int iNbVertex;
	double fDeltaXTrapeze;
	GLfloat *pVertexTab = cairo_dock_generate_trapeze_path (w - (myBackground.bRoundedBottomCorner ? 0 : 2*l/gamma), h+l, r, myBackground.bRoundedBottomCorner, gamma, &fDeltaXTrapeze, &iNbVertex);
	
	if (! pDock->bHorizontalDock)
		dx = pDock->iCurrentWidth - dx + fDeltaXTrapeze;
	else
		dx = dx - fDeltaXTrapeze;
	
	//\____________________ On dessine les decorations dedans.
	//fDockOffsetY = (!pDock->bDirectionUp ? pDock->iCurrentHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	glPushMatrix ();
	cairo_dock_draw_frame_background_opengl (g_iBackgroundTexture, w+2*fDeltaXTrapeze, h+l, dx, dy, pVertexTab, iNbVertex, pDock->bHorizontalDock, pDock->bDirectionUp, pDock->fDecorationsOffsetX);
	
	//\____________________ On dessine le cadre.
	if (l != 0)
		cairo_dock_draw_current_path_opengl (l, myBackground.fLineColor, iNbVertex);
	glPopMatrix ();
	
	/// donner un effet d'epaisseur => chaud du slip avec les separateurs physiques !
	
	
	//\____________________ On dessine la ficelle qui les joint.
	if (myIcons.iStringLineWidth > 0)
		cairo_dock_draw_string_opengl (pDock, myIcons.iStringLineWidth, FALSE, (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR));
	
	//\____________________ On dessine les icones et les etiquettes, en tenant compte de l'ordre pour dessiner celles en arriere-plan avant celles en avant-plan.
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
	if (pFirstDrawnElement == NULL)
		return;
		
	double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
	Icon *icon;
	GList *ic = pFirstDrawnElement;
	
	glLoadIdentity ();
 	if (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
	{
		do
		{
			icon = ic->data;
			
			if (icon->acFileName == NULL && CAIRO_DOCK_IS_SEPARATOR (icon))
			{
				glPushMatrix ();
				if (my_iDrawSeparator3D == CD_FLAT_SEPARATOR)
					cd_rendering_draw_flat_separator_opengl (icon, pDock);
				else
					cd_rendering_draw_physical_separator_opengl (icon, pDock, TRUE, NULL, NULL);
				glPopMatrix ();
			}
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
		
		do
		{
			icon = ic->data;
			
			if (icon->acFileName != NULL || ! CAIRO_DOCK_IS_SEPARATOR (icon))
			{
				glPushMatrix ();
				cairo_dock_render_one_icon_opengl (icon, pDock, fDockMagnitude, TRUE);
				glPopMatrix ();
			}
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
		
		if (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
		{
			do
			{
				icon = ic->data;
				
				if (icon->acFileName == NULL && CAIRO_DOCK_IS_SEPARATOR (icon))
				{
					glPushMatrix ();
					cd_rendering_draw_physical_separator_opengl (icon, pDock, FALSE, NULL, NULL);
					glPopMatrix ();
				}
				
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
		}
	}
	else
	{
		do
		{
			icon = ic->data;
			
			glPushMatrix ();
			
			cairo_dock_render_one_icon_opengl (icon, pDock, fDockMagnitude, TRUE);
			
			glPopMatrix ();
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
	}
}
void cd_rendering_render_optimized_3D_plane (cairo_t *pCairoContext, CairoDock *pDock, GdkRectangle *pArea)
{
	//g_print ("%s ((%d;%d) x (%d;%d) / (%dx%d))\n", __func__, pArea->x, pArea->y, pArea->width, pArea->height, pDock->iCurrentWidth, pDock->iCurrentHeight);
	double fLineWidth = myBackground.iDockLineWidth;
	double fMargin = myBackground.iFrameMargin;
	int iWidth = pDock->iCurrentWidth;
	int iHeight = pDock->iCurrentHeight;
	
	//\____________________ On dessine les decorations du fond sur la portion de fenetre.
	cairo_save (pCairoContext);
	
	double fDockOffsetX, fDockOffsetY;
	if (pDock->bHorizontalDock)
	{
		fDockOffsetX = pArea->x;
		fDockOffsetY = (pDock->bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	}
	else
	{
		fDockOffsetX = (pDock->bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
		fDockOffsetY = pArea->y;
	}
	
	//cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY);
	if (pDock->bHorizontalDock)
		cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pArea->width, pDock->iDecorationsHeight);
	else
		cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pDock->iDecorationsHeight, pArea->height);
	
	double fRadius = MIN (myBackground.iDockRadius, (pDock->iDecorationsHeight + myBackground.iDockLineWidth) / 2 - 1);
	double fDeltaXTrapeze=0.;
	double fOffsetX;
	if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
	{
		fOffsetX = fRadius + fLineWidth / 2;
	}
	else
	{
		Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
		fOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX - fMargin : fRadius + fLineWidth / 2);
	}
	double fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
	if (g_pBackgroundSurface != NULL)
	{
		double fInclinationOnHorizon = (fDockWidth / 2) / iVanishingPointY;
		double fRadius = myBackground.iDockRadius;
		if (2*fRadius > pDock->iDecorationsHeight + fLineWidth)
			fRadius = (pDock->iDecorationsHeight + fLineWidth) / 2 - 1;
		double fDeltaXForLoop = fInclinationOnHorizon * (pDock->iDecorationsHeight + fLineWidth - (myBackground.bRoundedBottomCorner ? 2 : 1) * fRadius);
		
		double cosa = 1. / sqrt (1 + fInclinationOnHorizon * fInclinationOnHorizon);
		fDeltaXTrapeze = fDeltaXForLoop + fRadius * cosa;
		
		double sina = cosa * fInclinationOnHorizon;
		fDeltaXTrapeze = fInclinationOnHorizon * (pDock->iDecorationsHeight - (FALSE ? 2 : 1-sina) * fRadius) + fRadius * (FALSE ? 1 : cosa);
	}
	cairo_dock_render_decorations_in_frame (pCairoContext, pDock, pDock->bHorizontalDock ? fDockOffsetY : fDockOffsetX, fOffsetX-fDeltaXTrapeze, fDockWidth+2*fDeltaXTrapeze);
	
	
	//\____________________ On dessine la partie du cadre qui va bien.
	cairo_new_path (pCairoContext);
	
	if (pDock->bHorizontalDock)
	{
		cairo_set_line_width (pCairoContext, fLineWidth);
		cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY - 0.5*fLineWidth);
		cairo_rel_line_to (pCairoContext, pArea->width, 0);
		cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
		cairo_stroke (pCairoContext);
		
		cairo_new_path (pCairoContext);
		cairo_move_to (pCairoContext, fDockOffsetX, (pDock->bDirectionUp ? iHeight - 0.5*fLineWidth : pDock->iDecorationsHeight + 1.5 * fLineWidth));
		cairo_rel_line_to (pCairoContext, pArea->width, 0);
	}
	else
	{
		cairo_move_to (pCairoContext, fDockOffsetX - .5*fLineWidth, fDockOffsetY);
		cairo_rel_line_to (pCairoContext, 0, pArea->height);
		cairo_set_line_width (pCairoContext, fLineWidth);
		cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
		cairo_stroke (pCairoContext);
		
		cairo_new_path (pCairoContext);
		cairo_move_to (pCairoContext, (pDock->bDirectionUp ? iHeight - fLineWidth / 2 : pDock->iDecorationsHeight + 1.5 * fLineWidth), fDockOffsetY);
		cairo_rel_line_to (pCairoContext, 0, pArea->height);
	}
	cairo_set_line_width (pCairoContext, fLineWidth);
	cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
	cairo_stroke (pCairoContext);
	
	cairo_restore (pCairoContext);
	
	//\____________________ On dessine les icones impactees.
	GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
	if (pFirstDrawnElement != NULL)
	{
		double fXMin = (pDock->bHorizontalDock ? pArea->x : pArea->y), fXMax = (pDock->bHorizontalDock ? pArea->x + pArea->width : pArea->y + pArea->height);
		double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
		double fXLeft, fXRight;
		Icon *icon;
		GList *ic = pFirstDrawnElement;
		
		if (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
		{
			cairo_set_line_cap (pCairoContext, CAIRO_LINE_CAP_SQUARE);
			do
			{
				icon = ic->data;
				
				if (CAIRO_DOCK_IS_SEPARATOR (icon) && icon->acFileName == NULL)
				{
					if (_cd_separator_is_impacted (icon, pDock, fXMin, fXMax, TRUE, (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)))
					{
						cairo_save (pCairoContext);
						cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, TRUE);
						cairo_restore (pCairoContext);
					}
				}
				
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
			
			do
			{
				icon = ic->data;
				if (! CAIRO_DOCK_IS_SEPARATOR (icon) || icon->acFileName != NULL)
				{
					fXLeft = icon->fDrawX + icon->fScale + 1;
					fXRight = icon->fDrawX + (icon->fWidth - 1) * icon->fScale * icon->fWidthFactor - 1;
					
					if (fXLeft <= fXMax && floor (fXRight) > fXMin)
					{
						if (icon->fDrawX >= 0 && icon->fDrawX + icon->fWidth * icon->fScale <= pDock->iCurrentWidth)
							icon->fAlpha = 1;
						else
							icon->fAlpha = .25;
						
						cairo_save (pCairoContext);
						
						cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
						
						cairo_restore (pCairoContext);
					}
				}
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
			
			if (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
			{
				do
				{
					icon = ic->data;
					
					if (CAIRO_DOCK_IS_SEPARATOR (icon) && icon->acFileName == NULL)
					{
						if (_cd_separator_is_impacted (icon, pDock, fXMin, fXMax, FALSE, (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)))
						{
							cairo_save (pCairoContext);
							cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, FALSE);
							cairo_restore (pCairoContext);
						}
					}
					
					ic = cairo_dock_get_next_element (ic, pDock->icons);
				} while (ic != pFirstDrawnElement);
			}
		}
		else
		{
			do
			{
				icon = ic->data;
				fXLeft = icon->fDrawX + icon->fScale + 1;
				fXRight = icon->fDrawX + (icon->fWidth - 1) * icon->fScale * icon->fWidthFactor - 1;
				
				if (fXLeft <= fXMax && floor (fXRight) > fXMin)
				{
					if (icon->fDrawX >= 0 && icon->fDrawX + icon->fWidth * icon->fScale <= pDock->iCurrentWidth)
						icon->fAlpha = 1;
					else
						icon->fAlpha = .25;
					
					cairo_save (pCairoContext);
					
					cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
					
					cairo_restore (pCairoContext);
				}
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
		}
	}
}
void cd_rendering_render_3D_plane (cairo_t *pCairoContext, CairoDock *pDock)
{
	_define_parameters (hi, h0, H, l, r, gamma, h, w, dw);
	h = pDock->iDecorationsHeight;
	if (h < 2 * r)
		r = h / 2;
	
	double dx, dy;
	if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
	{
		double Ws = pDock->iCurrentWidth;
		gamma = Ws / 2 / H;
		double W = Ws - 2 * (r + (l+(r==0)*2)*sqrt(1+gamma*gamma));
		double a = H + hi;
		double b = H + hi + h0 - W / 2;
		double c = - W / 2;
		gamma = (-b + sqrt (b * b - 4 * a * c)) / 2  / a;
		h = hi + h0 / (1 + gamma);
		//g_print ("h : %.2f (=) %d\n", h, pDock->iDecorationsHeight);
		w = 2 * H * gamma;
		dw = (Ws - w) / 2;
		//g_print ("dw : %.2f (=) %.2f\n", dw, h * gamma + r + (l+(r==0)*2)*sqrt(1+gamma*gamma));
		dx = dw;
	}
	else
	{
		w = cairo_dock_get_current_dock_width_linear (pDock);
		gamma = w / 2 / H;
		dw = h * gamma + r + (l+(r==0)*2)*sqrt(1+gamma*gamma);
		h = pDock->iDecorationsHeight;
		Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
		dx = (pFirstIcon != NULL ? pFirstIcon->fX - 0*myBackground.iFrameMargin : r);
	}
	
	//\____________________ On trace le cadre.
	int sens;
	if (pDock->bDirectionUp)
	{
		sens = 1;
		dy = pDock->iCurrentHeight - pDock->iDecorationsHeight - 1.5 * l;
	}
	else
	{
		sens = -1;
		dy = pDock->iDecorationsHeight + 1.5 * l;
	}
	
	cairo_save (pCairoContext);
	
	double fDeltaXTrapeze = cairo_dock_draw_frame (pCairoContext, r, l, w, pDock->iDecorationsHeight, dx, dy, sens, gamma, pDock->bHorizontalDock);
	
	//\____________________ On dessine les decorations dedans.
	dy = (pDock->bDirectionUp ? pDock->iCurrentHeight - pDock->iDecorationsHeight - l : l);
	cairo_dock_render_decorations_in_frame (pCairoContext, pDock, dy, dx-fDeltaXTrapeze, w+2*fDeltaXTrapeze);
	
	//\____________________ On dessine le cadre.
	if (l > 0)
	{
		cairo_set_line_width (pCairoContext, l);
		cairo_set_source_rgba (pCairoContext, myBackground.fLineColor[0], myBackground.fLineColor[1], myBackground.fLineColor[2], myBackground.fLineColor[3]);
		cairo_stroke (pCairoContext);
	}
	else
		cairo_new_path (pCairoContext);
	
	/// donner un effet d'epaisseur => chaud du slip avec les separateurs physiques !
	
	
	cairo_restore (pCairoContext);
	
	//\____________________ On dessine la ficelle qui les joint.
	if (myIcons.iStringLineWidth > 0)
		cairo_dock_draw_string (pCairoContext, pDock, myIcons.iStringLineWidth, FALSE, (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR));
	
	//\____________________ On dessine les icones et les etiquettes, en tenant compte de l'ordre pour dessiner celles en arriere-plan avant celles en avant-plan.
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
	if (pFirstDrawnElement == NULL)
		return;
		
	double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
	
	Icon *icon;
	GList *ic = pFirstDrawnElement;
	if (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
	{
		cairo_set_line_cap (pCairoContext, CAIRO_LINE_CAP_SQUARE);
		do
		{
			icon = ic->data;
			
			if (icon->acFileName == NULL && CAIRO_DOCK_IS_SEPARATOR (icon))
			{
				cairo_save (pCairoContext);
				cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, TRUE);
				cairo_restore (pCairoContext);
			}
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
		
		do
		{
			icon = ic->data;
			
			if (icon->acFileName != NULL || ! CAIRO_DOCK_IS_SEPARATOR (icon))
			{
				cairo_save (pCairoContext);
				cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
				cairo_restore (pCairoContext);
			}
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
		
		if (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
		{
			do
			{
				icon = ic->data;
				
				if (icon->acFileName == NULL && CAIRO_DOCK_IS_SEPARATOR (icon))
				{
					cairo_save (pCairoContext);
					cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, FALSE);
					cairo_restore (pCairoContext);
				}
				
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
		}
	}
	else
	{
		do
		{
			icon = ic->data;
			
			cairo_save (pCairoContext);
			cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
			cairo_restore (pCairoContext);
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
	}
}
static void render_opengl (CairoDesklet *pDesklet)
{
	static CairoDockGLPath *pPath = NULL;
	static const int iNbPoints1Round = 5;
	static const int iNbPointsCurve = 15;
	CDPanelParameters *pPanel = (CDPanelParameters *) pDesklet->pRendererData;
	if (pPanel == NULL)
		return ;
	
	// draw frame
	double fRadius = pPanel->iRadius;
	double fLineWidth = pPanel->iLineWidth;
	//double fOffsetX = fRadius + fLineWidth/2;
	//double fOffsetY = fLineWidth/2;
	double fFrameWidth = pDesklet->container.iWidth - 2 * fRadius - fLineWidth;
	double fFrameHeight = pDesklet->container.iHeight - 2 * fRadius - fLineWidth;
	double w = fFrameWidth / 2;
	double h = fFrameHeight / 2;
	double r = fRadius;
	if (fLineWidth != 0 && pPanel->fBgColor[3] != 0)
	{
		if (pPath == NULL)
		{
			pPath = cairo_dock_new_gl_path (4*iNbPoints1Round+iNbPointsCurve+1, -w, -h, pDesklet->container.iWidth, pDesklet->container.iHeight);  // on commence en bas a gauche pour avoir une bonne triangulation du polygone.  // 4 corners + 1 curve
		}
		else
		{
			cairo_dock_gl_path_move_to (pPath, -w, -h-r);
			cairo_dock_gl_path_set_extent (pPath, pDesklet->container.iWidth, pDesklet->container.iHeight);
		}
		_cairo_dock_disable_texture ();
		_cairo_dock_set_blend_alpha ();
	
		cairo_dock_gl_path_arc (pPath, iNbPoints1Round, -w, -h, r, -G_PI/2, -G_PI/2);  // coin bas gauche.
		
		cairo_dock_gl_path_arc (pPath, iNbPoints1Round, -w, h, r, -G_PI, -G_PI/2);  // coin haut gauche.
		
		cairo_dock_gl_path_rel_curve_to (pPath, iNbPointsCurve,
			w, 0,
			w, - pPanel->iMainIconSize,
			2*w, - pPanel->iMainIconSize);
		
		cairo_dock_gl_path_arc (pPath, iNbPoints1Round, w, h - pPanel->iMainIconSize, r, G_PI/2, -G_PI/2);  // coin haut droit.
		
		cairo_dock_gl_path_arc (pPath, iNbPoints1Round, w, -h, r, 0., -G_PI/2);  // coin bas droit.
		
		glColor4f (pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], 1.);
		glLineWidth (fLineWidth);
		cairo_dock_stroke_gl_path (pPath, TRUE);
		
		glColor4f (pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], pPanel->fBgColor[3]);
		cairo_dock_fill_gl_path (pPath, 0);
	}
	
	glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.);
	
	// draw main icon.
	_cairo_dock_enable_texture ();
	_cairo_dock_set_blend_alpha ();
	_cairo_dock_set_alpha (1.);
	
	Icon *pIcon = pDesklet->pIcon;
	if (pIcon && pIcon->image.iTexture != 0 )
	{
		glPushMatrix ();
		
		glTranslatef (floor (pIcon->fDrawX + pIcon->fWidth/2),
			floor (pDesklet->container.iHeight - pIcon->fDrawY - pIcon->fHeight/2),
			0.);
		_cairo_dock_apply_texture_at_size (pIcon->image.iTexture, pIcon->fWidth, pIcon->fHeight);
		
		/**if (pIcon->iQuickInfoTexture != 0)
		{
			glPushMatrix ();
			double dx = .5 * (pIcon->iQuickInfoWidth & 1);  // on decale la texture pour la coller sur la grille des coordonnees entieres.
			double dy = .5 * (pIcon->iQuickInfoHeight & 1);
			
			glTranslatef (floor (pIcon->fWidth/2 + pIcon->iQuickInfoWidth/2) + dx, dy, 0.);
			
			_cairo_dock_apply_texture_at_size (pIcon->iQuickInfoTexture,
				pIcon->iQuickInfoWidth,
				pIcon->iQuickInfoHeight);
			glPopMatrix ();
		}*/
		glTranslatef (floor (pIcon->fWidth),
			0.,
			0.);
		cairo_dock_draw_icon_overlays_opengl (pIcon, pDesklet->container.fRatio);
		
		glPopMatrix ();
	}
	
	// draw icons.
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons);
	if (pFirstDrawnElement == NULL)
		return;
	GList *ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		
		if (pIcon->image.iTexture != 0 && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			glPushMatrix ();
			
			glTranslatef (floor (pIcon->fDrawX + pIcon->fWidth/2),
				floor (pDesklet->container.iHeight - pIcon->fDrawY - pIcon->fHeight/2),
				0.);
			
			_cairo_dock_enable_texture ();  // cairo_dock_draw_icon_overlays_opengl() disable textures
			_cairo_dock_apply_texture_at_size (pIcon->image.iTexture, pIcon->fWidth, pIcon->fHeight);
			
			if (pIcon->label.iTexture != 0)
			{
				glPushMatrix ();
				
				double dx = .5 * (pIcon->label.iWidth & 1);  // on decale la texture pour la coller sur la grille des coordonnees entieres.
				double dy = .5 * (pIcon->label.iHeight & 1);
				double u0 = 0., u1 = 1.;
				double fOffsetX = 0.;
				if (pIcon->bPointed)
				{
					_cairo_dock_set_alpha (1.);
					if (pIcon->fDrawX + pIcon->fWidth + pIcon->label.iWidth/2 > pDesklet->container.iWidth)
						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth + pIcon->label.iWidth/2);
					if (pIcon->fDrawX + pIcon->fWidth - pIcon->label.iWidth/2 < 0)
						fOffsetX = pIcon->label.iWidth/2 - (pIcon->fDrawX + pIcon->fWidth);
				}
				else
				{
					_cairo_dock_set_alpha (.6);
					if (pIcon->label.iWidth > 2*pIcon->fWidth + 2 * myIconsParam.iLabelSize)
					{
						fOffsetX = 0.;
						u1 = (double) (2*pIcon->fWidth + 2 * myIconsParam.iLabelSize) / pIcon->label.iWidth;
					}
				}
				
				glTranslatef (ceil (-pIcon->fWidth/2 + fOffsetX + pIcon->label.iWidth/2) + dx, ceil (pIcon->fHeight/2 + pIcon->label.iHeight / 2) + dy, 0.);
				
				glBindTexture (GL_TEXTURE_2D, pIcon->label.iTexture);
				_cairo_dock_apply_current_texture_portion_at_size_with_offset (u0, 0.,
					u1 - u0, 1.,
					pIcon->label.iWidth * (u1 - u0), pIcon->label.iHeight,
					0., 0.);
				_cairo_dock_set_alpha (1.);
				
				glPopMatrix ();
			}
			
			/**if (pIcon->iQuickInfoTexture != 0)
			{
				double dx = .5 * (pIcon->iQuickInfoWidth & 1);  // on decale la texture pour la coller sur la grille des coordonnees entieres.
				double dy = .5 * (pIcon->iQuickInfoHeight & 1);
				
				glTranslatef (floor (pIcon->fWidth/2 + pIcon->iQuickInfoWidth/2) + dx, dy, 0.);
				
				_cairo_dock_set_alpha (1.);
				_cairo_dock_apply_texture_at_size (pIcon->iQuickInfoTexture,
					pIcon->iQuickInfoWidth,
					pIcon->iQuickInfoHeight);
			}*/
			cairo_dock_draw_icon_overlays_opengl (pIcon, pDesklet->container.fRatio);
			
			glPopMatrix ();
		}
		ic = cairo_dock_get_next_element (ic, pDesklet->icons);
	} while (ic != pFirstDrawnElement);
	
	_cairo_dock_disable_texture ();
}
static void render (cairo_t *pCairoContext, CairoDesklet *pDesklet)
{
	CDPanelParameters *pPanel = (CDPanelParameters *) pDesklet->pRendererData;
	//g_print ("%s(%x)\n", __func__, pPanel);
	if (pPanel == NULL)
		return ;
	
	double fRadius = pPanel->iRadius;
	double fLineWidth = pPanel->iLineWidth;
	double fOffsetX = fRadius + fLineWidth/2;
	double fOffsetY = fLineWidth/2;
	double fFrameWidth = pDesklet->container.iWidth - 2 * fRadius - fLineWidth;
	double fFrameHeight = pDesklet->container.iHeight - fLineWidth;
	// le cadre.
	cairo_set_line_width (pCairoContext, pPanel->iLineWidth);
	
	cairo_move_to (pCairoContext, fOffsetX, fOffsetY);
	
	cairo_rel_curve_to (pCairoContext,
		fFrameWidth/2, 0,
		fFrameWidth/2, pPanel->iMainIconSize,
		fFrameWidth, pPanel->iMainIconSize);
	
	//\_________________ Coin haut droit.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		fRadius, 0,
		fRadius, fRadius);
	cairo_rel_line_to (pCairoContext, 0, fFrameHeight - fRadius * 2 - pPanel->iMainIconSize);
	//\_________________ Coin bas droit.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		0, fRadius,
		-fRadius, fRadius);

	cairo_rel_line_to (pCairoContext, - fFrameWidth, 0);
	//\_________________ Coin bas gauche.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		-fRadius, 0,
		-fRadius, - fRadius);
	cairo_rel_line_to (pCairoContext, 0, - (fFrameHeight - fRadius * 2));
	//\_________________ Coin haut gauche.
	cairo_rel_curve_to (pCairoContext,
		0, 0,
		0, -fRadius,
		fRadius, -fRadius);
	
	cairo_set_source_rgba (pCairoContext, pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], 1.);
	cairo_stroke_preserve (pCairoContext);
	
	cairo_set_source_rgba (pCairoContext, pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], pPanel->fBgColor[3]);
	cairo_fill (pCairoContext);
	
	// les icones.
	Icon *pIcon;
	GList *ic;
	
	pIcon = pDesklet->pIcon;
	if (pIcon && pIcon->image.pSurface != NULL)
	{
		cairo_save (pCairoContext);
		
		cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY);
		
		cairo_dock_apply_image_buffer_surface_with_offset (&pIcon->image, pCairoContext, 0, 0, pIcon->fAlpha);
		
		cairo_dock_draw_icon_overlays_cairo (pIcon, pDesklet->container.fRatio, pCairoContext);
		
		cairo_restore (pCairoContext);
	}
	
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons);
	if (pFirstDrawnElement == NULL)
		return;
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		if (pIcon->image.pSurface != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			cairo_save (pCairoContext);
			
			cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY);
			
			cairo_dock_apply_image_buffer_surface_with_offset (&pIcon->image, pCairoContext, 0, 0, pIcon->fAlpha);
			
			if (pIcon->label.pSurface != NULL)
			{
				cairo_save (pCairoContext);
				
				double fOffsetX = 0., fAlpha;
				if (pIcon->bPointed)
				{
					fAlpha = 1.;
					/**if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2 > pDesklet->container.iWidth)
						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2);
					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->label.iWidth/2 < 0)
						fOffsetX = pIcon->label.iWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
					cairo_set_source_surface (pCairoContext,
						pIcon->label.pSurface,
						fOffsetX + pIcon->fWidth/2 - pIcon->label.iWidth/2,
						-myIconsParam.iLabelSize);*/
					cairo_set_source_surface (pCairoContext,
						pIcon->label.pSurface,
						0.,
						-myIconsParam.iLabelSize);
					cairo_paint_with_alpha (pCairoContext, fAlpha);
				}
				else
				{
					fAlpha = .6;
					if (pIcon->label.iWidth > 2*pIcon->fWidth + 0 * myIconsParam.iLabelSize)
					{
						///fOffsetX = - myIconsParam.iLabelSize;
						cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (fOffsetX,
							0.,
							fOffsetX + 2*pIcon->fWidth + 0*myIconsParam.iLabelSize,
							0.);
						cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							0.,
							0.,
							0.,
							0.,
							fAlpha);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							0.75,
							0.,
							0.,
							0.,
							fAlpha);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							1.,
							0.,
							0.,
							0.,
							0.);
						cairo_set_source_surface (pCairoContext,
							pIcon->label.pSurface,
							fOffsetX,
							-myIconsParam.iLabelSize);
						cairo_mask (pCairoContext, pGradationPattern);
						cairo_pattern_destroy (pGradationPattern);
					}
					else
					{
						///fOffsetX = pIcon->fWidth/2 - pIcon->label.iWidth/2;
						cairo_set_source_surface (pCairoContext,
							pIcon->label.pSurface,
							fOffsetX,
							-myIconsParam.iLabelSize);
						cairo_paint_with_alpha (pCairoContext, fAlpha);
					}
				}
				
				cairo_restore (pCairoContext);
			}
			
			cairo_translate (pCairoContext,
				pIcon->fWidth,
				- pIcon->fHeight/2);  // not ideal, it should be vertically centered.
			cairo_dock_draw_icon_overlays_cairo (pIcon, pDesklet->container.fRatio, pCairoContext);
			
			cairo_restore (pCairoContext);
		}
		ic = cairo_dock_get_next_element (ic, pDesklet->icons);
	}
	while (ic != pFirstDrawnElement);
}
static void render_opengl (CairoDesklet *pDesklet)
{
	CDSlideParameters *pSlide = (CDSlideParameters *) pDesklet->pRendererData;
	if (pSlide == NULL)
		return ;
	
	// le cadre.
	double fRadius = (pSlide->bRoundedRadius ? pSlide->iRadius : 0.);
	double fLineWidth = pSlide->iLineWidth;
	if (fLineWidth != 0 && pSlide->fLineColor[3] != 0)
	{
		cairo_dock_draw_rounded_rectangle_opengl (pDesklet->container.iWidth - 2 * fRadius,
			pDesklet->container.iHeight,
			fRadius,
			fLineWidth,
			pSlide->fLineColor);
	}
	
	glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.);
	
	// les icones.
	double w = pDesklet->container.iWidth - 2 * pSlide->fMargin;
	double h = pDesklet->container.iHeight - 2 * pSlide->fMargin;
	int dh = (h - pSlide->iNbLines * (pSlide->iIconSize + myIconsParam.iLabelSize)) / (pSlide->iNbLines != 1 ? pSlide->iNbLines - 1 : 1);  // ecart entre 2 lignes.
	int dw = (w - pSlide->iNbColumns * pSlide->iIconSize) / pSlide->iNbColumns;  // ecart entre 2 colonnes.
	
	_cairo_dock_enable_texture ();
	_cairo_dock_set_blend_alpha ();
	_cairo_dock_set_alpha (1.);
	
	double x = pSlide->fMargin + dw/2, y = pSlide->fMargin + myIconsParam.iLabelSize;
	int q = 0;
	Icon *pIcon;
	GList *ic;
	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
	{
		pIcon = ic->data;
		if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
			continue;
		
		pIcon->fDrawX = x;
		pIcon->fDrawY = y;
		
		x += pSlide->iIconSize + dw;
		q ++;
		if (q == pSlide->iNbColumns)
		{
			q = 0;
			x = pSlide->fMargin + dw/2;
			y += pSlide->iIconSize + myIconsParam.iLabelSize + dh;
		}
	}
	
	
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons);
	if (pFirstDrawnElement == NULL)
		return;
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		
		if (pIcon->image.iTexture != 0 && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			glPushMatrix ();
			
			glTranslatef (pIcon->fDrawX + pIcon->fWidth/2,
				pDesklet->container.iHeight - pIcon->fDrawY - pIcon->fHeight/2,
				0.);
			_cairo_dock_enable_texture ();  // cairo_dock_draw_icon_overlays_opengl() disable textures
			_cairo_dock_apply_texture_at_size (pIcon->image.iTexture, pIcon->fWidth, pIcon->fHeight);
			
			/// generer une notification ...
			/*if (pIcon->bHasIndicator && g_pIndicatorBuffer.iTexture != 0)
			{
				glPushMatrix ();
				glTranslatef (0., - pIcon->fHeight/2 + g_pIndicatorBuffer.iHeight/2 * pIcon->fWidth / g_pIndicatorBuffer.iWidth, 0.);
				_cairo_dock_apply_texture_at_size (g_pIndicatorBuffer.iTexture, pIcon->fWidth, g_pIndicatorBuffer.iHeight * pIcon->fWidth / g_pIndicatorBuffer.iWidth);
				glPopMatrix ();
			}*/
			
			if (pIcon->label.iTexture != 0)
			{
				glPushMatrix ();
				
				double dx = .5 * (pIcon->label.iWidth & 1);  // on decale la texture pour la coller sur la grille des coordonnees entieres.
				double dy = .5 * (pIcon->label.iHeight & 1);
				double u0 = 0., u1 = 1.;
				double fOffsetX = 0.;
				if (pIcon->bPointed)
				{
					_cairo_dock_set_alpha (1.);
					if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2 > pDesklet->container.iWidth)
						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2);
					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->label.iWidth/2 < 0)
						fOffsetX = pIcon->label.iWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
				}
				else
				{
					_cairo_dock_set_alpha (.6);
					if (pIcon->label.iWidth > pIcon->fWidth + 2 * myIconsParam.iLabelSize)
					{
						fOffsetX = 0.;
						u1 = (double) (pIcon->fWidth + 2 * myIconsParam.iLabelSize) / pIcon->label.iWidth;
					}
				}
				
				glTranslatef (ceil (fOffsetX) + dx, ceil (pIcon->fHeight/2 + pIcon->label.iHeight / 2) + dy, 0.);
				
				glBindTexture (GL_TEXTURE_2D, pIcon->label.iTexture);
				_cairo_dock_apply_current_texture_portion_at_size_with_offset (u0, 0.,
					u1 - u0, 1.,
					pIcon->label.iWidth * (u1 - u0), pIcon->label.iHeight,
					0., 0.);
				_cairo_dock_set_alpha (1.);
				
				glPopMatrix ();
			}
			
			cairo_dock_draw_icon_overlays_opengl (pIcon, pDesklet->container.fRatio);
			
			glPopMatrix ();
		}
		ic = cairo_dock_get_next_element (ic, pDesklet->icons);
	} while (ic != pFirstDrawnElement);
	
	_cairo_dock_disable_texture ();
}
static void render (cairo_t *pCairoContext, CairoDesklet *pDesklet)
{
	CDSlideParameters *pSlide = (CDSlideParameters *) pDesklet->pRendererData;
	//g_print ("%s(%x)\n", __func__, pSlide);
	if (pSlide == NULL)
		return ;
	
	double fRadius = pSlide->iRadius;
	double fLineWidth = pSlide->iLineWidth;
	// le cadre.
	cairo_set_line_width (pCairoContext, pSlide->iLineWidth);
	if (pSlide->bRoundedRadius)
	{
		cairo_translate (pCairoContext, 0., .5 * fLineWidth);
		cairo_dock_draw_rounded_rectangle (pCairoContext,
			fRadius,
			fLineWidth,
			pDesklet->container.iWidth - 2 * fRadius - fLineWidth,
			pDesklet->container.iHeight - 2*fLineWidth);
	}
	else
	{
		cairo_move_to (pCairoContext, 0., 0.);
		cairo_rel_line_to (pCairoContext,
			0.,
			pDesklet->container.iHeight - fRadius - fLineWidth);
		cairo_rel_line_to (pCairoContext,
			pSlide->iRadius,
			pSlide->iRadius);
		cairo_rel_line_to (pCairoContext,
			pDesklet->container.iWidth - fRadius - fLineWidth,
			0.);
	}
	cairo_set_source_rgba (pCairoContext, pSlide->fLineColor[0], pSlide->fLineColor[1], pSlide->fLineColor[2], pSlide->fLineColor[3]);
	cairo_stroke (pCairoContext);
	
	// les icones.
	double w = pDesklet->container.iWidth - 2 * pSlide->fMargin;
	double h = pDesklet->container.iHeight - 2 * pSlide->fMargin;
	int dh = (h - pSlide->iNbLines * (pSlide->iIconSize + myIconsParam.iLabelSize)) / (pSlide->iNbLines != 1 ? pSlide->iNbLines - 1 : 1);  // ecart entre 2 lignes.
	int dw = (w - pSlide->iNbColumns * pSlide->iIconSize) / pSlide->iNbColumns;  // ecart entre 2 colonnes.
	
	// on determine la 1ere icone a tracer : l'icone suivant l'icone pointee.
	
	double x = pSlide->fMargin + dw/2, y = pSlide->fMargin + myIconsParam.iLabelSize;
	int q = 0;
	Icon *pIcon;
	GList *ic;
	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
	{
		pIcon = ic->data;
		if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
			continue;
		
		pIcon->fDrawX = x;
		pIcon->fDrawY = y;
		
		x += pSlide->iIconSize + dw;
		q ++;
		if (q == pSlide->iNbColumns)
		{
			q = 0;
			x = pSlide->fMargin + dw/2;
			y += pSlide->iIconSize + myIconsParam.iLabelSize + dh;
		}
	}
	
	
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons);
	if (pFirstDrawnElement == NULL)
		return;
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		if (pIcon->image.pSurface != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			cairo_save (pCairoContext);
			
			cairo_dock_render_one_icon_in_desklet (pIcon, CAIRO_CONTAINER (pDesklet), pCairoContext, FALSE);
			
			cairo_restore (pCairoContext);
			
			if (pIcon->label.pSurface != NULL)
			{
				cairo_save (pCairoContext);
				cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY);
				
				double fOffsetX = 0., fAlpha;
				if (pIcon->bPointed)
				{
					fAlpha = 1.;
					if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2 > pDesklet->container.iWidth)
						fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2);
					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->label.iWidth/2 < 0)
						fOffsetX = pIcon->label.iWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
					cairo_set_source_surface (pCairoContext,
						pIcon->label.pSurface,
						fOffsetX + pIcon->fWidth/2 - pIcon->label.iWidth/2,
						-myIconsParam.iLabelSize);
					cairo_paint_with_alpha (pCairoContext, fAlpha);
				}
				else
				{
					fAlpha = .6;
					if (pIcon->label.iWidth > pIcon->fWidth + 2 * myIconsParam.iLabelSize)
					{
						fOffsetX = - myIconsParam.iLabelSize;
						cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (fOffsetX,
							0.,
							fOffsetX + pIcon->fWidth + 2*myIconsParam.iLabelSize,
							0.);
						cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							0.,
							0.,
							0.,
							0.,
							fAlpha);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							0.75,
							0.,
							0.,
							0.,
							fAlpha);
						cairo_pattern_add_color_stop_rgba (pGradationPattern,
							1.,
							0.,
							0.,
							0.,
							0.);
						cairo_set_source_surface (pCairoContext,
							pIcon->label.pSurface,
							fOffsetX,
							-myIconsParam.iLabelSize);
						cairo_mask (pCairoContext, pGradationPattern);
						cairo_pattern_destroy (pGradationPattern);
					}
					else
					{
						fOffsetX = pIcon->fWidth/2 - pIcon->label.iWidth/2;
						cairo_set_source_surface (pCairoContext,
							pIcon->label.pSurface,
							fOffsetX,
							-myIconsParam.iLabelSize);
						cairo_paint_with_alpha (pCairoContext, fAlpha);
					}
				}
				
				cairo_restore (pCairoContext);
			}
		}
		ic = cairo_dock_get_next_element (ic, pDesklet->icons);
	}
	while (ic != pFirstDrawnElement);
}
void rendering_draw_slide_in_desklet_opengl (CairoDesklet *pDesklet)
{
	_cairo_dock_define_static_vertex_tab (7);
	CDSlideParameters *pSlide = (CDSlideParameters *) pDesklet->pRendererData;
	if (pSlide == NULL)
		return ;
	
	// le cadre.
	double fRadius = pSlide->iRadius;
	double fLineWidth = pSlide->iLineWidth;
	if (fLineWidth != 0 && pSlide->fLineColor[3] != 0)
	{
		if (pSlide->bRoundedRadius)
		{
			cairo_dock_draw_rounded_rectangle_opengl (fRadius,
				fLineWidth,
				pDesklet->iWidth - 2 * fRadius,
				pDesklet->iHeight,
				0., 0.,
				pSlide->fLineColor);
			glTranslatef (-pDesklet->iWidth/2, -pDesklet->iHeight/2, 0.);
		}
		else
		{
			int i = 0;
			_cairo_dock_set_vertex_xy (0, -pDesklet->iWidth/2, 				+pDesklet->iHeight/2);
			_cairo_dock_set_vertex_xy (1, -pDesklet->iWidth/2, 				-pDesklet->iHeight/2 + fRadius);
			_cairo_dock_set_vertex_xy (2, -pDesklet->iWidth/2 + fRadius, 	-pDesklet->iHeight/2);
			_cairo_dock_set_vertex_xy (3, +pDesklet->iWidth/2, 				-pDesklet->iHeight/2);
			_cairo_dock_set_path_as_current ();
			cairo_dock_draw_current_path_opengl (fLineWidth, pSlide->fLineColor, 4);
		}
	}
	
	glTranslatef (-pDesklet->iWidth/2, -pDesklet->iHeight/2, 0.);
	
	// les icones.
	double w = pDesklet->iWidth - 2 * pSlide->fMargin;
	double h = pDesklet->iHeight - 2 * pSlide->fMargin;
	int dh = (h - pSlide->iNbLines * (pSlide->iIconSize + myLabels.iLabelSize)) / (pSlide->iNbLines != 1 ? pSlide->iNbLines - 1 : 1);  // ecart entre 2 lignes.
	int dw = (w - pSlide->iNbColumns * pSlide->iIconSize) / pSlide->iNbColumns;  // ecart entre 2 colonnes.
	
	_cairo_dock_enable_texture ();
	_cairo_dock_set_blend_alpha ();
	_cairo_dock_set_alpha (1.);
	
	
	double x = pSlide->fMargin + dw/2, y = pSlide->fMargin + myLabels.iLabelSize;
	int q = 0;
	Icon *pIcon;
	GList *ic;
	for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
	{
		pIcon = ic->data;
		
		pIcon->fDrawX = x;
		pIcon->fDrawY = y;
		
		x += pSlide->iIconSize + dw;
		q ++;
		if (q == pSlide->iNbColumns)
		{
			q = 0;
			x = pSlide->fMargin + dw/2;
			y += pSlide->iIconSize + myLabels.iLabelSize + dh;
		}
	}
	
	
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons);
	if (pFirstDrawnElement == NULL)
		return;
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		
		if (pIcon->iIconTexture != 0)
		{
			glPushMatrix ();
			
			glTranslatef (pIcon->fDrawX + pIcon->fWidth/2,
				pDesklet->iHeight - pIcon->fDrawY - pIcon->fHeight/2,
				0.);
			//g_print (" %d) %d;%d %dx%d\n", pIcon->iIconTexture, (int)(pIcon->fDrawX + pIcon->fWidth/2), (int)(pDesklet->iHeight - pIcon->fDrawY - pIcon->fHeight/2), (int)(pIcon->fWidth/2), (int)(pIcon->fHeight/2));
			_cairo_dock_apply_texture_at_size (pIcon->iIconTexture, pIcon->fWidth, pIcon->fHeight);
			
			if (pIcon->bHasIndicator && g_iIndicatorTexture != 0)
			{
				glPushMatrix ();
				glTranslatef (0., - pIcon->fHeight/2 + g_fIndicatorHeight/2 * pIcon->fWidth / g_fIndicatorWidth, 0.);
				_cairo_dock_apply_texture_at_size (g_iIndicatorTexture, pIcon->fWidth, g_fIndicatorHeight * pIcon->fWidth / g_fIndicatorWidth);
				glPopMatrix ();
			}
			
			if (pIcon->iLabelTexture != 0)
			{
				glPushMatrix ();
				
				double u0 = 0., u1 = 1.;
				double fOffsetX = 0.;
				if (pIcon->bPointed)
				{
					_cairo_dock_set_alpha (1.);
					if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->iTextWidth/2 > pDesklet->iWidth)
						fOffsetX = pDesklet->iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->iTextWidth/2);
					if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->iTextWidth/2 < 0)
						fOffsetX = pIcon->iTextWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2);
				}
				else
				{
					_cairo_dock_set_alpha (.6);
					if (pIcon->iTextWidth > pIcon->fWidth + 2 * myLabels.iLabelSize)
					{
						fOffsetX = 0.;
						u1 = (double) (pIcon->fWidth + 2 * myLabels.iLabelSize) / pIcon->iTextWidth;
					}
				}
				
				glTranslatef (fOffsetX, pIcon->fHeight/2 + pIcon->iTextHeight / 2, 0.);
				
				glBindTexture (GL_TEXTURE_2D, pIcon->iLabelTexture);
				_cairo_dock_apply_current_texture_portion_at_size_with_offset (u0, 0.,
					u1 - u0, 1.,
					pIcon->iTextWidth * (u1 - u0), pIcon->iTextHeight,
					0., 0.);
				_cairo_dock_set_alpha (1.);
				
				glPopMatrix ();
			}
			
			if (pIcon->iQuickInfoTexture != 0)
			{
				glTranslatef (0., (- pIcon->fHeight + pIcon->iQuickInfoHeight)/2, 0.);
				
				_cairo_dock_apply_texture_at_size (pIcon->iQuickInfoTexture,
					pIcon->iQuickInfoWidth,
					pIcon->iQuickInfoHeight);
			}
			
			glPopMatrix ();
		}
		
		ic = cairo_dock_get_next_element (ic, pDesklet->icons);
	} while (ic != pFirstDrawnElement);
	
	_cairo_dock_disable_texture ();
}
static void cd_render_opengl (CairoDock *pDock)
{
	//\_____________ On definit notre rectangle.
	double fLineWidth = myDocksParam.iDockLineWidth;
	double fMargin = myDocksParam.iFrameMargin;
	double fRadius = (pDock->iDecorationsHeight + fLineWidth - 2 * myDocksParam.iDockRadius > 0 ? myDocksParam.iDockRadius : (pDock->iDecorationsHeight + fLineWidth) / 2 - 1);
	double fExtraWidth = 2 * fRadius + fLineWidth;
	double fDockWidth;
	double fFrameHeight = pDock->iDecorationsHeight + fLineWidth;
	
	double fDockOffsetX, fDockOffsetY;  // Offset du coin haut gauche du cadre.
	GList *pFirstDrawnElement = pDock->icons;
	if (pFirstDrawnElement == NULL)
		return ;
	if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
	{
		fDockWidth = pDock->container.iWidth - fExtraWidth;
		fDockOffsetX = fLineWidth / 2;
	}
	else
	{
		fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
		Icon *pFirstIcon = pFirstDrawnElement->data;
		fDockOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX + 0 - fMargin - fRadius : fLineWidth / 2);
		if (fDockOffsetX - fLineWidth/2 < 0)
			fDockOffsetX = fLineWidth / 2;
		if (fDockOffsetX + fDockWidth + (2*fRadius + fLineWidth) > pDock->container.iWidth)
			fDockWidth = pDock->container.iWidth - fDockOffsetX - (2*fRadius + fLineWidth);
	}
	
	fDockOffsetY = pDock->iDecorationsHeight + 1.5 * fLineWidth;
	
	double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
	
	//\_____________ On genere les coordonnees du contour.
	const CairoDockGLPath *pFramePath = cairo_dock_generate_rectangle_path (fDockWidth, fFrameHeight, fRadius, FALSE);  // same remark as in cairo rendering
	
	//\_____________ On remplit avec le fond.
	glPushMatrix ();
	cairo_dock_set_container_orientation_opengl (CAIRO_CONTAINER (pDock));
	glTranslatef (fDockOffsetX + (fDockWidth+2*fRadius)/2,
		fDockOffsetY - fFrameHeight/2,
		0.);
	
	_cairo_dock_set_blend_source ();
	cairo_dock_fill_gl_path (pFramePath, pDock->backgroundBuffer.iTexture);
	
	//\_____________ On trace le contour.
	if (fLineWidth != 0)
	{
		glLineWidth (fLineWidth);
		if (myDocksParam.bUseDefaultColors)
			gldi_style_colors_set_line_color (NULL);
		else
			gldi_color_set_opengl (&myDocksParam.fLineColor);
		cairo_dock_stroke_gl_path (pFramePath, TRUE);
	}
	glPopMatrix ();
	
	
	//\_____________ On trace les separateurs physiques.
	GList *ic;
	Icon *pIcon;
	if (my_bPanelPhysicalSeparator)
	{
		glPushMatrix ();
		cairo_dock_set_container_orientation_opengl (CAIRO_CONTAINER (pDock));
		
		double x1, x2, dx, delta, h = pDock->iDecorationsHeight + 2*fLineWidth, h_ = h - fLineWidth;
		for (ic = pDock->icons; ic != NULL; ic = ic->next)
		{
			pIcon = ic->data;
			if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
			{
				x1 = pIcon->fDrawX = pIcon->fX;
				
				pIcon = NULL;
				for (ic = ic->next; ic != NULL; ic = ic->next)
				{
					pIcon = ic->data;
					if (!CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
						break;
				}
				if (ic != NULL)
				{
					pIcon = ic->data;
					x2 = pIcon->fDrawX;
				}
				else
					break;
				
				CairoDockGLPath *pPath = cairo_dock_new_gl_path (2*(iNbCurveSteps+1) + 1, (x1+x2)/2, h, 0., 0.);  // on part du milieu en haut pour que les triangles soient contenus dans l'enveloppe.
				
				dx = MIN (my_fPanelRadius, (x2 - x1) / 2);
				delta = dx + h*tan(my_fPanelInclination)/2;
				if (delta > (x2 - x1) / 2)
					delta = (x2 - x1) / 2;
				
				cairo_dock_gl_path_rel_line_to (pPath,
					-(x2-x1)/2, 0.);
				cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
					dx, 0.,
					delta - dx, -h,
					delta, -h);
				cairo_dock_gl_path_rel_line_to (pPath,
					x2 - x1 - 2*delta, 0.);
				cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
					dx, 0.,
					delta - dx, h,
					delta, h);
				
				glBlendFunc (GL_ONE, GL_ZERO);
				glColor4f (0., 0., 0., 0.);
				cairo_dock_fill_gl_path (pPath, 0);
				glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				
				if (fLineWidth > 0)
				{
					cairo_dock_gl_path_move_to (pPath, x1, h - fLineWidth/2);  // on part du haut/gauche, le nombre de points est ok.
					cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
						dx, 0.,
						delta - dx, -h_,
						delta, -h_);
					cairo_dock_gl_path_rel_line_to (pPath,
						x2 - x1 - 2*delta, 0.);
					cairo_dock_gl_path_rel_curve_to (pPath, iNbCurveSteps,
						dx, 0.,
						delta - dx, h_,
						delta, h_);
					glLineWidth (fLineWidth);
					if (myDocksParam.bUseDefaultColors)
						gldi_style_colors_set_line_color (NULL);
					else
						gldi_color_set_opengl (&myDocksParam.fLineColor);
					cairo_dock_stroke_gl_path (pPath, FALSE);
				}
				
				cairo_dock_free_gl_path (pPath);
			}
		}
		glPopMatrix ();
	}
	
	//\_____________ On dessine la ficelle.
	if (myIconsParam.iStringLineWidth > 0)
		cairo_dock_draw_string_opengl (pDock, myIconsParam.iStringLineWidth, FALSE, FALSE);
	
	
	//\_____________ On dessine les icones.
	pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
	if (pFirstDrawnElement == NULL)
		return;
	
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		
		if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			glPushMatrix ();
			cairo_dock_render_one_icon_opengl (pIcon, pDock, fDockMagnitude, pIcon->bPointed);
			glPopMatrix ();
		}
		
		ic = cairo_dock_get_next_element (ic, pDock->icons);
	} while (ic != pFirstDrawnElement);
}
static void cd_render_optimized (cairo_t *pCairoContext, CairoDock *pDock, GdkRectangle *pArea)
{
	//g_print ("%s ((%d;%d) x (%d;%d) / (%dx%d))\n", __func__, pArea->x, pArea->y, pArea->width, pArea->height, pDock->container.iWidth, pDock->container.iHeight);
	double fLineWidth = myDocksParam.iDockLineWidth;
	double fMargin = myDocksParam.iFrameMargin;
	int iHeight = pDock->container.iHeight;

	//\____________________ On dessine les decorations du fond sur la portion de fenetre.
	cairo_save (pCairoContext);

	double fDockOffsetX, fDockOffsetY;
	if (pDock->container.bIsHorizontal)
	{
		fDockOffsetX = pArea->x;
		fDockOffsetY = (pDock->container.bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	}
	else
	{
		fDockOffsetX = (pDock->container.bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
		fDockOffsetY = pArea->y;
	}

	if (pDock->container.bIsHorizontal)
		cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pArea->width, pDock->iDecorationsHeight);
	else
		cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pDock->iDecorationsHeight, pArea->height);

	fDockOffsetY = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	
	double fRadius = MIN (myDocksParam.iDockRadius, (pDock->iDecorationsHeight + myDocksParam.iDockLineWidth) / 2 - 1);
	double fOffsetX;
	if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
	{
		fOffsetX = fRadius + fLineWidth / 2;
	}
	else
	{
		Icon *pFirstIcon = cairo_dock_get_first_icon (pDock->icons);
		fOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX - fMargin : fRadius + fLineWidth / 2);
	}
	double fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
	double fDeltaXTrapeze = fRadius;
	cairo_dock_render_decorations_in_frame (pCairoContext, pDock, fDockOffsetY, fOffsetX - fDeltaXTrapeze, fDockWidth + 2*fDeltaXTrapeze);
	
	//\____________________ On dessine la partie du cadre qui va bien.
	cairo_new_path (pCairoContext);
	if (myDocksParam.bUseDefaultColors)
		gldi_style_colors_set_line_color (pCairoContext);
	else
		gldi_color_set_cairo (pCairoContext, &myDocksParam.fLineColor);
	cairo_set_line_width (pCairoContext, fLineWidth);
	
	if (pDock->container.bIsHorizontal)
	{
		cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY - fLineWidth / 2);
		cairo_rel_line_to (pCairoContext, pArea->width, 0);
		cairo_stroke (pCairoContext);

		cairo_new_path (pCairoContext);
		cairo_move_to (pCairoContext, fDockOffsetX, (pDock->container.bDirectionUp ? iHeight - fLineWidth / 2 : pDock->iDecorationsHeight + 1.5 * fLineWidth));
		cairo_rel_line_to (pCairoContext, pArea->width, 0);
	}
	else
	{
		cairo_move_to (pCairoContext, fDockOffsetX - fLineWidth / 2, fDockOffsetY);
		cairo_rel_line_to (pCairoContext, 0, pArea->height);
		cairo_stroke (pCairoContext);

		cairo_new_path (pCairoContext);
		cairo_move_to (pCairoContext, (pDock->container.bDirectionUp ? iHeight - fLineWidth / 2 : pDock->iDecorationsHeight + 1.5 * fLineWidth), fDockOffsetY);
		cairo_rel_line_to (pCairoContext, 0, pArea->height);
	}
	cairo_stroke (pCairoContext);

	cairo_restore (pCairoContext);

	//\____________________ On dessine les icones impactees.
	cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);

	GList *pFirstDrawnElement = pDock->icons;
	if (pFirstDrawnElement != NULL)
	{
		double fXMin = (pDock->container.bIsHorizontal ? pArea->x : pArea->y), fXMax = (pDock->container.bIsHorizontal ? pArea->x + pArea->width : pArea->y + pArea->height);
		double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
		double fXLeft, fXRight;
		
		//g_print ("redraw [%d -> %d]\n", (int) fXMin, (int) fXMax);
		Icon *icon;
		GList *ic = pFirstDrawnElement;
		do
		{
			icon = ic->data;

			fXLeft = icon->fDrawX + icon->fScale + 1;
			fXRight = icon->fDrawX + (icon->fWidth - 1) * icon->fScale * icon->fWidthFactor - 1;

			if (fXLeft < fXMax && fXRight > fXMin && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
			{
				cairo_save (pCairoContext);
				//g_print ("dessin optimise de %s [%.2f -> %.2f]\n", icon->cName, fXLeft, fXRight);
				
				icon->fAlpha = 1;
				if (icon->iAnimationState == CAIRO_DOCK_STATE_AVOID_MOUSE)
				{
					icon->fAlpha = 0.7;
				}
				
				cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, icon->bPointed);
				cairo_restore (pCairoContext);
			}

			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
	}
}
static void cd_render (cairo_t *pCairoContext, CairoDock *pDock)
{
	//\____________________ On trace le cadre.
	double fLineWidth = myDocksParam.iDockLineWidth;
	double fMargin = myDocksParam.iFrameMargin;
	double fRadius = (pDock->iDecorationsHeight + fLineWidth - 2 * myDocksParam.iDockRadius > 0 ? myDocksParam.iDockRadius : (pDock->iDecorationsHeight + fLineWidth) / 2 - 1);
	double fExtraWidth = 2 * fRadius + fLineWidth;
	double fDockWidth;
	int sens;
	double fDockOffsetX, fDockOffsetY;  // Offset du coin haut gauche du cadre.
	if (cairo_dock_is_extended_dock (pDock))  // mode panel etendu.
	{
		fDockWidth = pDock->container.iWidth - fExtraWidth;
		fDockOffsetX = fExtraWidth / 2;
	}
	else
	{
		fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
		Icon *pFirstIcon = cairo_dock_get_first_icon (pDock->icons);
		fDockOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX - fMargin : fExtraWidth / 2);
		if (fDockOffsetX < fExtraWidth / 2)
			fDockOffsetX = fExtraWidth / 2;
		if (fDockOffsetX + fDockWidth + fExtraWidth / 2 > pDock->container.iWidth)
			fDockWidth = pDock->container.iWidth - fDockOffsetX - fExtraWidth / 2;
	}
	if (pDock->container.bDirectionUp)
	{
		sens = 1;
		fDockOffsetY = pDock->container.iHeight - pDock->iDecorationsHeight - 1.5 * fLineWidth;
	}
	else
	{
		sens = -1;
		fDockOffsetY = pDock->iDecorationsHeight + 1.5 * fLineWidth;
	}

	cairo_save (pCairoContext);
	double fDeltaXTrapeze = cairo_dock_draw_frame (pCairoContext, fRadius, fLineWidth, fDockWidth, pDock->iDecorationsHeight, fDockOffsetX, fDockOffsetY, sens, 0., pDock->container.bIsHorizontal, FALSE);  // FALSE <=> ignore 'myDocksParam.bRoundedBottomCorner', as bottom rounded corners looks bad for a panel.

	//\____________________ On dessine les decorations dedans.
	fDockOffsetY = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	cairo_dock_render_decorations_in_frame (pCairoContext, pDock, fDockOffsetY, fDockOffsetX - fDeltaXTrapeze, fDockWidth + 2*fDeltaXTrapeze);

	//\____________________ On dessine le cadre.
	if (fLineWidth > 0)
	{
		cairo_set_line_width (pCairoContext, fLineWidth);
		if (myDocksParam.bUseDefaultColors)
			gldi_style_colors_set_line_color (pCairoContext);
		else
			gldi_color_set_cairo (pCairoContext, &myDocksParam.fLineColor);
		cairo_stroke (pCairoContext);
	}
	else
		cairo_new_path (pCairoContext);
	cairo_restore (pCairoContext);
	
	//\____________________ On dessine les separateurs physiques.
	GList *ic;
	Icon *pIcon;
	if (my_bPanelPhysicalSeparator)
	{
		cairo_save (pCairoContext);
		if (pDock->container.bIsHorizontal)
		{
			if (! pDock->container.bDirectionUp)
			{
				cairo_translate (pCairoContext, 0., pDock->container.iHeight);
				cairo_scale (pCairoContext, 1., -1.);
			}
		}
		else
		{
			cairo_translate (pCairoContext, pDock->container.iHeight/2., pDock->container.iWidth/2.);
			cairo_rotate (pCairoContext, G_PI/2);
			if (pDock->container.bDirectionUp)
				cairo_scale (pCairoContext, 1., -1.);
			cairo_translate (pCairoContext, -pDock->container.iWidth/2., -pDock->container.iHeight/2.);
		}
		
		double x1, x2, dx, delta, h = pDock->iDecorationsHeight + 2*fLineWidth, h_ = h - fLineWidth;
		for (ic = pDock->icons; ic != NULL; ic = ic->next)
		{
			pIcon = ic->data;
			if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
			{
				x1 = pIcon->fDrawX = pIcon->fX;
				
				pIcon = NULL;
				for (ic = ic->next; ic != NULL; ic = ic->next)
				{
					pIcon = ic->data;
					if (!CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
						break;
				}
				if (ic != NULL)
				{
					pIcon = ic->data;
					x2 = pIcon->fDrawX;
				}
				else
					break;
				
				dx = MIN (my_fPanelRadius, (x2 - x1) / 2);
				delta = dx + h*tan(my_fPanelInclination)/2;
				if (delta > (x2 - x1) / 2)
					delta = (x2 - x1) / 2;
				
				cairo_move_to (pCairoContext, x1, pDock->iMaxDockHeight - h);
				cairo_rel_curve_to (pCairoContext,
					dx, 0.,
					delta - dx, h,
					delta, h);
				cairo_rel_line_to (pCairoContext,
					x2 - x1 - 2*delta, 0.);
				cairo_rel_curve_to (pCairoContext,
					dx, 0.,
					delta - dx, -h,
					delta, -h);
				cairo_close_path (pCairoContext);
				
				cairo_set_operator (pCairoContext, CAIRO_OPERATOR_DEST_OUT);
				cairo_set_source_rgba (pCairoContext, 0.0, 0.0, 0.0, 1.0);
				cairo_fill (pCairoContext);
				
				if (fLineWidth > 0)
				{
					cairo_move_to (pCairoContext, x1, pDock->iMaxDockHeight - h_ - fLineWidth/2);
					cairo_rel_curve_to (pCairoContext,
						dx, 0.,
						delta - dx, h_,
						delta, h_);
					cairo_rel_line_to (pCairoContext,
						x2 - x1 - 2*delta, 0.);
					cairo_rel_curve_to (pCairoContext,
						dx, 0.,
						delta - dx, -h_,
						delta, -h_);
					
					cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
					cairo_set_line_width (pCairoContext, fLineWidth);
					if (myDocksParam.bUseDefaultColors)
						gldi_style_colors_set_line_color (pCairoContext);
					else
						gldi_color_set_cairo (pCairoContext, &myDocksParam.fLineColor);
					cairo_stroke (pCairoContext);
				}
			}
		}
		cairo_restore (pCairoContext);
	}
	
	//\____________________ On dessine la ficelle qui les joint.
	if (myIconsParam.iStringLineWidth > 0)
		cairo_dock_draw_string (pCairoContext, pDock, myIconsParam.iStringLineWidth, FALSE, FALSE);

	//\____________________ On dessine les icones et les etiquettes, en tenant compte de l'ordre pour dessiner celles en arriere-plan avant celles en avant-plan.
	GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
	if (pFirstDrawnElement == NULL)
		return;
	
	double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);  // * pDock->fMagnitudeMax
	ic = pFirstDrawnElement;
	do
	{
		pIcon = ic->data;
		
		if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
		{
			cairo_save (pCairoContext);
			cairo_dock_render_one_icon (pIcon, pDock, pCairoContext, fDockMagnitude, pIcon->bPointed);
			cairo_restore (pCairoContext);
		}
		ic = cairo_dock_get_next_element (ic, pDock->icons);
	} while (ic != pFirstDrawnElement);
}
void cd_rendering_render_optimized_3D_plane (cairo_t *pCairoContext, CairoDock *pDock, GdkRectangle *pArea)
{
	//g_print ("%s ((%d;%d) x (%d;%d) / (%dx%d))\n", __func__, pArea->x, pArea->y, pArea->width, pArea->height, pDock->iCurrentWidth, pDock->iCurrentHeight);
	double fLineWidth = g_iDockLineWidth;
	double fMargin = g_iFrameMargin;
	int iWidth = pDock->iCurrentWidth;
	int iHeight = pDock->iCurrentHeight;
	
	//\____________________ On dessine les decorations du fond sur la portion de fenetre.
	cairo_save (pCairoContext);
	
	double fDockOffsetX, fDockOffsetY;
	if (pDock->bHorizontalDock)
	{
		fDockOffsetX = pArea->x;
		fDockOffsetY = (pDock->bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	}
	else
	{
		fDockOffsetX = (pDock->bDirectionUp ? iHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
		fDockOffsetY = pArea->y;
	}
	
	cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY);
	if (pDock->bHorizontalDock)
		cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pArea->width, pDock->iDecorationsHeight);
	else
		cairo_rectangle (pCairoContext, fDockOffsetX, fDockOffsetY, pDock->iDecorationsHeight, pArea->height);
	
	cairo_dock_render_decorations_in_frame (pCairoContext, pDock, pDock->bHorizontalDock ? fDockOffsetY : fDockOffsetX);
	
	
	//\____________________ On dessine la partie du cadre qui va bien.
	cairo_new_path (pCairoContext);
	
	if (pDock->bHorizontalDock)
	{
		cairo_set_line_width (pCairoContext, fLineWidth);
		cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY - 0.5*fLineWidth);
		cairo_rel_line_to (pCairoContext, pArea->width, 0);
		cairo_set_source_rgba (pCairoContext, g_fLineColor[0], g_fLineColor[1], g_fLineColor[2], g_fLineColor[3]);
		cairo_stroke (pCairoContext);
		
		cairo_new_path (pCairoContext);
		cairo_move_to (pCairoContext, fDockOffsetX, (pDock->bDirectionUp ? iHeight - 0.5*fLineWidth : pDock->iDecorationsHeight + 1.5 * fLineWidth));
		cairo_rel_line_to (pCairoContext, pArea->width, 0);
	}
	else
	{
		cairo_move_to (pCairoContext, fDockOffsetX - .5*fLineWidth, fDockOffsetY);
		cairo_rel_line_to (pCairoContext, 0, pArea->height);
		cairo_set_line_width (pCairoContext, fLineWidth);
		cairo_set_source_rgba (pCairoContext, g_fLineColor[0], g_fLineColor[1], g_fLineColor[2], g_fLineColor[3]);
		cairo_stroke (pCairoContext);
		
		cairo_new_path (pCairoContext);
		cairo_move_to (pCairoContext, (pDock->bDirectionUp ? iHeight - fLineWidth / 2 : pDock->iDecorationsHeight + 1.5 * fLineWidth), fDockOffsetY);
		cairo_rel_line_to (pCairoContext, 0, pArea->height);
	}
	cairo_set_line_width (pCairoContext, fLineWidth);
	cairo_set_source_rgba (pCairoContext, g_fLineColor[0], g_fLineColor[1], g_fLineColor[2], g_fLineColor[3]);
	cairo_stroke (pCairoContext);
	
	cairo_restore (pCairoContext);
	
	//\____________________ On dessine les icones impactees.
	GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
	if (pFirstDrawnElement != NULL)
	{
		double fXMin = (pDock->bHorizontalDock ? pArea->x : pArea->y), fXMax = (pDock->bHorizontalDock ? pArea->x + pArea->width : pArea->y + pArea->height);
		double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
		double fRatio = (pDock->iRefCount == 0 ? 1 : g_fSubDockSizeRatio);
		fRatio = pDock->fRatio;
		double fXLeft, fXRight;
		Icon *icon;
		GList *ic = pFirstDrawnElement;
		
		if (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
		{
			cairo_set_line_cap (pCairoContext, CAIRO_LINE_CAP_SQUARE);
			do
			{
				icon = ic->data;
				
				if (CAIRO_DOCK_IS_SEPARATOR (icon) && icon->acFileName == NULL)
				{
					if (_cd_separator_is_impacted (icon, pDock, fXMin, fXMax, TRUE, (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)))
					{
						cairo_save (pCairoContext);
						cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, TRUE);
						cairo_restore (pCairoContext);
					}
				}
				
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
			
			do
			{
				icon = ic->data;
				if (! CAIRO_DOCK_IS_SEPARATOR (icon) || icon->acFileName != NULL)
				{
					fXLeft = icon->fDrawX + icon->fScale + 1;
					fXRight = icon->fDrawX + (icon->fWidth - 1) * icon->fScale * icon->fWidthFactor - 1;
					
					if (fXLeft <= fXMax && floor (fXRight) > fXMin)
					{
						if (icon->iAnimationType == CAIRO_DOCK_AVOID_MOUSE)
							icon->fAlpha = 0.4;
						else if (icon->fDrawX >= 0 && icon->fDrawX + icon->fWidth * icon->fScale <= pDock->iCurrentWidth)
							icon->fAlpha = 1;
						else
							icon->fAlpha = .25;
						
						cairo_save (pCairoContext);
						
						cairo_dock_render_one_icon (icon, pCairoContext, pDock->bHorizontalDock, fRatio, fDockMagnitude, pDock->bUseReflect, TRUE, pDock->iCurrentWidth, pDock->bDirectionUp);
						
						cairo_restore (pCairoContext);
					}
				}
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
			
			if (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
			{
				do
				{
					icon = ic->data;
					
					if (CAIRO_DOCK_IS_SEPARATOR (icon) && icon->acFileName == NULL)
					{
						if (_cd_separator_is_impacted (icon, pDock, fXMin, fXMax, FALSE, (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)))
						{
							cairo_save (pCairoContext);
							cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, FALSE);
							cairo_restore (pCairoContext);
						}
					}
					
					ic = cairo_dock_get_next_element (ic, pDock->icons);
				} while (ic != pFirstDrawnElement);
			}
		}
		else
		{
			do
			{
				icon = ic->data;
				fXLeft = icon->fDrawX + icon->fScale + 1;
				fXRight = icon->fDrawX + (icon->fWidth - 1) * icon->fScale * icon->fWidthFactor - 1;
				
				if (fXLeft <= fXMax && floor (fXRight) > fXMin)
				{
					if (icon->iAnimationType == CAIRO_DOCK_AVOID_MOUSE)
						icon->fAlpha = 0.4;
					else if (icon->fDrawX >= 0 && icon->fDrawX + icon->fWidth * icon->fScale <= pDock->iCurrentWidth)
						icon->fAlpha = 1;
					else
						icon->fAlpha = .25;
					
					cairo_save (pCairoContext);
					
					cairo_dock_render_one_icon (icon, pCairoContext, pDock->bHorizontalDock, fRatio, fDockMagnitude, pDock->bUseReflect, TRUE, pDock->iCurrentWidth, pDock->bDirectionUp);
					
					cairo_restore (pCairoContext);
				}
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
		}
	}
}
void cd_rendering_render_3D_plane (cairo_t *pCairoContext, CairoDock *pDock)
{
	//\____________________ On trace le cadre.
	double fLineWidth = g_iDockLineWidth;
	double fMargin = g_iFrameMargin;
	double fRadius = (pDock->iDecorationsHeight + fLineWidth - 2 * g_iDockRadius > 0 ? g_iDockRadius : (pDock->iDecorationsHeight + fLineWidth) / 2 - 1);
	double fDockWidth = cairo_dock_get_current_dock_width_linear (pDock);
	
	int sens;
	double fDockOffsetX, fDockOffsetY;  // Offset du coin haut gauche du cadre.
	Icon *pFirstIcon = cairo_dock_get_first_drawn_icon (pDock);
	fDockOffsetX = (pFirstIcon != NULL ? pFirstIcon->fX + 0 - fMargin : fRadius + fLineWidth / 2);
	if (pDock->bDirectionUp)
	{
		sens = 1;
		fDockOffsetY = pDock->iCurrentHeight - pDock->iDecorationsHeight - 1.5 * fLineWidth;
	}
	else
	{
		sens = -1;
		fDockOffsetY = pDock->iDecorationsHeight + 1.5 * fLineWidth;
	}
	
	cairo_save (pCairoContext);
	
	double fInclinationOnHorizon = (fDockWidth / 2) / iVanishingPointY;
        cairo_dock_draw_frame (pCairoContext, fRadius, fLineWidth, fDockWidth, pDock->iDecorationsHeight, fDockOffsetX, fDockOffsetY, sens, fInclinationOnHorizon, pDock->bHorizontalDock);  // fLineWidth
	
	//\____________________ On dessine les decorations dedans.
	fDockOffsetY = (pDock->bDirectionUp ? pDock->iCurrentHeight - pDock->iDecorationsHeight - fLineWidth : fLineWidth);
	cairo_dock_render_decorations_in_frame (pCairoContext, pDock, fDockOffsetY);
	
	//\____________________ On dessine le cadre.
	if (fLineWidth > 0)
	{
		cairo_set_line_width (pCairoContext, fLineWidth);
		cairo_set_source_rgba (pCairoContext, g_fLineColor[0], g_fLineColor[1], g_fLineColor[2], g_fLineColor[3]);
		cairo_stroke (pCairoContext);
	}
	else
		cairo_new_path (pCairoContext);
	
	/// donner un effet d'epaisseur => chaud du slip avec les separateurs physiques !
	
	
	cairo_restore (pCairoContext);
	
	//\____________________ On dessine la ficelle qui les joint.
	if (g_iStringLineWidth > 0)
		cairo_dock_draw_string (pCairoContext, pDock, g_iStringLineWidth, FALSE, (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR));
	
	//\____________________ On dessine les icones et les etiquettes, en tenant compte de l'ordre pour dessiner celles en arriere-plan avant celles en avant-plan.
	double fRatio = (pDock->iRefCount == 0 ? 1 : g_fSubDockSizeRatio);
	fRatio = pDock->fRatio;
	GList *pFirstDrawnElement = (pDock->pFirstDrawnElement != NULL ? pDock->pFirstDrawnElement : pDock->icons);
	if (pFirstDrawnElement == NULL)
		return ;
		
	double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
	Icon *icon;
	GList *ic = pFirstDrawnElement;
	
	if (my_iDrawSeparator3D == CD_FLAT_SEPARATOR || my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
	{
		cairo_set_line_cap (pCairoContext, CAIRO_LINE_CAP_SQUARE);
		do
		{
			icon = ic->data;
			
			if (icon->acFileName == NULL && CAIRO_DOCK_IS_SEPARATOR (icon))
			{
				cairo_save (pCairoContext);
				cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, TRUE);
				cairo_restore (pCairoContext);
			}
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
		
		do
		{
			icon = ic->data;
			
			if (icon->acFileName != NULL || ! CAIRO_DOCK_IS_SEPARATOR (icon))
			{
				cairo_save (pCairoContext);
				cairo_dock_render_one_icon (icon, pCairoContext, pDock->bHorizontalDock, fRatio, fDockMagnitude, pDock->bUseReflect, TRUE, pDock->iCurrentWidth, pDock->bDirectionUp);
				cairo_restore (pCairoContext);
			}
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
		
		if (my_iDrawSeparator3D == CD_PHYSICAL_SEPARATOR)
		{
			do
			{
				icon = ic->data;
				
				if (icon->acFileName == NULL && CAIRO_DOCK_IS_SEPARATOR (icon))
				{
					cairo_save (pCairoContext);
					cd_rendering_draw_3D_separator (icon, pCairoContext, pDock, pDock->bHorizontalDock, FALSE);
					cairo_restore (pCairoContext);
				}
				
				ic = cairo_dock_get_next_element (ic, pDock->icons);
			} while (ic != pFirstDrawnElement);
		}
	}
	else
	{
		do
		{
			icon = ic->data;
			
			cairo_save (pCairoContext);
			cairo_dock_render_one_icon (icon, pCairoContext, pDock->bHorizontalDock, fRatio, fDockMagnitude, pDock->bUseReflect, TRUE, pDock->iCurrentWidth, pDock->bDirectionUp);
			cairo_restore (pCairoContext);
			
			ic = cairo_dock_get_next_element (ic, pDock->icons);
		} while (ic != pFirstDrawnElement);
	}
}