/**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include "cairo-dock-icon-facility.h" // cairo_dock_get_next_element
#include "cairo-dock-dock-factory.h"
#include "cairo-dock-dock-facility.h" // cairo_dock_get_first_drawn_element_linear
#include "cairo-dock-animations.h" // cairo_dock_calculate_magnitude
#include "cairo-dock-log.h"
#include "cairo-dock-dock-manager.h" // myDocksParam
#include "cairo-dock-applications-manager.h"
#include "cairo-dock-separator-manager.h"
#include "cairo-dock-applet-manager.h"
#include "cairo-dock-backends-manager.h"
#include "cairo-dock-container.h"
#include "cairo-dock-image-buffer.h"
#include "cairo-dock-desktop-manager.h" // g_pFakeTransparencyDesktopBg
#include "cairo-dock-windows-manager.h"
#include "cairo-dock-style-manager.h"
#include "cairo-dock-draw-opengl.h" // pour cairo_dock_render_one_icon
#include "cairo-dock-overlay.h" // cairo_dock_draw_icon_overlays_cairo
#include "cairo-dock-draw.h"
extern CairoDockImageBuffer g_pVisibleZoneBuffer;
extern GldiDesktopBackground *g_pFakeTransparencyDesktopBg;
extern gboolean g_bUseOpenGL;
cairo_t * cairo_dock_create_drawing_context_generic (GldiContainer *pContainer)
{
return gdk_cairo_create (gldi_container_get_gdk_window (pContainer));
}
cairo_t *cairo_dock_create_drawing_context_on_container (GldiContainer *pContainer)
{
cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (pContainer);
g_return_val_if_fail (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS, NULL);
cairo_dock_init_drawing_context_on_container (pContainer, pCairoContext);
return pCairoContext;
}
void cairo_dock_init_drawing_context_on_container (GldiContainer *pContainer, cairo_t *pCairoContext)
{
if (g_pFakeTransparencyDesktopBg && g_pFakeTransparencyDesktopBg->pSurface)
{
if (pContainer->bIsHorizontal)
cairo_set_source_surface (pCairoContext, g_pFakeTransparencyDesktopBg->pSurface, - pContainer->iWindowPositionX, - pContainer->iWindowPositionY);
else
cairo_set_source_surface (pCairoContext, g_pFakeTransparencyDesktopBg->pSurface, - pContainer->iWindowPositionY, - pContainer->iWindowPositionX);
}
else
cairo_set_source_rgba (pCairoContext, 0.0, 0.0, 0.0, 0.0);
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_SOURCE);
cairo_paint (pCairoContext);
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
}
cairo_t *cairo_dock_create_drawing_context_on_area (GldiContainer *pContainer, GdkRectangle *pArea, double *fBgColor)
{
cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (pContainer);
g_return_val_if_fail (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS, pCairoContext);
if (pArea != NULL && (pArea->x > 0 || pArea->y > 0))
{
cairo_rectangle (pCairoContext,
pArea->x,
pArea->y,
pArea->width,
pArea->height);
cairo_clip (pCairoContext);
}
///if (myContainersParam.bUseFakeTransparency)
///{
if (g_pFakeTransparencyDesktopBg && g_pFakeTransparencyDesktopBg->pSurface)
{
if (pContainer->bIsHorizontal)
cairo_set_source_surface (pCairoContext, g_pFakeTransparencyDesktopBg->pSurface, - pContainer->iWindowPositionX, - pContainer->iWindowPositionY);
else
cairo_set_source_surface (pCairoContext, g_pFakeTransparencyDesktopBg->pSurface, - pContainer->iWindowPositionY, - pContainer->iWindowPositionX);
}
/**else
cairo_set_source_rgba (pCairoContext, 0.8, 0.8, 0.8, 0.0);
}*/
else if (fBgColor != NULL)
cairo_set_source_rgba (pCairoContext, fBgColor[0], fBgColor[1], fBgColor[2], fBgColor[3]);
else
cairo_set_source_rgba (pCairoContext, 0.0, 0.0, 0.0, 0.0);
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_SOURCE);
cairo_paint (pCairoContext);
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
return pCairoContext;
}
double cairo_dock_calculate_extra_width_for_trapeze (double fFrameHeight, double fInclination, double fRadius, double fLineWidth)
{
if (2 * fRadius > fFrameHeight + fLineWidth)
fRadius = (fFrameHeight + fLineWidth) / 2 - 1;
double cosa = 1. / sqrt (1 + fInclination * fInclination);
double sina = fInclination * cosa;
double fExtraWidth = fInclination * (fFrameHeight - (FALSE ? 2 : 1-cosa) * fRadius) + fRadius * (FALSE ? 1 : sina);
return (2 * fExtraWidth + fLineWidth);
/**double fDeltaXForLoop = fInclination * (fFrameHeight + fLineWidth - (myDocksParam.bRoundedBottomCorner ? 2 : 1) * fRadius);
double fDeltaCornerForLoop = fRadius * cosa + (myDocksParam.bRoundedBottomCorner ? fRadius * (1 + sina) * fInclination : 0);
return (2 * (fLineWidth/2 + fDeltaXForLoop + fDeltaCornerForLoop + myDocksParam.iFrameMargin));*/
}
/**void cairo_dock_draw_rounded_rectangle (cairo_t *pCairoContext, double fRadius, double fLineWidth, double fFrameWidth, double fFrameHeight)
{
if (2*fRadius > fFrameHeight + fLineWidth)
fRadius = (fFrameHeight + fLineWidth) / 2 - 1;
double fDockOffsetX = fRadius + fLineWidth/2;
double fDockOffsetY = 0.;
cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY);
cairo_rel_line_to (pCairoContext, fFrameWidth, 0);
//\_________________ Coin haut droit.
cairo_rel_curve_to (pCairoContext,
0, 0,
fRadius, 0,
fRadius, fRadius);
cairo_rel_line_to (pCairoContext, 0, (fFrameHeight + fLineWidth - fRadius * 2));
//\_________________ 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 - fLineWidth + fRadius * 2));
//\_________________ Coin haut gauche.
cairo_rel_curve_to (pCairoContext,
0, 0,
0, -fRadius,
fRadius, -fRadius);
if (fRadius < 1)
cairo_close_path (pCairoContext);
}*/
void cairo_dock_draw_rounded_rectangle (cairo_t *pCairoContext, double fRadius, double fLineWidth, double fFrameWidth, double fFrameHeight)
{
if (2*fRadius > fFrameHeight + fLineWidth)
fRadius = (fFrameHeight + fLineWidth) / 2 - 1;
double fDockOffsetX = fRadius + fLineWidth/2;
double fDockOffsetY = fLineWidth/2;
cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY);
cairo_rel_line_to (pCairoContext, fFrameWidth, 0);
//\_________________ Coin haut droit.
cairo_arc (pCairoContext,
fDockOffsetX + fFrameWidth, fDockOffsetY + fRadius,
fRadius,
-G_PI/2, 0.);
cairo_rel_line_to (pCairoContext, 0, (fFrameHeight + fLineWidth - fRadius * 2));
//\_________________ Coin bas droit.
cairo_arc (pCairoContext,
fDockOffsetX + fFrameWidth, fDockOffsetY + fFrameHeight - fLineWidth/2 - fRadius,
fRadius,
0., G_PI/2);
cairo_rel_line_to (pCairoContext, - fFrameWidth, 0);
//\_________________ Coin bas gauche.
cairo_arc (pCairoContext,
fDockOffsetX, fDockOffsetY + fFrameHeight - fLineWidth/2 - fRadius,
fRadius,
G_PI/2, G_PI);
cairo_rel_line_to (pCairoContext, 0, (- fFrameHeight - fLineWidth + fRadius * 2));
//\_________________ Coin haut gauche.
cairo_arc (pCairoContext,
fDockOffsetX, fDockOffsetY + fRadius,
fRadius,
G_PI, -G_PI/2);
if (fRadius < 1)
cairo_close_path (pCairoContext);
}
static double cairo_dock_draw_frame_horizontal (cairo_t *pCairoContext, double fRadius, double fLineWidth, double fFrameWidth, double fFrameHeight, double fDockOffsetX, double fDockOffsetY, int sens, double fInclination, gboolean bRoundedBottomCorner) // la largeur est donnee par rapport "au fond".
{
if (2*fRadius > fFrameHeight + fLineWidth)
fRadius = (fFrameHeight + fLineWidth) / 2 - 1;
double cosa = 1. / sqrt (1 + fInclination * fInclination);
double sina = cosa * fInclination;
double fDeltaXForLoop = fInclination * (fFrameHeight + fLineWidth - (bRoundedBottomCorner ? 2 : 1-sina) * fRadius);
cairo_move_to (pCairoContext, fDockOffsetX, fDockOffsetY);
cairo_rel_line_to (pCairoContext, fFrameWidth, 0);
//\_________________ Coin haut droit.
cairo_rel_curve_to (pCairoContext,
0, 0,
fRadius * (1. / cosa - fInclination), 0,
fRadius * cosa, sens * fRadius * (1 - sina));
cairo_rel_line_to (pCairoContext, fDeltaXForLoop, sens * (fFrameHeight + fLineWidth - fRadius * (bRoundedBottomCorner ? 2 : 1 - sina)));
//\_________________ Coin bas droit.
if (bRoundedBottomCorner)
cairo_rel_curve_to (pCairoContext,
0, 0,
fRadius * (1 + sina) * fInclination, sens * fRadius * (1 + sina),
-fRadius * cosa, sens * fRadius * (1 + sina));
cairo_rel_line_to (pCairoContext, - fFrameWidth - 2 * fDeltaXForLoop - (bRoundedBottomCorner ? 0 : 2 * fRadius * cosa), 0);
//\_________________ Coin bas gauche.
if (bRoundedBottomCorner)
cairo_rel_curve_to (pCairoContext,
0, 0,
-fRadius * (fInclination + 1. / cosa), 0,
-fRadius * cosa, -sens * fRadius * (1 + sina));
cairo_rel_line_to (pCairoContext, fDeltaXForLoop, sens * (- fFrameHeight - fLineWidth + fRadius * (bRoundedBottomCorner ? 2 : 1 - sina)));
//\_________________ Coin haut gauche.
cairo_rel_curve_to (pCairoContext,
0, 0,
fRadius * (1 - sina) * fInclination, -sens * fRadius * (1 - sina),
fRadius * cosa, -sens * fRadius * (1 - sina));
if (fRadius < 1)
cairo_close_path (pCairoContext);
//return fDeltaXForLoop + fRadius * cosa;
return fInclination * (fFrameHeight - (FALSE ? 2 : 1-sina) * fRadius) + fRadius * (FALSE ? 1 : cosa);
}
static double cairo_dock_draw_frame_vertical (cairo_t *pCairoContext, double fRadius, double fLineWidth, double fFrameWidth, double fFrameHeight, double fDockOffsetX, double fDockOffsetY, int sens, double fInclination, gboolean bRoundedBottomCorner)
{
if (2*fRadius > fFrameHeight + fLineWidth)
fRadius = (fFrameHeight + fLineWidth) / 2 - 1;
double fDeltaXForLoop = fInclination * (fFrameHeight + fLineWidth - (bRoundedBottomCorner ? 2 : 1) * fRadius);
double cosa = 1. / sqrt (1 + fInclination * fInclination);
double sina = cosa * fInclination;
cairo_move_to (pCairoContext, fDockOffsetY, fDockOffsetX);
cairo_rel_line_to (pCairoContext, 0, fFrameWidth);
//\_________________ Coin haut droit.
cairo_rel_curve_to (pCairoContext,
0, 0,
0, fRadius * (1. / cosa - fInclination),
sens * fRadius * (1 - sina), fRadius * cosa);
cairo_rel_line_to (pCairoContext, sens * (fFrameHeight + fLineWidth - fRadius * (bRoundedBottomCorner ? 2 : 1 - sina)), fDeltaXForLoop);
//\_________________ Coin bas droit.
if (bRoundedBottomCorner)
cairo_rel_curve_to (pCairoContext,
0, 0,
sens * fRadius * (1 + sina), fRadius * (1 + sina) * fInclination,
sens * fRadius * (1 + sina), -fRadius * cosa);
cairo_rel_line_to (pCairoContext, 0, - fFrameWidth - 2 * fDeltaXForLoop - (bRoundedBottomCorner ? 0 : 2 * fRadius * cosa));
//\_________________ Coin bas gauche.
if (bRoundedBottomCorner)
cairo_rel_curve_to (pCairoContext,
0, 0,
0, -fRadius * (fInclination + 1. / cosa),
-sens * fRadius * (1 + sina), -fRadius * cosa);
cairo_rel_line_to (pCairoContext, sens * (- fFrameHeight - fLineWidth + fRadius * (bRoundedBottomCorner ? 2 : 1)), fDeltaXForLoop);
//\_________________ Coin haut gauche.
cairo_rel_curve_to (pCairoContext,
0, 0,
-sens * fRadius * (1 - sina), fRadius * (1 - sina) * fInclination,
-sens * fRadius * (1 - sina), fRadius * cosa);
if (fRadius < 1)
cairo_close_path (pCairoContext);
//return fDeltaXForLoop + fRadius * cosa;
return fInclination * (fFrameHeight - (FALSE ? 2 : 1-sina) * fRadius) + fRadius * (FALSE ? 1 : cosa);
}
double cairo_dock_draw_frame (cairo_t *pCairoContext, double fRadius, double fLineWidth, double fFrameWidth, double fFrameHeight, double fDockOffsetX, double fDockOffsetY, int sens, double fInclination, gboolean bHorizontal, gboolean bRoundedBottomCorner)
{
if (bHorizontal)
return cairo_dock_draw_frame_horizontal (pCairoContext, fRadius, fLineWidth, fFrameWidth, fFrameHeight, fDockOffsetX, fDockOffsetY, sens, fInclination, bRoundedBottomCorner);
else
return cairo_dock_draw_frame_vertical (pCairoContext, fRadius, fLineWidth, fFrameWidth, fFrameHeight, fDockOffsetX, fDockOffsetY, sens, fInclination, bRoundedBottomCorner);
}
void cairo_dock_render_decorations_in_frame (cairo_t *pCairoContext, CairoDock *pDock, double fOffsetY, double fOffsetX, double fWidth)
{
//g_print ("%.2f\n", pDock->fDecorationsOffsetX);
if (pDock->backgroundBuffer.pSurface == NULL)
return ;
cairo_save (pCairoContext);
if (pDock->container.bIsHorizontal)
{
cairo_translate (pCairoContext, fOffsetX, fOffsetY);
cairo_scale (pCairoContext, (double)fWidth / pDock->backgroundBuffer.iWidth, (double)pDock->iDecorationsHeight / pDock->backgroundBuffer.iHeight); // pDock->container.iWidth
}
else
{
cairo_translate (pCairoContext, fOffsetY, fOffsetX);
cairo_scale (pCairoContext, (double)pDock->iDecorationsHeight / pDock->backgroundBuffer.iHeight, (double)fWidth / pDock->backgroundBuffer.iWidth);
}
cairo_dock_draw_surface (pCairoContext, pDock->backgroundBuffer.pSurface, pDock->backgroundBuffer.iWidth, pDock->backgroundBuffer.iHeight, pDock->container.bDirectionUp, pDock->container.bIsHorizontal, -1.); // -1 <=> fill_preserve
cairo_restore (pCairoContext);
}
void cairo_dock_set_icon_scale_on_context (cairo_t *pCairoContext, Icon *icon, gboolean bIsHorizontal, G_GNUC_UNUSED double fRatio, gboolean bDirectionUp)
{
if (bIsHorizontal)
{
if (myIconsParam.bConstantSeparatorSize && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
{
cairo_translate (pCairoContext,
icon->fWidthFactor * icon->fWidth * (icon->fScale - 1) / 2,
(bDirectionUp ? 1 * icon->fHeightFactor * icon->fHeight * (icon->fScale - 1) : 0));
cairo_scale (pCairoContext,
icon->fWidth / icon->image.iWidth * icon->fWidthFactor/**fRatio * icon->fWidthFactor / (1 + myIconsParam.fAmplitude)*/,
icon->fHeight / icon->image.iHeight * icon->fHeightFactor/**fRatio * icon->fHeightFactor / (1 + myIconsParam.fAmplitude)*/);
}
else
cairo_scale (pCairoContext,
icon->fWidth / icon->image.iWidth * icon->fWidthFactor * icon->fScale/**fRatio * icon->fWidthFactor * icon->fScale / (1 + myIconsParam.fAmplitude)*/ * icon->fGlideScale,
icon->fHeight / icon->image.iHeight * icon->fHeightFactor * icon->fScale/**fRatio * icon->fHeightFactor * icon->fScale / (1 + myIconsParam.fAmplitude)*/ * icon->fGlideScale);
}
else
{
if (myIconsParam.bConstantSeparatorSize && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
{
cairo_translate (pCairoContext,
icon->fHeightFactor * icon->fHeight * (icon->fScale - 1) / 2,
(bDirectionUp ? 1 * icon->fWidthFactor * icon->fWidth * (icon->fScale - 1) : 0));
cairo_scale (pCairoContext,
icon->fHeight / icon->image.iWidth * icon->fHeightFactor/**fRatio * icon->fHeightFactor / (1 + myIconsParam.fAmplitude)*/,
icon->fWidth / icon->image.iHeight * icon->fWidthFactor/**fRatio * icon->fWidthFactor / (1 + myIconsParam.fAmplitude)*/);
}
else
cairo_scale (pCairoContext,
icon->fHeight / icon->image.iWidth * icon->fHeightFactor * icon->fScale/**fRatio * icon->fHeightFactor * icon->fScale / (1 + myIconsParam.fAmplitude)*/ * icon->fGlideScale,
icon->fWidth / icon->image.iHeight * icon->fWidthFactor * icon->fScale/**fRatio * icon->fWidthFactor * icon->fScale / (1 + myIconsParam.fAmplitude)*/ * icon->fGlideScale);
}
}
void cairo_dock_draw_icon_reflect_cairo (Icon *icon, GldiContainer *pContainer, cairo_t *pCairoContext)
{
if (pContainer->bUseReflect && icon->image.pSurface != NULL)
{
cairo_save (pCairoContext);
double fScale = (myIconsParam.bConstantSeparatorSize && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon) ? 1. : icon->fScale);
if (pContainer->bIsHorizontal)
{
cairo_translate (pCairoContext,
0,
(pContainer->bDirectionUp ?
icon->fDeltaYReflection + icon->fHeight * fScale : // go to bottom of icon
-icon->fDeltaYReflection - icon->fHeight * myIconsParam.fReflectHeightRatio)); // go to top of reflect
cairo_rectangle (pCairoContext, 0, 0, icon->fWidth * icon->fScale, icon->fHeight * myIconsParam.fReflectHeightRatio);
if (pContainer->bDirectionUp)
cairo_translate (pCairoContext, 0, icon->fHeight * icon->fHeightFactor * fScale);
else
cairo_translate (pCairoContext, 0, icon->fHeight * icon->fHeightFactor * myIconsParam.fReflectHeightRatio); // go back to top of icon, since we will flip y axis
}
else
{
cairo_translate (pCairoContext,
(pContainer->bDirectionUp ?
icon->fDeltaYReflection + icon->fHeight * fScale : // go to bottom of icon
-icon->fDeltaYReflection - icon->fHeight * myIconsParam.fReflectHeightRatio), // go to top of reflect
0);
cairo_rectangle (pCairoContext, 0, 0, icon->fHeight * myIconsParam.fReflectHeightRatio, icon->fWidth * icon->fScale);
if (pContainer->bDirectionUp)
cairo_translate (pCairoContext, icon->fHeight * icon->fHeightFactor * fScale, 0);
else
cairo_translate (pCairoContext, icon->fHeight * icon->fHeightFactor * myIconsParam.fReflectHeightRatio, 0); // go back to top of icon, since we will flip y axis
}
cairo_clip (pCairoContext);
cairo_dock_set_icon_scale_on_context (pCairoContext, icon, pContainer->bIsHorizontal, 1., pContainer->bDirectionUp);
if (pContainer->bIsHorizontal)
cairo_scale (pCairoContext, 1, -1);
else
cairo_scale (pCairoContext, -1, 1);
cairo_set_source_surface (pCairoContext, icon->image.pSurface, 0.0, 0.0);
if (myBackendsParam.bDynamicReflection) // on applique la surface avec un degrade en transparence, ou avec une transparence simple.
{
cairo_pattern_t *pGradationPattern;
if (pContainer->bIsHorizontal)
{
if (pContainer->bDirectionUp)
pGradationPattern = cairo_pattern_create_linear (
0,
icon->image.iHeight,
0,
icon->image.iHeight * (1 - myIconsParam.fReflectHeightRatio));
else
pGradationPattern = cairo_pattern_create_linear (
0,
0.,
0,
icon->image.iHeight * myIconsParam.fReflectHeightRatio);
g_return_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS);
cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
cairo_pattern_add_color_stop_rgba (pGradationPattern,
0.,
0.,
0.,
0.,
icon->fAlpha * myIconsParam.fAlbedo);
cairo_pattern_add_color_stop_rgba (pGradationPattern,
1.,
0.,
0.,
0.,
0.);
}
else
{
if (pContainer->bDirectionUp)
pGradationPattern = cairo_pattern_create_linear (
icon->image.iWidth,
0.,
icon->image.iWidth * (1-myIconsParam.fReflectHeightRatio),
0);
else
pGradationPattern = cairo_pattern_create_linear (
0,
0.,
icon->image.iWidth * myIconsParam.fReflectHeightRatio,
0);
g_return_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS);
cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE);
cairo_pattern_add_color_stop_rgba (pGradationPattern,
0.,
0.,
0.,
0.,
icon->fAlpha * myIconsParam.fAlbedo);
cairo_pattern_add_color_stop_rgba (pGradationPattern,
1.,
0.,
0.,
0.,
0.);
}
cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
cairo_mask (pCairoContext, pGradationPattern);
cairo_pattern_destroy (pGradationPattern);
}
else
{
cairo_paint_with_alpha (pCairoContext, icon->fAlpha * myIconsParam.fAlbedo);
}
cairo_restore (pCairoContext);
}
}
void cairo_dock_draw_icon_cairo (Icon *icon, CairoDock *pDock, cairo_t *pCairoContext)
{
//\_____________________ On dessine l'icone.
if (icon->image.pSurface != NULL)
{
cairo_save (pCairoContext);
cairo_dock_set_icon_scale_on_context (pCairoContext, icon, pDock->container.bIsHorizontal, 1., pDock->container.bDirectionUp);
cairo_set_source_surface (pCairoContext, icon->image.pSurface, 0.0, 0.0);
if (icon->fAlpha == 1)
cairo_paint (pCairoContext);
else
cairo_paint_with_alpha (pCairoContext, icon->fAlpha);
cairo_restore (pCairoContext);
}
//\_____________________ On dessine son reflet.
cairo_dock_draw_icon_reflect_cairo (icon, CAIRO_CONTAINER (pDock), pCairoContext);
}
gboolean cairo_dock_render_icon_notification (G_GNUC_UNUSED gpointer pUserData, Icon *icon, CairoDock *pDock, gboolean *bHasBeenRendered, cairo_t *pCairoContext)
{
if (*bHasBeenRendered)
return GLDI_NOTIFICATION_LET_PASS;
if (pCairoContext != NULL)
{
if (icon->image.pSurface != NULL)
{
cairo_dock_draw_icon_cairo (icon, pDock, pCairoContext);
}
}
else
{
if (icon->image.iTexture != 0)
{
cairo_dock_draw_icon_opengl (icon, pDock);
}
}
*bHasBeenRendered = TRUE;
return GLDI_NOTIFICATION_LET_PASS;
}
void cairo_dock_render_one_icon (Icon *icon, CairoDock *pDock, cairo_t *pCairoContext, double fDockMagnitude, gboolean bUseText)
{
int iWidth = pDock->container.iWidth;
double fRatio = pDock->container.fRatio;
gboolean bDirectionUp = pDock->container.bDirectionUp;
gboolean bIsHorizontal = pDock->container.bIsHorizontal;
if (CAIRO_DOCK_IS_APPLI (icon) && myTaskbarParam.fVisibleAppliAlpha != 0 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon) && !(myTaskbarParam.iMinimizedWindowRenderType == 1 && icon->pAppli->bIsHidden))
{
double fAlpha = (icon->pAppli->bIsHidden ? MIN (1 - myTaskbarParam.fVisibleAppliAlpha, 1) : MIN (myTaskbarParam.fVisibleAppliAlpha + 1, 1));
if (fAlpha != 1)
icon->fAlpha = fAlpha; // astuce bidon pour pas multiplier 2 fois.
/**if (icon->bIsHidden)
icon->fAlpha *= MIN (1 - myTaskbarParam.fVisibleAppliAlpha, 1);
else
icon->fAlpha *= MIN (myTaskbarParam.fVisibleAppliAlpha + 1, 1);*/
//g_print ("fVisibleAppliAlpha : %.2f & %d => %.2f\n", myTaskbarParam.fVisibleAppliAlpha, icon->bIsHidden, icon->fAlpha);
}
//\_____________________ On se place sur l'icone.
double fGlideScale;
if (icon->fGlideOffset != 0 && (! myIconsParam.bConstantSeparatorSize || ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon)))
{
double fPhase = icon->fPhase + icon->fGlideOffset * icon->fWidth / fRatio / myIconsParam.iSinusoidWidth * G_PI;
if (fPhase < 0)
{
fPhase = 0;
}
else if (fPhase > G_PI)
{
fPhase = G_PI;
}
fGlideScale = (1 + fDockMagnitude * pDock->fMagnitudeMax * myIconsParam.fAmplitude * sin (fPhase)) / icon->fScale; // c'est un peu hacky ... il faudrait passer l'icone precedente en parametre ...
if (bDirectionUp)
{
if (bIsHorizontal)
cairo_translate (pCairoContext, 0., (1-fGlideScale)*icon->fHeight*icon->fScale);
else
cairo_translate (pCairoContext, (1-fGlideScale)*icon->fHeight*icon->fScale, 0.);
}
}
else
fGlideScale = 1;
icon->fGlideScale = fGlideScale;
if (bIsHorizontal)
cairo_translate (pCairoContext, icon->fDrawX + icon->fGlideOffset * icon->fWidth * icon->fScale * (icon->fGlideOffset < 0 ? fGlideScale : 1), icon->fDrawY);
else
cairo_translate (pCairoContext, icon->fDrawY, icon->fDrawX + icon->fGlideOffset * icon->fWidth * icon->fScale * (icon->fGlideOffset < 0 ? fGlideScale : 1));
cairo_save (pCairoContext);
//\_____________________ On positionne l'icone.
if (icon->fOrientation != 0)
cairo_rotate (pCairoContext, icon->fOrientation);
//\_____________________ On dessine l'icone.
gboolean bIconHasBeenDrawn = FALSE;
gldi_object_notify (&myIconObjectMgr, NOTIFICATION_PRE_RENDER_ICON, icon, pDock, pCairoContext);
gldi_object_notify (&myIconObjectMgr, NOTIFICATION_RENDER_ICON, icon, pDock, &bIconHasBeenDrawn, pCairoContext);
cairo_restore (pCairoContext); // retour juste apres la translation (fDrawX, fDrawY).
//\_____________________ On dessine les etiquettes, avec un alpha proportionnel au facteur d'echelle de leur icone.
if (bUseText && icon->label.pSurface != NULL && icon->iHideLabel == 0
&& (icon->bPointed || (icon->fScale > 1.01 && ! myIconsParam.bLabelForPointedIconOnly))) // 1.01 car sin(pi) = 1+epsilon :-/ // && icon->iAnimationState < CAIRO_DOCK_STATE_CLICKED
{
cairo_save (pCairoContext);
double fMagnitude;
if (myIconsParam.bLabelForPointedIconOnly || pDock->fMagnitudeMax == 0. || myIconsParam.fAmplitude == 0.)
{
fMagnitude = fDockMagnitude; // (icon->fScale - 1) / myIconsParam.fAmplitude / sin (icon->fPhase); // sin (phi ) != 0 puisque fScale > 1.
}
else
{
fMagnitude = (icon->fScale - 1) / myIconsParam.fAmplitude; /// il faudrait diviser par pDock->fMagnitudeMax ...
fMagnitude = pow (fMagnitude, myIconsParam.fLabelAlphaThreshold);
///fMagnitude *= (fMagnitude * myIconsParam.fLabelAlphaThreshold + 1) / (myIconsParam.fLabelAlphaThreshold + 1);
}
int iLabelSize = icon->label.iHeight;
///int iLabelSize = myIconsParam.iLabelSize;
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
//g_print ("%d / %d\n", icon->label.iHeight, myIconsParam.iLabelSize),
cairo_identity_matrix (pCairoContext); // on positionne les etiquettes sur un pixels entier, sinon ca floute.
if (bIsHorizontal)
cairo_translate (pCairoContext, floor (icon->fDrawX + icon->fGlideOffset * icon->fWidth * icon->fScale * (icon->fGlideOffset < 0 ? fGlideScale : 1)), floor (icon->fDrawY));
else
cairo_translate (pCairoContext, floor (icon->fDrawY), floor (icon->fDrawX + icon->fGlideOffset * icon->fWidth * icon->fScale * (icon->fGlideOffset < 0 ? fGlideScale : 1)));
double fOffsetX = (icon->fWidth * icon->fScale - icon->label.iWidth) / 2;
if (fOffsetX < - icon->fDrawX) // l'etiquette deborde a gauche.
fOffsetX = - icon->fDrawX;
else if (icon->fDrawX + fOffsetX + icon->label.iWidth > iWidth) // l'etiquette deborde a droite.
fOffsetX = iWidth - icon->label.iWidth - icon->fDrawX;
if (bIsHorizontal)
{
cairo_dock_apply_image_buffer_surface_with_offset (&icon->label, pCairoContext,
floor (fOffsetX), floor (bDirectionUp ? - iLabelSize - gap : icon->fHeight * icon->fScale + gap), fMagnitude);
}
else // horizontal label on a vertical dock -> draw them next to the icon, vertically centered (like the Parabolic view)
{
if (icon->pSubDock && gldi_container_is_visible (CAIRO_CONTAINER (icon->pSubDock))) // in vertical mode
{
fMagnitude /= 3;
}
const int pad = 0;
double fY = icon->fDrawY;
int iMaxWidth = (pDock->container.bDirectionUp ?
fY - gap - pad :
pDock->container.iHeight - (fY + icon->fHeight * icon->fScale + gap + pad));
int iOffsetX = floor (bDirectionUp ?
MAX (- iMaxWidth, - gap - pad - icon->label.iWidth):
icon->fHeight * icon->fScale + gap + pad);
int iOffsetY = floor (icon->fWidth * icon->fScale/2 - icon->label.iHeight/2);
if (icon->label.iWidth < iMaxWidth)
{
cairo_dock_apply_image_buffer_surface_with_offset (&icon->label, pCairoContext,
iOffsetX,
iOffsetY,
fMagnitude);
}
else
{
cairo_dock_apply_image_buffer_surface_with_offset_and_limit (&icon->label, pCairoContext, iOffsetX, iOffsetY, fMagnitude, iMaxWidth);
}
}
cairo_restore (pCairoContext); // retour juste apres la translation (fDrawX, fDrawY).
}
//\_____________________ Draw the overlays on top of that.
cairo_dock_draw_icon_overlays_cairo (icon, fRatio, pCairoContext);
}
void cairo_dock_render_one_icon_in_desklet (Icon *icon, GldiContainer *pContainer, cairo_t *pCairoContext, gboolean bUseText)
{
//\_____________________ On dessine l'icone en fonction de son placement, son angle, et sa transparence.
//g_print ("%s (%.2f;%.2f x %.2f)\n", __func__, icon->fDrawX, icon->fDrawY, icon->fScale);
if (icon->image.pSurface != NULL)
{
cairo_save (pCairoContext);
cairo_translate (pCairoContext, icon->fDrawX, icon->fDrawY);
cairo_scale (pCairoContext, icon->fWidthFactor * icon->fScale, icon->fHeightFactor * icon->fScale);
if (icon->fOrientation != 0)
cairo_rotate (pCairoContext, icon->fOrientation);
cairo_dock_apply_image_buffer_surface_with_offset (&icon->image, pCairoContext, 0, 0, icon->fAlpha);
cairo_restore (pCairoContext); // retour juste apres la translation (fDrawX, fDrawY).
if (pContainer->bUseReflect)
{
cairo_dock_draw_icon_reflect_cairo (icon, pContainer, pCairoContext);
}
}
//\_____________________ On dessine les etiquettes.
if (bUseText && icon->label.pSurface != NULL)
{
cairo_save (pCairoContext);
double fOffsetX = (icon->fWidthFactor * icon->fWidth * icon->fScale - icon->label.iWidth) / 2;
if (fOffsetX < - icon->fDrawX)
fOffsetX = - icon->fDrawX;
else if (icon->fDrawX + fOffsetX + icon->label.iWidth > pContainer->iWidth)
fOffsetX = pContainer->iWidth - icon->label.iWidth - icon->fDrawX;
if (icon->fOrientation != 0)
{
cairo_rotate (pCairoContext, icon->fOrientation);
}
cairo_dock_apply_image_buffer_surface_with_offset (&icon->label, pCairoContext,
fOffsetX, -icon->label.iHeight, 1.);
cairo_restore (pCairoContext); // retour juste apres la translation (fDrawX, fDrawY).
}
//\_____________________ Draw the overlays on top of that.
cairo_dock_draw_icon_overlays_cairo (icon, pContainer->fRatio, pCairoContext);
}
void cairo_dock_draw_string (cairo_t *pCairoContext, CairoDock *pDock, double fStringLineWidth, gboolean bIsLoop, gboolean bForceConstantSeparator)
{
bForceConstantSeparator = bForceConstantSeparator || myIconsParam.bConstantSeparatorSize;
GList *ic, *pFirstDrawnElement = pDock->icons;
if (pFirstDrawnElement == NULL || fStringLineWidth <= 0)
return ;
cairo_save (pCairoContext);
cairo_set_tolerance (pCairoContext, 0.5);
Icon *prev_icon = NULL, *next_icon, *icon;
double x, y, fCurvature = 0.3;
if (bIsLoop)
{
ic = cairo_dock_get_previous_element (pFirstDrawnElement, pDock->icons);
prev_icon = ic->data;
}
ic = pFirstDrawnElement;
icon = ic->data;
GList *next_ic;
double x1, x2, x3;
double y1, y2, y3;
double dx, dy;
x = icon->fDrawX + icon->fWidth * icon->fScale * icon->fWidthFactor / 2;
y = icon->fDrawY + icon->fHeight * icon->fScale / 2 + (bForceConstantSeparator && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon) ? icon->fHeight * (icon->fScale - 1) / 2 : 0);
if (pDock->container.bIsHorizontal)
cairo_move_to (pCairoContext, x, y);
else
cairo_move_to (pCairoContext, y, x);
do
{
if (prev_icon != NULL)
{
x1 = prev_icon->fDrawX + prev_icon->fWidth * prev_icon->fScale * prev_icon->fWidthFactor / 2;
y1 = prev_icon->fDrawY + prev_icon->fHeight * prev_icon->fScale / 2 + (bForceConstantSeparator && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (prev_icon) ? prev_icon->fHeight * (prev_icon->fScale - 1) / 2 : 0);
}
else
{
x1 = x;
y1 = y;
}
prev_icon = icon;
ic = cairo_dock_get_next_element (ic, pDock->icons);
if (ic == pFirstDrawnElement && ! bIsLoop)
break;
icon = ic->data;
x2 = icon->fDrawX + icon->fWidth * icon->fScale * icon->fWidthFactor / 2;
y2 = icon->fDrawY + icon->fHeight * icon->fScale / 2 + (bForceConstantSeparator && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon) ? icon->fHeight * (icon->fScale - 1) / 2 : 0);
dx = x2 - x;
dy = y2 - y;
next_ic = cairo_dock_get_next_element (ic, pDock->icons);
next_icon = (next_ic == pFirstDrawnElement && ! bIsLoop ? NULL : next_ic->data);
if (next_icon != NULL)
{
x3 = next_icon->fDrawX + next_icon->fWidth * next_icon->fScale * next_icon->fWidthFactor / 2;
y3 = next_icon->fDrawY + next_icon->fHeight * next_icon->fScale / 2 + (bForceConstantSeparator && CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (next_icon) ? next_icon->fHeight * (next_icon->fScale - 1) / 2 : 0);
}
else
{
x3 = x2;
y3 = y2;
}
if (pDock->container.bIsHorizontal)
cairo_rel_curve_to (pCairoContext,
(fabs ((x - x1) / (y - y1)) > .35 ? dx * fCurvature : 0),
(fabs ((x - x1) / (y - y1)) > .35 ? dx * fCurvature * (y - y1) / (x - x1) : 0),
(fabs ((x3 - x2) / (y3 - y2)) > .35 ? dx * (1 - fCurvature) : dx),
(fabs ((x3 - x2) / (y3 - y2)) > .35 ? MAX (0, MIN (dy, dy - dx * fCurvature * (y3 - y2) / (x3 - x2))) : dy),
dx,
dy);
else
cairo_rel_curve_to (pCairoContext,
(fabs ((x - x1) / (y - y1)) > .35 ? dx * fCurvature * (y - y1) / (x - x1) : 0),
(fabs ((x - x1) / (y - y1)) > .35 ? dx * fCurvature : 0),
(fabs ((x3 - x2) / (y3 - y2)) > .35 ? MAX (0, MIN (dy, dy - dx * fCurvature * (y3 - y2) / (x3 - x2))) : dy),
(fabs ((x3 - x2) / (y3 - y2)) > .35 ? dx * (1 - fCurvature) : dx),
dy,
dx);
x = x2;
y = y2;
}
while (ic != pFirstDrawnElement);
cairo_set_line_width (pCairoContext, myIconsParam.iStringLineWidth);
cairo_set_source_rgba (pCairoContext, myIconsParam.fStringColor[0], myIconsParam.fStringColor[1], myIconsParam.fStringColor[2], myIconsParam.fStringColor[3]);
cairo_stroke (pCairoContext);
cairo_restore (pCairoContext);
}
void cairo_dock_render_icons_linear (cairo_t *pCairoContext, CairoDock *pDock)
{
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
Icon *icon;
GList *ic = pFirstDrawnElement;
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);
}
void cairo_dock_draw_surface (cairo_t *pCairoContext, cairo_surface_t *pSurface, int iWidth, int iHeight, gboolean bDirectionUp, gboolean bHorizontal, gdouble fAlpha)
{
if (bDirectionUp)
{
if (bHorizontal)
{
cairo_set_source_surface (pCairoContext, pSurface, 0., 0.);
}
else
{
cairo_rotate (pCairoContext, - G_PI/2);
cairo_set_source_surface (pCairoContext, pSurface, - iWidth, 0.);
}
}
else
{
if (bHorizontal)
{
cairo_scale (pCairoContext, 1., -1.);
cairo_set_source_surface (pCairoContext, pSurface, 0., - iHeight);
}
else
{
cairo_rotate (pCairoContext, G_PI/2);
cairo_set_source_surface (pCairoContext, pSurface, 0., - iHeight);
}
}
if (fAlpha == -1)
cairo_fill_preserve (pCairoContext);
else if (fAlpha != 1)
cairo_paint_with_alpha (pCairoContext, fAlpha);
else
cairo_paint (pCairoContext);
}
void cairo_dock_render_hidden_dock (cairo_t *pCairoContext, CairoDock *pDock)
{
//\_____________________ on dessine la zone de rappel.
if (g_pVisibleZoneBuffer.pSurface != NULL)
{
cairo_save (pCairoContext);
int w = MIN (myDocksParam.iZoneWidth, pDock->container.iWidth);
int h = MIN (myDocksParam.iZoneHeight, pDock->container.iHeight);
if (pDock->container.bIsHorizontal)
{
if (pDock->container.bDirectionUp)
cairo_translate (pCairoContext, (pDock->container.iWidth - w)/2, pDock->container.iHeight - h);
else
cairo_translate (pCairoContext, (pDock->container.iWidth - w)/2, 0.);
}
else
{
if (pDock->container.bDirectionUp)
cairo_translate (pCairoContext, pDock->container.iHeight - h, (pDock->container.iWidth - w)/2);
else
cairo_translate (pCairoContext, 0., (pDock->container.iWidth - w)/2);
}
cairo_dock_draw_surface (pCairoContext, g_pVisibleZoneBuffer.pSurface,
w,
h,
pDock->container.bDirectionUp, // reverse image with dock.
pDock->container.bIsHorizontal,
1.);
cairo_restore (pCairoContext);
}
//\_____________________ on dessine les icones demandant l'attention.
GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDock->icons);
if (pFirstDrawnElement == NULL)
return;
double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
double y;
Icon *icon;
GList *ic = pFirstDrawnElement;
GldiColor *pHiddenBgColor;
const double r = (myDocksParam.bUseDefaultColors ? myStyleParam.iCornerRadius/2 : 4); // corner radius of the background
const double gap = 2; // gap to the screen
double alpha;
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).
double w, h;
do
{
icon = ic->data;
if (icon->bIsDemandingAttention || icon->bAlwaysVisible)
{
y = icon->fDrawY;
icon->fDrawY = (pDock->container.bDirectionUp ? pDock->container.iHeight - icon->fHeight * icon->fScale - gap: gap);
if (icon->bHasHiddenBg)
{
pHiddenBgColor = NULL;
if (icon->pHiddenBgColor) // custom bg color
pHiddenBgColor = icon->pHiddenBgColor;
else if (! myDocksParam.bUseDefaultColors) // default bg color
pHiddenBgColor = &myDocksParam.fHiddenBg;
//if (pHiddenBgColor && pHiddenBgColor[3] != 0)
{
cairo_save (pCairoContext);
if (pHiddenBgColor)
{
gldi_color_set_cairo (pCairoContext, pHiddenBgColor);
alpha = pHiddenBgColor->rgba.alpha;
}
else
{
gldi_style_colors_set_bg_color (pCairoContext);
alpha = .7;
}
w = icon->fWidth * icon->fScale;
h = icon->fHeight * icon->fScale;
if (pDock->container.bIsHorizontal)
{
cairo_translate (pCairoContext, icon->fDrawX - dw / 2, icon->fDrawY);
cairo_dock_draw_rounded_rectangle (pCairoContext, r, 0, w - 2*r + dw, h);
}
else
{
cairo_translate (pCairoContext, icon->fDrawY - dw / 2, icon->fDrawX);
cairo_dock_draw_rounded_rectangle (pCairoContext, r, 0, h - 2*r + dw, w);
}
///cairo_fill (pCairoContext);
cairo_clip (pCairoContext);
cairo_paint_with_alpha (pCairoContext, alpha * pDock->fPostHideOffset);
cairo_restore (pCairoContext);
}
}
cairo_save (pCairoContext);
icon->fAlpha = pDock->fPostHideOffset;
cairo_dock_render_one_icon (icon, pDock, pCairoContext, fDockMagnitude, TRUE);
cairo_restore (pCairoContext);
icon->fDrawY = y;
}
ic = cairo_dock_get_next_element (ic, pDock->icons);
} while (ic != pFirstDrawnElement);
}