/* Excelsior Engine
 * Copyright (C) 2006 Richard Stellingwerff
 * Copyright (C) 2006 Daniel Borgman
 * Copyright (C) 2007 Benjamin Berg
 * Copyright (C) 2007 Andrea Cimitan
 * Copyright (C) 2008 Christopher Bratusek
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 */

#include "excelsior_draw.h"
#include "excelsior_style.h"
#include "excelsior_types.h"

#include "support.h"
#include "ge-support.h"
#include <math.h>

#include <cairo.h>

#define EXCELSIOR_RAND_MAX 32767

enum {LEFT, RIGHT};

static unsigned long next = 1;

typedef void (*menubar_draw_proto) (cairo_t *cr,
                                    const excelsiorColors *colors,
                                    const WidgetParameters *params,
                                    const MenuBarParameters *menubar,
                                    int x, int y, int width, int height);

void
excelsior_srand (unsigned seed) {
    next = seed;
}

int
excelsior_rand (void) {
    next = next * 1103515245 + 12345;
    return ((unsigned) (next/65536) % 32768);
}

int
excelsior_rand_within (int low, int high)
{
    return low + excelsior_rand () / (EXCELSIOR_RAND_MAX / (high - low));
}

static void
draw_swoosh (cairo_t *cr, int side, int x, int y, int width, int height,
	     int top_x, int top_y, int left_x, int left_y,
	     int right_x, int right_y, int bottom_x, int bottom_y, int STRENGTH)
{
    cairo_pattern_t *pattern;

    cairo_save (cr);

    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
    if (side == LEFT) {
	cairo_new_path (cr);
	cairo_move_to (cr, top_x, y);
	cairo_line_to (cr, right_x + 1, y);
	cairo_line_to (cr, right_x + 1, top_y - 1);
	cairo_line_to (cr, left_x - 1, top_y - 1);
	cairo_line_to (cr, left_x - 1, bottom_y + 1);
	cairo_line_to (cr, x, bottom_y + 1);
	cairo_line_to (cr, x, left_y);
	cairo_close_path (cr);
	cairo_clip (cr);
    }
    else {
	cairo_new_path (cr);
	cairo_move_to (cr, bottom_x, y + height);
	cairo_line_to (cr, x + width, right_y);
	cairo_line_to (cr, x + width, top_y - 1);
	cairo_line_to (cr, right_x + 1, top_y - 1);
	cairo_line_to (cr, right_x + 1, bottom_y + 1);
	cairo_line_to (cr, left_x - 1, bottom_y + 1);
	cairo_line_to (cr, left_x - 1, y + height);
	cairo_close_path (cr);
	cairo_clip (cr);
    }

    cairo_new_path (cr);
    cairo_move_to (cr, top_x, top_y);
    cairo_curve_to (cr,
		    top_x + STRENGTH, top_y,
		    right_x, right_y - STRENGTH,
		    right_x, right_y);

    cairo_curve_to (cr,
		    right_x, right_y + STRENGTH,
		    bottom_x + STRENGTH, bottom_y,
		    bottom_x, bottom_y);

    cairo_curve_to (cr,
		    bottom_x - STRENGTH, bottom_y,
		    left_x, left_y + STRENGTH,
		    left_x, left_y);

    cairo_curve_to (cr,
		    left_x, left_y - STRENGTH,
		    top_x - STRENGTH, top_y,
		    top_x, top_y);
    cairo_close_path (cr);

    top_y += 1;
    left_x += 3;
    right_x -= 3;
    bottom_y -= 1;

    cairo_move_to (cr, top_x, top_y);
    cairo_curve_to (cr,
		    top_x + STRENGTH, top_y,
		    right_x, right_y - STRENGTH,
		    right_x, right_y);

    cairo_curve_to (cr,
		    right_x, right_y + STRENGTH,
		    bottom_x + STRENGTH, bottom_y,
		    bottom_x, bottom_y);

    cairo_curve_to (cr,
		    bottom_x - STRENGTH, bottom_y,
		    left_x, left_y + STRENGTH,
		    left_x, left_y);

    cairo_curve_to (cr,
		    left_x, left_y - STRENGTH,
		    top_x - STRENGTH, top_y,
		    top_x, top_y);

    if (side == LEFT)
	pattern = cairo_pattern_create_linear (left_x, bottom_y, top_x, top_y);
    else
	pattern = cairo_pattern_create_linear (right_x, top_y,
					       bottom_x, bottom_y);

    cairo_pattern_add_color_stop_rgba (pattern, 0, 0, 0, 0.75, 0.5);
    cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 0.29, 1);
    cairo_set_source (cr, pattern);
    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
    cairo_fill (cr);
    cairo_pattern_destroy (pattern);

    cairo_restore (cr);
}

static void
swoosh (cairo_t *cr, int x, int y, int width, int height, int STRENGTH)
{
    int top_x, top_y, left_x, left_y, right_x, right_y, bottom_x, bottom_y;

    top_x = x + excelsior_rand_within (15, 40);
    top_y = y - 2;
    left_x = x - 4;
    left_y = excelsior_rand_within (y + height / 2 - 5, y + height / 2 + 5);
    right_x = left_x + excelsior_rand_within (50, 60);
    right_y = excelsior_rand_within (y + height / 2 - 5, y + height / 2 + 5);
    bottom_x = x + excelsior_rand_within (10, 20);
    bottom_y = y + height - excelsior_rand_within (0, 4);

    draw_swoosh (cr, LEFT, x, y, width, height,
		 top_x, top_y, left_x, left_y,
		 right_x, right_y, bottom_x, bottom_y, STRENGTH);

    top_x = x + width - excelsior_rand_within (10, 20);
    top_y = y + excelsior_rand_within (0, 4);
    right_x = x + width + 4;
    right_y = y + excelsior_rand_within (height / 2 - 5, height / 2 + 5);
    left_x = right_x - excelsior_rand_within (50, 60);
    left_y = y + excelsior_rand_within (height / 2 - 5, height / 2 + 5);
    bottom_x = x + width - excelsior_rand_within (15, 40);
    bottom_y = y + height + 2;

    draw_swoosh (cr, RIGHT, x, y, width, height,
		 top_x, top_y, left_x, left_y,
		 right_x, right_y, bottom_x, bottom_y, STRENGTH);
}

void drawstripes(cairo_t *cr, int x1, int y1, int x2, int y2)
{
	int d=(x1-x2)/2;
	cairo_move_to(cr, x1+1,y1-1);
	cairo_curve_to(cr,x1+d,y1,x2,y2,x2,y2);
	cairo_curve_to(cr,x2,y2,x1+d+d/2,y1,x1+d,y1);
	cairo_line_to(cr,x1,y1);
	cairo_close_path (cr);
	cairo_fill(cr);
}

void drawcircles(cairo_t *cr, int x1, int y1, int x2, int y2, int circle_spacing, int circle_radius)
{
	cairo_move_to (cr, x1+1, y1-1);
	cairo_arc (cr, x1, y1, circle_radius, 0, G_PI*2);
	x1 += 2*circle_radius*circle_spacing;
	y1 += 2*circle_radius*circle_spacing;
	cairo_close_path (cr);
	cairo_fill (cr);
}

void
excelsior_draw_random_stripes(cairo_t *cr, int xoffset, int yoffset,
			int x, int y, int width, int height, int count)
{

	int i;

	for (i=0;i<count;i++){
		int x1,x2;
		static GHashTable *ght=NULL;
		if (ght==NULL) ght=g_hash_table_new_full(g_str_hash,g_str_equal,NULL,NULL);

		gchar key[4]={(char)x,(char)y,(char)i,0};
		gchar *obj=g_hash_table_lookup(ght,key);
		if (obj==NULL){
			x1=rand()%width;
			x2=rand()%(width/5)-width/10;
			gchar obj[]={x1,x2,0};
			g_hash_table_insert(ght,g_strdup(key),g_strdup(obj));
		}
		else
		{
			x1=obj[0];
			x2=obj[1];
		}
		int d=x2*2;
		drawstripes(cr,x1+xoffset,yoffset,x1+d+xoffset,height/1.75+yoffset);
	}
}

void
excelsior_draw_random_circles(cairo_t *cr, int xoffset, int yoffset,
			int x, int y, int width, int height, int count, int circle_spacing, int circle_radius)
{

	int i;

	for (i=0;i<count;i++){
		int x1,x2;
		static GHashTable *ght=NULL;
		if (ght==NULL) ght=g_hash_table_new_full(g_str_hash,g_str_equal,NULL,NULL);

		gchar key[4]={(char)x,(char)y,(char)i,0};
		gchar *obj=g_hash_table_lookup(ght,key);
		if (obj==NULL){
			x1=rand()%width;
			x2=rand()%(width/5)-width/10;
			gchar obj[]={x1,x2,0};
			g_hash_table_insert(ght,g_strdup(key),g_strdup(obj));
		}
		else
		{
			x1=obj[0];
			x2=obj[1];
		}
		int d=x2*2;
		drawcircles(cr,x1/xoffset,x2/yoffset,x1+d-xoffset,height*0.80-yoffset, circle_spacing, circle_radius);
	}
}

static void
excelsior_draw_inset (cairo_t          *cr,
                       const CairoColor *bg_color,
                       double x, double y, double w, double h,
                       double radius, uint8 corners)
{
	CairoColor shadow;
	CairoColor highlight;

	ge_shade_color (bg_color, 0.94, &shadow);
	ge_shade_color (bg_color, 1.06, &highlight);

	cairo_move_to (cr, x + w + (radius * -0.2928932188), y - (radius * -0.2928932188));

	if (corners & CR_CORNER_TOPRIGHT)
		cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.75, G_PI * 2);
	else
		cairo_line_to (cr, x + w, y);

	if (corners & CR_CORNER_BOTTOMRIGHT)
		cairo_arc (cr, x + w - radius, y + h - radius, radius, 0, G_PI * 0.5);
	else
		cairo_line_to (cr, x + w, y + h);

	if (corners & CR_CORNER_BOTTOMLEFT)
		cairo_arc (cr, x + radius, y + h - radius, radius, G_PI * 0.5, G_PI * 0.75);
	else
		cairo_line_to (cr, x, y + h);

	ge_cairo_set_color (cr, &highlight);
	cairo_stroke (cr);

	/* shadow */
	cairo_move_to (cr, x + (radius * 0.2928932188), y + h + (radius * -0.2928932188));

	if (corners & CR_CORNER_BOTTOMLEFT)
		cairo_arc (cr, x + radius, y + h - radius, radius, G_PI * 0.75, G_PI);
	else
		cairo_line_to (cr, x, y + h);

	if (corners & CR_CORNER_TOPLEFT)
		cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
	else
		cairo_line_to (cr, x, y);

	if (corners & CR_CORNER_TOPRIGHT)
	    cairo_arc (cr, x + w - radius, y + radius, radius, G_PI * 1.5, G_PI * 1.75);
	else
		cairo_line_to (cr, x + w, y);

	ge_cairo_set_color (cr, &shadow);
	cairo_stroke (cr);
}

static void
rotate_mirror_translate (cairo_t *cr, double radius, double x, double y,
                         boolean mirror_horizontally, boolean mirror_vertically)
{
	cairo_matrix_t matrix_rotate;
	cairo_matrix_t matrix_mirror;
	cairo_matrix_t matrix_result;

	double r_cos = cos(radius);
	double r_sin = sin(radius);

	cairo_matrix_init (&matrix_rotate, r_cos,
	                                   r_sin,
	                                   r_sin,
	                                   r_cos,
	                                   x, y);

	cairo_matrix_init (&matrix_mirror, mirror_horizontally ? -1 : 1,
	                                   0,
	                                   0,
	                                   mirror_vertically ? -1 : 1,
								  0, 0);

	cairo_matrix_multiply (&matrix_result, &matrix_mirror, &matrix_rotate);

	cairo_set_matrix (cr, &matrix_result);
}

static void
excelsior_draw_shadow (cairo_t *cr, const excelsiorColors *colors, gfloat radius, int width, int height)
{
	CairoColor shadow;
	ge_shade_color (&colors->shade[5], 0.85, &shadow);

	cairo_set_line_width (cr, 1.0);

	cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1);

	cairo_move_to (cr, width, radius);
	ge_cairo_rounded_corner (cr, width, height, radius, CR_CORNER_BOTTOMRIGHT);
	cairo_line_to (cr, radius, height);

	cairo_stroke (cr);
}

static void
excelsior_draw_top_left_highlight (cairo_t *cr, const CairoColor *color,
                                    const WidgetParameters *params,
                                    int width, int height, gdouble radius)
{
	CairoColor hilight;

	double light_top = params->ythickness-1,
	       light_bottom = height - params->ythickness - 1,
	       light_left = params->xthickness-1,
	       light_right = width - params->xthickness - 1;

	ge_shade_color (color, 1.3, &hilight);
	cairo_move_to         (cr, light_left, light_bottom - (int)radius/2);

	ge_cairo_rounded_corner (cr, light_left, light_top, radius, params->corners & CR_CORNER_TOPLEFT);

	cairo_line_to         (cr, light_right - (int)radius/2, light_top);
	cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5);
	cairo_stroke          (cr);
}

static void
excelsior_draw_highlight_and_shade (cairo_t *cr, const excelsiorColors *colors,
                                     const ShadowParameters *params,
                                     int width, int height, gdouble radius)
{
	CairoColor hilight;
	CairoColor shadow;
	uint8 corners = params->corners;
	double x = 1.0;
	double y = 1.0;

	ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 1.15, &hilight);
	ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 0.90, &shadow);

	width  -= 3;
	height -= 3;

	cairo_save (cr);

	/* Top/Left highlight */
	if (corners & CR_CORNER_BOTTOMLEFT)
		cairo_move_to (cr, x, y+height-radius);
	else
		cairo_move_to (cr, x, y+height);

	ge_cairo_rounded_corner (cr, x, y, radius, corners & CR_CORNER_TOPLEFT);

	if (corners & CR_CORNER_TOPRIGHT)
		cairo_line_to (cr, x+width-radius, y);
	else
		cairo_line_to (cr, x+width, y);

	if (params->shadow & XCL_SHADOW_OUT)
		ge_cairo_set_color (cr, &hilight);
	else
		ge_cairo_set_color (cr, &shadow);

	cairo_stroke (cr);

	/* Bottom/Right highlight -- this includes the corners */
	cairo_move_to (cr, x+width-radius, y); /* topright and by radius to the left */
	ge_cairo_rounded_corner (cr, x+width, y, radius, corners & CR_CORNER_TOPRIGHT);
	ge_cairo_rounded_corner (cr, x+width, y+height, radius, corners & CR_CORNER_BOTTOMRIGHT);
	ge_cairo_rounded_corner (cr, x, y+height, radius, corners & CR_CORNER_BOTTOMLEFT);

	if (params->shadow & XCL_SHADOW_OUT)
		ge_cairo_set_color (cr, &shadow);
	else
		ge_cairo_set_color (cr, &hilight);

	cairo_stroke (cr);

	cairo_restore (cr);
}

static void
excelsior_set_border_gradient (cairo_t *cr, const CairoColor *color, double hilight, int width, int height)
{
	cairo_pattern_t *pattern;


	pattern	= cairo_pattern_create_linear (0, 0, width, height);
	cairo_pattern_add_color_stop_rgba (pattern, 0.0, color->r, color->g, color->b, 1.0);
	cairo_pattern_add_color_stop_rgba (pattern, 1.0, color->r, color->g, color->b, 0.5);

	cairo_set_source (cr, pattern);
	cairo_pattern_destroy (pattern);
}

static void
excelsior_draw_gripdots (cairo_t *cr, const excelsiorColors *colors, int x, int y,
                          int width, int height, int xr, int yr,
                          float contrast)
{
	const CairoColor *dark = &colors->shade[4];
	CairoColor hilight;
	int i, j;
	int xoff, yoff;

	ge_shade_color (dark, 0.85, &hilight);

	for ( i = 0; i < xr; i++ )
	{
		for ( j = 0; j < yr; j++ )
		{
			xoff = x -(xr * 3 / 2) + 3 * i;
			yoff = y -(yr * 3 / 2) + 3 * j;

			cairo_rectangle (cr, width/2+0.75+xoff, height/2+0.75+yoff, 2, 2);
			cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.8+contrast);
			cairo_fill (cr);
			cairo_rectangle (cr, width/2+0.75+xoff, height/2+0.75+yoff, 2, 2);
			cairo_set_source_rgba (cr, dark->r, dark->g, dark->b, 0.8+contrast);
			cairo_fill (cr);
		}
	}
}

static void
excelsior_draw_button (cairo_t *cr,
                        const excelsiorColors *colors,
                        const WidgetParameters *params,
                        int x, int y, int width, int height, double grip_opacity)
{
	double xoffset = 0, yoffset = 0;
	double radius = params->radius;
	const CairoColor *fill = &colors->bg[params->state_type];
	const CairoColor *stripe = &colors->bg[GTK_STATE_SELECTED];
	const CairoColor *border_disabled = &colors->shade[4];
	const CairoColor *random_color = &colors->text[GTK_STATE_NORMAL];
	CairoColor border_normal;
	CairoColor shadow;

	ge_shade_color(&colors->shade[6], 0.95, &border_normal);
	ge_shade_color (&border_normal, 0.88, &shadow);

	cairo_save (cr);

	cairo_translate (cr, x, y);
	cairo_set_line_width (cr, 0.75);

	if (params->xthickness == 3 || params->ythickness == 3)
	{
		if (params->xthickness == 3)
			xoffset = 1;
		if (params->ythickness == 3)
			yoffset = 1;
	}

	radius = MIN (radius, MIN ((width - 2.0 - xoffset * 2.0) / 2.0, (height - 2.0 - yoffset * 2) / 2.0));

	ge_cairo_rounded_rectangle (cr, xoffset+2, yoffset+2,
						width-(xoffset*2)-2,
						height-(yoffset*2)-2,
						radius, params->corners);

	if (params->button_style == 0)
	{

	if (params->disabled)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.94, &shade1);
		ge_shade_color (fill, 1.00, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->active && !params->is_default)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.96, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);

		ge_cairo_set_color(cr, &colors->bg[GTK_STATE_SELECTED]);
		ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, params->corners);
		cairo_stroke (cr);
	}
	else
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.97, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	}
	else if (params->button_style == 1)
	{
	if (params->disabled)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.00, &shade1);
		ge_shade_color (fill, 1.10, &shade2);
		ge_shade_color (fill, 0.95, &shade3);
		ge_shade_color (fill, 0.85, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->active)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.15, &shade1);
		ge_shade_color (fill, 1.25, &shade2);
		ge_shade_color (fill, 1.10, &shade3);
		ge_shade_color (fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);

		ge_cairo_set_color(cr, &colors->bg[GTK_STATE_SELECTED]);
		ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, params->corners);
		cairo_stroke (cr);
	}
	else
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.15, &shade1);
		ge_shade_color (fill, 1.25, &shade2);
		ge_shade_color (fill, 1.10, &shade3);
		ge_shade_color (fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	}
	else if (params->button_style == 2)
	{
	if (params->disabled)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 0.98, &shadow);
		ge_shade_color (fill, 0.98, &hilight);
		ge_shade_color (fill, 0.93, &f1);
		ge_shade_color (fill, 0.88, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->active)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);

		ge_cairo_set_color(cr, &colors->bg[GTK_STATE_SELECTED]);
		ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, params->corners);
		cairo_stroke (cr);
	}
	else
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	}

	if (params->disabled)
		ge_cairo_set_color (cr, border_disabled);
	else
		excelsior_set_border_gradient (cr, &border_normal, 1.15, 0, height);


	ge_cairo_rounded_rectangle (cr, xoffset + 0.75, yoffset + 0.75,
					width-(xoffset*2)-1, height-(yoffset*2)-1,
					radius, params->corners);
	cairo_stroke (cr);

	cairo_translate (cr, 0.75, 0.75);

	cairo_move_to (cr, width-params->xthickness, params->ythickness - 1);
	cairo_line_to (cr, width-params->xthickness, height - params->ythickness - 1);
	cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1);
	cairo_stroke (cr);

	excelsior_draw_top_left_highlight (cr, fill, params, width, height, radius);

	if (params->random_effect == 1)
	{
		cairo_set_source_rgba(cr, random_color->r, random_color->g, random_color->b, params->random_opacity);
		excelsior_draw_random_stripes(cr,1,1,x,y,width-4,height-4,(width*2.75)/100);
	}
	else if (params->random_effect == 2)
	{
		cairo_set_source_rgba(cr, random_color->r, random_color->g, random_color->b, params->random_opacity);

		excelsior_draw_random_circles(cr,1,1,x*1.5,y/1.5,width-4,height-4,(width*2)/150, 6, 4);
		excelsior_draw_random_circles(cr,1,1,x*2,y*2,width-4,height-4,(width*2)/2250, 4, 2);
		excelsior_draw_random_circles(cr,1,1,x/1.5,y*1.5,width-4,height-4,(width*2)/225, 8, 6);
	}
	if (params->swoosh_effect == 1)
	{
		swoosh(cr,1,1,width,height,params->swoosh_strength);
	}

	if (params->active)
	{
		const CairoColor *grip_color = &colors->bg[GTK_STATE_SELECTED];
		cairo_set_source_rgba(cr, grip_color->r, grip_color->g, grip_color->b, grip_opacity*2);
	}
	else
	{
		const CairoColor *grip_color = &colors->text[GTK_STATE_NORMAL];
		cairo_set_source_rgba(cr, grip_color->r, grip_color->g, grip_color->b, grip_opacity);
	}

	cairo_move_to (cr, width-6, height-6);
	cairo_line_to (cr, width-12, height-6);
	cairo_line_to (cr, width-6, height-12);
	cairo_close_path (cr);
	cairo_fill(cr);

	cairo_restore (cr);
}

static void

excelsior_draw_mw_gradient (cairo_t *cr,
                       const excelsiorColors *colors,
                       const WidgetParameters *params,
                       int x, int y, int width, int height)
{
	cairo_pattern_t *pattern;

	const CairoColor *fill = &colors->bg[params->state_type];
	double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0));

	CairoColor highlight, low, lower;
	ge_shade_color (fill, 1.20, &highlight);
	ge_shade_color (fill, 1.15, &low);
	ge_shade_color (fill, 0.88, &lower);

	if (params->mw_gradient == 1)
	{
		pattern = cairo_pattern_create_linear (0, 0, 0, height);

		cairo_pattern_add_color_stop_rgb (pattern, 0.00, highlight.r, highlight.g, highlight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45, low.r, low.g, low.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.55, low.r, low.g, low.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.74, lower.r, lower.g, lower.b);
		cairo_set_source (cr, pattern);
	}
	else if (params->mw_gradient == 2)
	{
		pattern = cairo_pattern_create_linear (0, 0, width/1.75, height);

		cairo_pattern_add_color_stop_rgb (pattern, 0.00, highlight.r, highlight.g, highlight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45, low.r, low.g, low.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.55, low.r, low.g, low.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.77, lower.r, lower.g, lower.b);
		cairo_set_source (cr, pattern);
	}
	else if (params->mw_gradient == 3)
	{
		double           tile_pos = 0;
		double           stroke_width;
		int			x_step;
		stroke_width = height/1.25;

		x_step = (((float)stroke_width/10));

		while (tile_pos <= width+x_step)
		{
		cairo_move_to (cr, stroke_width/2-x_step, 0);
		cairo_line_to (cr, stroke_width-x_step,   0);
		cairo_line_to (cr, stroke_width/2-x_step, height);
		cairo_line_to (cr, -x_step, height);

		cairo_translate (cr, stroke_width, 0);
		tile_pos += stroke_width;
		}
	}
	else if (params->mw_gradient == 4)
	{
		double           tile_pos = 0;
		double           stroke_width;
		double           arrow_width;
		int			x_step;
		stroke_width = height/1.25;
		arrow_width = stroke_width/2;

		x_step = (((float)stroke_width/10));

		while (tile_pos <= width+x_step)
		{
		cairo_move_to (cr, stroke_width/2-x_step, 0);
		cairo_line_to (cr, stroke_width-x_step, height/2);
		cairo_line_to (cr, stroke_width/2-x_step, height);
		cairo_line_to (cr, stroke_width/2-x_step-arrow_width, height);
		cairo_line_to (cr, stroke_width-x_step-arrow_width, height/2);
		cairo_line_to (cr, stroke_width/2-x_step-arrow_width, 0);

		cairo_translate (cr, stroke_width, 0);
		tile_pos += stroke_width;
		}
	}

	ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
	cairo_fill (cr);

}

static void
excelsior_draw_entry (cairo_t *cr,
                       const excelsiorColors *colors,
                       const WidgetParameters *params,
                       int x, int y, int width, int height)
{
	CairoColor border = colors->shade[params->disabled ? 4 : 6];
	const CairoColor *fill = &colors->bg[params->state_type];
	double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0));

	if (params->focus)
		border = colors->spot[2];

	cairo_translate (cr, x+0.5, y+0.5);
	cairo_set_line_width (cr, 0.75);

	cairo_pattern_t *pattern;

	if (params->button_style == 0)
	{
		if (params->disabled)
		{
		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.94, &shade1);
		ge_shade_color (fill, 1.00, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
		}
		else
		{
		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.95, &shade1);
		ge_shade_color (fill, 1.20, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
		}
	}
	else if (params->button_style == 1)
	{
		if (params->disabled)
		{
		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.00, &shade1);
		ge_shade_color (fill, 1.10, &shade2);
		ge_shade_color (fill, 0.95, &shade3);
		ge_shade_color (fill, 0.85, &shade4);

		pattern = cairo_pattern_create_linear (0, -2, 0, height-2);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
		}
		else
		{
		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.15, &shade1);
		ge_shade_color (fill, 1.25, &shade2);
		ge_shade_color (fill, 1.10, &shade3);
		ge_shade_color (fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, -2, 0, height-2);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
		}
	}
	else if (params->button_style == 2)
	{
		if (params->disabled)
		{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 0.98, &shadow);
		ge_shade_color (fill, 0.98, &hilight);
		ge_shade_color (fill, 0.93, &f1);
		ge_shade_color (fill, 0.88, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
		}
		else
		{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
		}
	}

	cairo_fill(cr);

	/* Draw the inner shadow */
	if (params->entry_ib_ever == 1)
	{
		ge_cairo_set_color (cr, &colors->spot[0]);
		ge_cairo_stroke_rectangle (cr, 2, 2, width-5, height-5);
	}
	else if (params->entry_ib_ever == 0)
	{
		if (params->focus)
		{
			ge_cairo_set_color (cr, &colors->spot[0]);
			ge_cairo_stroke_rectangle (cr, 2, 2, width-5, height-5);
		}
	}

	if (params->enable_shadow)
	{
		ge_cairo_rounded_rectangle (cr, 1, 1, width-3, height-3, radius, params->corners);
		excelsior_set_border_gradient (cr, &border, 1.32, 0, height);
		cairo_stroke (cr);
	}
	else
	{
		cairo_set_source_rgba (cr, border.r, border.g, border.b, 0.00);
		cairo_stroke (cr);
	}
}

static void
excelsior_draw_spinbutton (cairo_t *cr,
                            const excelsiorColors *colors,
                            const WidgetParameters *params,
                            int x, int y, int width, int height)
{
	const CairoColor *border = &colors->shade[!params->disabled ? 5 : 3];
	CairoColor hilight;

	params->style_functions->draw_button (cr, colors, params, x, y, width, height, 0.0);

	ge_shade_color (border, 1.25, &hilight);

	cairo_translate (cr, x, y);
}

static void
excelsior_draw_spinbutton_down (cairo_t *cr,
                                 const excelsiorColors *colors,
                                 const WidgetParameters *params,
                                 int x, int y, int width, int height)
{
	cairo_pattern_t *pattern;
	double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0));
	CairoColor shadow;
	ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 0.8, &shadow);

	cairo_translate (cr, x+1, y+1);

	ge_cairo_rounded_rectangle (cr, 1, 1, width-4, height-4, radius, params->corners);

	ge_cairo_set_color (cr, &colors->bg[params->state_type]);

	cairo_fill_preserve (cr);

	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.0, shadow.r, shadow.g, shadow.b);
	cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0);

	cairo_set_source (cr, pattern);
	cairo_fill (cr);

	cairo_pattern_destroy (pattern);
}

static void
excelsior_scale_draw_gradient (cairo_t *cr,
                                const CairoColor *c1,
                                const CairoColor *c2,
                                const CairoColor *c3,
                                const CairoColor *c4,
                                int x, int y, int width, int height,
                                boolean horizontal)
{
	cairo_pattern_t *pattern;

	pattern = cairo_pattern_create_linear (0, 0, horizontal ? 0 :  width, horizontal ? height : 0);
	cairo_pattern_add_color_stop_rgb (pattern, 0.00, c1->r, c1->g, c1->b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.50, c2->r, c2->g, c2->b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.50, c2->r, c2->g, c2->b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.75, c3->r, c3->g, c3->b);

	cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1);
	cairo_set_source (cr, pattern);
	cairo_fill (cr);
	cairo_pattern_destroy (pattern);

	ge_cairo_set_color (cr, c4);
	ge_cairo_stroke_rectangle (cr, x, y, width, height);
}

static void
excelsior_draw_scale_trough (cairo_t *cr,
                              const excelsiorColors *colors,
                              const WidgetParameters *params,
                              const SliderParameters *slider,
                              int x, int y, int width, int height)
{
	int     trough_width, trough_height;
	double  translate_x, translate_y;

	if (slider->horizontal)
	{
		trough_width  = width;
		trough_height = params->scale_trough_size-2;

		translate_x   = x + 0.5;
		translate_y   = y + 0.5 + (height/2) - (params->scale_trough_size/2);
	}
	else
	{
		trough_width  = params->scale_trough_size-2;
		trough_height = height;

		translate_x   = x + 0.5 + (width/2) - (params->scale_trough_size/2);
		translate_y   = y + 0.5;
	}

	cairo_set_line_width (cr, 1.0);
	cairo_translate (cr, translate_x, translate_y);

	if (!slider->fill_level)
		params->style_functions->draw_inset (cr, &params->parentbg, 0, 0, trough_width+2, trough_height+2, 0, 0);

	if (slider->horizontal)
		cairo_translate (cr, 0, 1);
	else
		cairo_translate (cr, 1, 0);

	if (!slider->lower && ! slider->fill_level)
		excelsior_scale_draw_gradient (cr, &colors->shade[2], /* top */
		                                    &colors->shade[1], /* middle */
		                                    &colors->shade[0], /* bottom */
		                                    &colors->shade[6], /* border */
		                                    0, 0, trough_width, trough_height,
		                                    slider->horizontal);
	else
		excelsior_scale_draw_gradient (cr, &colors->spot[1], /* top    */
		                                    &colors->spot[0], /* middle */
		                                    &colors->spot[1], /* bottom */
		                                    &colors->shade[6], /* border */
		                                    0, 0, trough_width, trough_height,
		                                    slider->horizontal);
}

static void
excelsior_draw_slider (cairo_t *cr,
                        const excelsiorColors *colors,
                        const WidgetParameters *params,
                        int x, int y, int width, int height)
{
	const CairoColor *border = &colors->shade[params->disabled ? 4 : 6];
	const CairoColor *fill   = &colors->bg[params->state_type];
	double radius = MIN (params->radius, MIN ((width - 1.0) / 2.0, (height - 1.0) / 2.0));

	cairo_pattern_t *pattern;

	cairo_set_line_width (cr, 1.0);
	cairo_translate      (cr, x, y);

	if (params->prelight)
		border = &colors->spot[2];

	/* fill the widget */
	cairo_rectangle (cr, 0.5, 0.5, width-2, height-2);

	if (params->old_scales == 1)
	{
		const CairoColor *top = &colors->shade[0];
		const CairoColor *bot = &colors->shade[2];

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.0,  top->r, top->g, top->b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.5,  top->r, top->g, top->b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.5,  bot->r, bot->g, bot->b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.0,  bot->r, bot->g, bot->b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->pellucid_scales == 1)
	{
	}
	if (params->button_style == 0)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.97, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 1)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.15, &shade1);
		ge_shade_color (fill, 1.25, &shade2);
		ge_shade_color (fill, 1.10, &shade3);
		ge_shade_color (fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 2)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else
	{
		ge_cairo_set_color (cr, fill);
		cairo_rectangle    (cr, 0.5, 0.5, width-2, height-2);
		cairo_fill         (cr);
	}

	/* Set the clip */
	cairo_save (cr);
	cairo_rectangle (cr, 0.5, 0.5, 6, height-2);
	cairo_rectangle (cr, width-7.5, 0.5, 6 , height-2);
	cairo_clip_preserve (cr);

	cairo_new_path (cr);

	/* Draw the handles */
	ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, params->corners);
	pattern = cairo_pattern_create_linear (0.5, 0.5, 0.5, 0.5+height);

	cairo_fill (cr);
	cairo_pattern_destroy (pattern);

	cairo_restore (cr);

	/* Draw the border */
	ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);

	if (params->prelight || params->disabled)
		ge_cairo_set_color (cr, border);
	else
		excelsior_set_border_gradient (cr, border, 1.2, 0, height);
	cairo_stroke (cr);

	/* Draw handle lines */
	if (width > 14)
	{
		cairo_move_to (cr, 6, 0.5);
		cairo_line_to (cr, 6, height-1);

		cairo_move_to (cr, width-7, 0.5);
		cairo_line_to (cr, width-7, height-1);

		cairo_set_line_width (cr, 1.0);
		cairo_set_source_rgba (cr, border->r,
		                           border->g,
		                           border->b,
	                                   0.3);
		cairo_stroke (cr);
	}
}

static void
excelsior_draw_slider_button (cairo_t *cr,
                               const excelsiorColors *colors,
                               const WidgetParameters *params,
                               const SliderParameters *slider,
                               int x, int y, int width, int height)
{
	double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
	cairo_set_line_width (cr, 1.0);

	if (!slider->horizontal)
		ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
	cairo_translate (cr, x+0.5, y+0.5);

	params->style_functions->draw_shadow (cr, colors, radius, width-1, height-1);
	params->style_functions->draw_slider (cr, colors, params, 1, 1, width-2, height-2);

	if (height > 14)
		params->style_functions->draw_gripdots (cr, colors, 0, 0, width-3, height-1, 3, 2, 0);
}

static void
excelsior_draw_progressbar_trough (cairo_t *cr,
                                    const excelsiorColors *colors,
                                    const WidgetParameters *params,
                                    int x, int y, int width, int height)
{
	const CairoColor *border = &colors->shade[6];
	cairo_pattern_t *pattern;
	const CairoColor *fill   = &colors->bg[params->state_type];
	double          radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0));

	cairo_save (cr);

	cairo_set_line_width (cr, 1.0);

	/* Create trough box */
	ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners);
	ge_cairo_set_color (cr, &colors->shade[1]);
	cairo_fill (cr);

	/* Draw border */
	ge_cairo_rounded_rectangle (cr, x+0.5, y+0.5, width-1, height-1, radius, params->corners);
	ge_cairo_set_color (cr, border);
	cairo_stroke (cr);

	/* clip the corners of the shadows */
	ge_cairo_rounded_rectangle (cr, x+1, y+1, width-2, height-2, radius, params->corners);
	cairo_clip (cr);

	if (height > width)
	{
		int tmp = height;
		height  = width;
		width   = tmp;

		rotate_mirror_translate (cr, G_PI/2, x, y, FALSE, FALSE);
	}


	if (params->button_style == 0)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.96, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width - 1, height - 1, params->radius, params->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 1)
	{

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.15, &shade1);
		ge_shade_color (fill, 1.25, &shade2);
		ge_shade_color (fill, 1.10, &shade3);
		ge_shade_color (fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);

		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width - 1, height - 1, params->radius, params->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 2)
	{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (x, y+1, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);

		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width - 1, height - 1, params->radius, params->corners);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
}

static void
excelsior_draw_progressbar_fill (cairo_t *cr,
                                  const excelsiorColors *colors,
                                  const WidgetParameters *params,
                                  const ProgressBarParameters *progressbar,
                                  int x, int y, int width, int height,
                                  gint offset)
{
	if (progressbar->progbar_style == 2)
	{
	boolean          is_horizontal = progressbar->orientation < 2;
	double           stroke_width;
	int		 x_step;
	double           arrow_width;
	double          radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0));

	cairo_pattern_t *pattern;
	CairoColor fill = colors->bg[GTK_STATE_SELECTED];

	cairo_rectangle (cr, x, y, width, height);
	cairo_clip (cr);
	cairo_new_path (cr);

	if (is_horizontal)
	{
		if (progressbar->orientation == XCL_ORIENTATION_LEFT_TO_RIGHT)
			rotate_mirror_translate (cr, 0, x, y, FALSE, FALSE);
		else
			rotate_mirror_translate (cr, 0, x+width, y, TRUE, FALSE);
	}
	else
	{
		int tmp = height;
		height  = width;
		width   = tmp;

		if (progressbar->orientation == XCL_ORIENTATION_TOP_TO_BOTTOM)
			rotate_mirror_translate (cr, G_PI/2, x, y, FALSE, FALSE);
		else
			rotate_mirror_translate (cr, G_PI/2, x, y+width, TRUE, FALSE);
	}

	stroke_width = height*1.25;

	x_step = (((float)stroke_width/10)*offset);

	arrow_width = stroke_width/2;

	ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);

	/* Draw fill */
	cairo_set_source_rgb (cr, colors->spot[1].r,
	                          colors->spot[1].g,
	                          colors->spot[1].b);
	cairo_fill_preserve (cr);

	if (params->button_style == 0)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (&fill, 0.97, &shade1);
		ge_shade_color (&fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 1)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (&fill, 1.15, &shade1);
		ge_shade_color (&fill, 1.25, &shade2);
		ge_shade_color (&fill, 1.10, &shade3);
		ge_shade_color (&fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 2)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (&fill, 1.15, &shadow);
		ge_shade_color (&fill, 1.25, &hilight);
		ge_shade_color (&fill, 1.10, &f1);
		ge_shade_color (&fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}

	cairo_set_source_rgba (cr, colors->spot[2].r,
	                           colors->spot[2].g,
	                           colors->spot[2].b,
	                           0.15);
	cairo_fill (cr);

	cairo_restore (cr);

	cairo_rectangle (cr, 0.5, 0.5, width-2, height-1);
	cairo_stroke (cr);

	cairo_reset_clip (cr);

	/* Left shadow */
	cairo_translate (cr, width, 0);
	pattern = cairo_pattern_create_linear (0, 0, 3, 0);
	cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0., 0., 0., 0.1);
	cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0., 0., 0., 0.);
	ge_cairo_rounded_rectangle (cr, 0, 0, 3, height, radius, params->corners);
	cairo_set_source (cr, pattern);
	cairo_fill (cr);
	cairo_pattern_destroy (pattern);

	/* End of bar line */
	cairo_move_to (cr, -0.5, 0);
	cairo_line_to (cr, -0.5, 0);
	cairo_set_source_rgba (cr, colors->spot[2].r,
	                           colors->spot[2].g,
	                           colors->spot[2].b,
						0.5);
	cairo_stroke (cr);

	}
	else if (progressbar->progbar_style == 1)
	{
	boolean          is_horizontal = progressbar->orientation < 2;
	double           tile_pos = 0;
	double           stroke_width;
	int		 x_step;
	double           arrow_width;
	double          radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0));

	cairo_pattern_t *pattern;
	CairoColor fill = colors->bg[GTK_STATE_SELECTED];

	cairo_rectangle (cr, x, y, width, height);
	cairo_clip (cr);
	cairo_new_path (cr);

	if (is_horizontal)
	{
		if (progressbar->orientation == XCL_ORIENTATION_LEFT_TO_RIGHT)
			rotate_mirror_translate (cr, 0, x, y, FALSE, FALSE);
		else
			rotate_mirror_translate (cr, 0, x+width, y, TRUE, FALSE);
	}
	else
	{
		int tmp = height;
		height  = width;
		width   = tmp;

		if (progressbar->orientation == XCL_ORIENTATION_TOP_TO_BOTTOM)
			rotate_mirror_translate (cr, G_PI/2, x, y, FALSE, FALSE);
		else
			rotate_mirror_translate (cr, G_PI/2, x, y+width, TRUE, FALSE);
	}

	stroke_width = height*1.25;

	x_step = (((float)stroke_width/10)*offset);

	arrow_width = stroke_width/2;

	ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);

	/* Draw fill */
	cairo_set_source_rgb (cr, colors->spot[1].r,
	                          colors->spot[1].g,
	                          colors->spot[1].b);
	cairo_fill_preserve (cr);

	if (params->button_style == 0)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (&fill, 0.97, &shade1);
		ge_shade_color (&fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 1)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (&fill, 1.15, &shade1);
		ge_shade_color (&fill, 1.25, &shade2);
		ge_shade_color (&fill, 1.10, &shade3);
		ge_shade_color (&fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 2)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (&fill, 1.15, &shadow);
		ge_shade_color (&fill, 1.25, &hilight);
		ge_shade_color (&fill, 1.10, &f1);
		ge_shade_color (&fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}

	/* Draw strokes */

	while (tile_pos <= width+x_step)
	{
		cairo_move_to (cr, stroke_width/2-x_step, 0);
		cairo_line_to (cr, stroke_width-x_step, height/2);
		cairo_line_to (cr, stroke_width/2-x_step, height);
		cairo_line_to (cr, stroke_width/2-x_step-arrow_width, height);
		cairo_line_to (cr, stroke_width-x_step-arrow_width, height/2);
		cairo_line_to (cr, stroke_width/2-x_step-arrow_width, 0);

		cairo_translate (cr, stroke_width, 0);
		tile_pos += stroke_width;
	}

	cairo_set_source_rgba (cr, colors->spot[2].r,
	                           colors->spot[2].g,
	                           colors->spot[2].b,
	                           0.15);

	cairo_fill (cr);

	cairo_restore (cr);

	cairo_rectangle (cr, 0.5, 0.5, width-2, height-1);
	cairo_stroke (cr);

	cairo_reset_clip (cr);

	/* Left shadow */
	cairo_translate (cr, width, 0);
	pattern = cairo_pattern_create_linear (0, 0, 3, 0);
	cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0., 0., 0., 0.1);
	cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0., 0., 0., 0.);
	ge_cairo_rounded_rectangle (cr, 0, 0, 3, height, radius, params->corners);
	cairo_set_source (cr, pattern);
	cairo_fill (cr);
	cairo_pattern_destroy (pattern);

	/* End of bar line */
	cairo_move_to (cr, -0.5, 0);
	cairo_line_to (cr, -0.5, 0);
	cairo_set_source_rgba (cr, colors->spot[2].r,
	                           colors->spot[2].g,
	                           colors->spot[2].b,
						0.5);
	cairo_stroke (cr);
	}
	else if (progressbar->progbar_style == 0)
	{

	boolean          is_horizontal = progressbar->orientation < 2;
	double           tile_pos = 0;
	double           stroke_width;
	int		 x_step;
	double           arrow_width;
	double          radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0));

	cairo_pattern_t *pattern;
	CairoColor fill = colors->bg[GTK_STATE_SELECTED];

	cairo_rectangle (cr, x, y, width, height);
	cairo_clip (cr);
	cairo_new_path (cr);

	if (is_horizontal)
	{
		if (progressbar->orientation == XCL_ORIENTATION_LEFT_TO_RIGHT)
			rotate_mirror_translate (cr, 0, x, y, FALSE, FALSE);
		else
			rotate_mirror_translate (cr, 0, x+width, y, TRUE, FALSE);
	}
	else
	{
		int tmp = height;
		height  = width;
		width   = tmp;

		if (progressbar->orientation == XCL_ORIENTATION_TOP_TO_BOTTOM)
			rotate_mirror_translate (cr, G_PI/2, x, y, FALSE, FALSE);
		else
			rotate_mirror_translate (cr, G_PI/2, x, y+width, TRUE, FALSE);
	}

	stroke_width = height*1.25;

	x_step = (((float)stroke_width/10)*offset);

	arrow_width = stroke_width/2;

	ge_cairo_rounded_rectangle (cr, 0, 0, width, height, radius, params->corners);

	/* Draw fill */
	cairo_set_source_rgb (cr, colors->spot[1].r,
	                          colors->spot[1].g,
	                          colors->spot[1].b);
	cairo_fill_preserve (cr);

	if (params->button_style == 0)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (&fill, 0.97, &shade1);
		ge_shade_color (&fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 1)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (&fill, 1.15, &shade1);
		ge_shade_color (&fill, 1.25, &shade2);
		ge_shade_color (&fill, 1.10, &shade3);
		ge_shade_color (&fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 2)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (&fill, 1.15, &shadow);
		ge_shade_color (&fill, 1.25, &hilight);
		ge_shade_color (&fill, 1.10, &f1);
		ge_shade_color (&fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}

	/* Draw the Strokes */
	while (tile_pos <= width+x_step)
	{
		cairo_move_to (cr, stroke_width/2-x_step, 0);
		cairo_line_to (cr, stroke_width-x_step,   0);
		cairo_line_to (cr, stroke_width/2-x_step, height);
		cairo_line_to (cr, -x_step, height);

		cairo_translate (cr, stroke_width, 0);
		tile_pos += stroke_width;
	}

	cairo_set_source_rgba (cr, colors->spot[2].r,
	                           colors->spot[2].g,
	                           colors->spot[2].b,
	                           0.15);

	cairo_fill (cr);

	cairo_restore (cr);

	cairo_rectangle (cr, 0.5, 0.5, width-2, height-1);
	cairo_stroke (cr);

	cairo_reset_clip (cr);

	/* Left shadow */
	cairo_translate (cr, width, 0);
	pattern = cairo_pattern_create_linear (0, 0, 3, 0);
	cairo_pattern_add_color_stop_rgba (pattern, 0.0, 0., 0., 0., 0.1);
	cairo_pattern_add_color_stop_rgba (pattern, 1.0, 0., 0., 0., 0.);
	ge_cairo_rounded_rectangle (cr, 0, 0, 3, height, radius, params->corners);
	cairo_set_source (cr, pattern);
	cairo_fill (cr);
	cairo_pattern_destroy (pattern);

	/* End of bar line */
	cairo_move_to (cr, -0.5, 0);
	cairo_line_to (cr, -0.5, 0);
	cairo_set_source_rgba (cr, colors->spot[2].r,
	                           colors->spot[2].g,
	                           colors->spot[2].b,
						0.5);
	cairo_stroke (cr);

	}
}

static void
excelsior_draw_optionmenu (cairo_t *cr,
                            const excelsiorColors *colors,
                            const WidgetParameters *params,
                            const OptionMenuParameters *optionmenu,
                            int x, int y, int width, int height)
{
	params->style_functions->draw_button (cr, colors, params, x, y, width, height, 0.5);
}

static void
excelsior_draw_menu_item_separator (cairo_t                   *cr,
                                     const excelsiorColors    *colors,
                                     const WidgetParameters    *widget,
                                     const SeparatorParameters *separator,
                                     int x, int y, int width, int height)
{
	cairo_save (cr);
	cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
	ge_cairo_set_color (cr, &colors->shade[5]);

	if (separator->horizontal)
		cairo_rectangle (cr, x, y, width, 1);
	else
		cairo_rectangle (cr, x, y, 1, height);

	cairo_fill      (cr);

	cairo_restore (cr);
}

static void
excelsior_draw_menubar0 (cairo_t *cr,
                          const excelsiorColors *colors,
                          const WidgetParameters *params,
                          const MenuBarParameters *menubar,
                          int x, int y, int width, int height)
{
	CairoColor lower;
	CairoColor top;
	cairo_pattern_t *pattern;

	ge_shade_color (&colors->bg[0], 0.9, &top);
	ge_shade_color (&colors->bg[0], 1.1, &lower);

	cairo_translate (cr, x, y);
	cairo_rectangle (cr, 0, 0, width, height);

	/* Draw the gradient */
	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.0, top.r,
	                                                top.g,
	                                                top.b);
	cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r,
	                                                lower.g,
	                                                lower.b);
	cairo_set_source      (cr, pattern);
	cairo_fill            (cr);
	cairo_pattern_destroy (pattern);

}

static void
excelsior_draw_menubar1 (cairo_t *cr,
                          const excelsiorColors *colors,
                          const WidgetParameters *params,
                          const MenuBarParameters *menubar,
                          int x, int y, int width, int height)
{
	CairoColor lower;
	CairoColor top;
	cairo_pattern_t *pattern;

	ge_shade_color (&colors->bg[0], 1.1, &top);
	ge_shade_color (&colors->bg[0], 0.9, &lower);

	cairo_translate (cr, x, y);
	cairo_rectangle (cr, 0, 0, width, height);

	/* Draw the gradient */
	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.0, top.r,
	                                                top.g,
	                                                top.b);
	cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r,
	                                                lower.g,
	                                                lower.b);
	cairo_set_source      (cr, pattern);
	cairo_fill            (cr);
	cairo_stroke (cr);
	cairo_pattern_destroy (pattern);

}

static void
excelsior_draw_menubar2 (cairo_t *cr,
                          const excelsiorColors *colors,
                          const WidgetParameters *params,
                          const MenuBarParameters *menubar,
                          int x, int y, int width, int height)
{
	CairoColor lower;
	CairoColor top;
	cairo_pattern_t *pattern;

	ge_shade_color (&colors->bg[0], 0.95, &top);
	ge_shade_color (&colors->bg[0], 1.10, &lower);

	cairo_translate (cr, x, y);
	cairo_rectangle (cr, 0, 0, width, height);

	/* Draw the gradient */
	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.0, top.r,
	                                                top.g,
	                                                top.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.3, top.r,
	                                                top.g,
	                                                top.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.7, lower.r,
	                                                lower.g,
	                                                lower.b);
	cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r,
	                                                lower.g,
	                                                lower.b);
	cairo_set_source      (cr, pattern);
	cairo_fill            (cr);
	cairo_stroke (cr);
	cairo_pattern_destroy (pattern);

}

static menubar_draw_proto excelsior_menubar_draw[4] =
{
	excelsior_draw_menubar0,
	excelsior_draw_menubar1,
	excelsior_draw_menubar2
};

static void
excelsior_draw_menubar (cairo_t *cr,
                         const excelsiorColors *colors,
                         const WidgetParameters *params,
                         const MenuBarParameters *menubar,
                         int x, int y, int width, int height)
{
	if (menubar->style < 0 || menubar->style >= G_N_ELEMENTS (excelsior_menubar_draw))
		return;

	excelsior_menubar_draw[menubar->style](cr, colors, params, menubar,
	                             x, y, width, height);
}

static void
excelsior_get_frame_gap_clip (int x, int y, int width, int height,
                               const FrameParameters     *frame,
                               excelsiorRectangle *bevel,
                               excelsiorRectangle *border)
{
	if (frame->gap_side == XCL_GAP_TOP)
	{
		EXCELSIOR_RECTANGLE_SET ((*bevel),  1.5 + frame->gap_x,  -0.5,
											 frame->gap_width - 3, 2.0);
		EXCELSIOR_RECTANGLE_SET ((*border), 0.5 + frame->gap_x,  -0.5,
											 frame->gap_width - 2, 2.0);
	}
	else if (frame->gap_side == XCL_GAP_BOTTOM)
	{
		EXCELSIOR_RECTANGLE_SET ((*bevel),  1.5 + frame->gap_x,  height - 2.5,
											 frame->gap_width - 3, 2.0);
		EXCELSIOR_RECTANGLE_SET ((*border), 0.5 + frame->gap_x,  height - 1.5,
											 frame->gap_width - 2, 2.0);
	}
	else if (frame->gap_side == XCL_GAP_LEFT)
	{
		EXCELSIOR_RECTANGLE_SET ((*bevel),  -0.5, 1.5 + frame->gap_x,
											 2.0, frame->gap_width - 3);
		EXCELSIOR_RECTANGLE_SET ((*border), -0.5, 0.5 + frame->gap_x,
											 1.0, frame->gap_width - 2);
	}
	else if (frame->gap_side == XCL_GAP_RIGHT)
	{
		EXCELSIOR_RECTANGLE_SET ((*bevel),  width - 2.5, 1.5 + frame->gap_x,
											 2.0, frame->gap_width - 3);
		EXCELSIOR_RECTANGLE_SET ((*border), width - 1.5, 0.5 + frame->gap_x,
											 1.0, frame->gap_width - 2);
	}
}

static void
excelsior_draw_frame            (cairo_t *cr,
                                  const excelsiorColors     *colors,
                                  const WidgetParameters     *params,
                                  const FrameParameters      *frame,
                                  int x, int y, int width, int height)
{
	const CairoColor *border = frame->border;
	const CairoColor *dark   = (CairoColor*)&colors->shade[8];
	excelsiorRectangle bevel_clip = {0, 0, 0, 0};
	excelsiorRectangle frame_clip = {0, 0, 0, 0};
	double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
	CairoColor hilight;

	ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 1.05, &hilight);

	if (frame->shadow == XCL_SHADOW_NONE)
		return;

	if (frame->gap_x != -1)
		excelsior_get_frame_gap_clip (x, y, width, height,
		                               frame, &bevel_clip, &frame_clip);

	cairo_set_line_width (cr, 1.0);
	cairo_translate      (cr, x+0.5, y+0.5);

	/* save everything */
	cairo_save (cr);
	/* Set clip for the bevel */
	if (frame->gap_x != -1)
	{
		/* Set clip for gap */
		cairo_set_fill_rule  (cr, CAIRO_FILL_RULE_EVEN_ODD);
		cairo_rectangle      (cr, -0.5, -0.5, width, height);
		cairo_rectangle      (cr, bevel_clip.x, bevel_clip.y, bevel_clip.width, bevel_clip.height);
		cairo_clip           (cr);
	}

	/* Draw the bevel */
	if (frame->shadow == XCL_SHADOW_ETCHED_IN || frame->shadow == XCL_SHADOW_ETCHED_OUT)
	{
		ge_cairo_set_color (cr, &hilight);
		if (frame->shadow == XCL_SHADOW_ETCHED_IN)
			ge_cairo_rounded_rectangle (cr, 0, 0, width-2, height-2, radius, params->corners);
		else
			ge_cairo_rounded_rectangle (cr, 0, 0, width-2, height-2, radius, params->corners);
		cairo_stroke (cr);
	}
	else if (frame->shadow != XCL_SHADOW_NONE)
	{
		ShadowParameters shadow;
		shadow.corners = params->corners;
		shadow.shadow  = frame->shadow;
		excelsior_draw_highlight_and_shade (cr, colors, &shadow, width, height, 0);
	}

	/* restore the previous clip region */
	cairo_restore    (cr);
	cairo_save       (cr);
	if (frame->gap_x != -1)
	{
		/* Set clip for gap */
		cairo_set_fill_rule  (cr, CAIRO_FILL_RULE_EVEN_ODD);
		cairo_rectangle      (cr, -0.5, -0.5, width, height);
		cairo_rectangle      (cr, frame_clip.x, frame_clip.y, frame_clip.width, frame_clip.height);
		cairo_clip           (cr);
	}

	/* Draw frame */
	if (frame->shadow == XCL_SHADOW_ETCHED_IN || frame->shadow == XCL_SHADOW_ETCHED_OUT)
	{
		ge_cairo_set_color (cr, dark);
		if (frame->shadow == XCL_SHADOW_ETCHED_IN)
			ge_cairo_rounded_rectangle (cr, 0, 0, width-2, height-2, radius, params->corners);
		else
			ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, params->corners);
	}
	else
	{
		ge_cairo_set_color (cr, border);
		ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
	}
	cairo_stroke (cr);

	cairo_restore (cr);
}

static void
excelsior_draw_tab (cairo_t *cr,
                     const excelsiorColors *colors,
                     const WidgetParameters *params,
                     const TabParameters    *tab,
                     int x, int y, int width, int height)
{
	const CairoColor    *border       = &colors->shade[5];
	const CairoColor    *stripe_fill   = &colors->spot[1];
	const CairoColor    *stripe_border = &colors->spot[2];
	const CairoColor    *random_color = &colors->text[GTK_STATE_NORMAL];
	const CairoColor    *fill;
	CairoColor           hilight, middle;

	cairo_pattern_t     *pattern;

	double               radius;
	double               strip_size;
	double               length;

	radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));

	/* Set clip */
	cairo_rectangle      (cr, x, y, width, height);
	cairo_clip           (cr);
	cairo_new_path       (cr);

	/* Translate and set line width */
	cairo_set_line_width (cr, 1.0);
	cairo_translate      (cr, x+0.5, y+0.5);


	/* Make the tabs slightly bigger than they should be, to create a gap */
	/* And calculate the strip size too, while you're at it */
	if (tab->gap_side == XCL_GAP_TOP || tab->gap_side == XCL_GAP_BOTTOM)
	{
		height += 3.0;
		length = height;
	 	strip_size = 2.0/height; /* 2 pixel high strip */

		if (tab->gap_side == XCL_GAP_TOP)
			cairo_translate (cr, 0.0, -3.0); /* gap at the other side */
	}
	else
	{
		width += 3.0;
		length = width;
	 	strip_size = 2.0/width;

		if (tab->gap_side == XCL_GAP_LEFT)
			cairo_translate (cr, -3.0, 0.0); /* gap at the other side */
	}

	/* Set the fill color */
	fill = &colors->bg[params->state_type];

	/* Set tab shape */
	ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1,
	                            radius, params->corners);

	/* Draw fill */
	ge_shade_color (fill, 1.25, &hilight);
	ge_cairo_set_color (cr, &hilight);
	cairo_fill   (cr);



	/* Draw highlight */
	if (!params->active)
	{
		ShadowParameters shadow;

		shadow.shadow  = XCL_SHADOW_OUT;
		shadow.corners = params->corners;

		excelsior_draw_highlight_and_shade (cr, colors, &shadow, width, height, radius);
	}

	if (params->active)
	{
		CairoColor shadow, hilight, f1, f2;

		switch (tab->gap_side)
		{
			case XCL_GAP_TOP:
				pattern = cairo_pattern_create_linear (0, height-2, 0, 0);
				break;
			case XCL_GAP_BOTTOM:
				pattern = cairo_pattern_create_linear (0, 1, 0, height);
				break;
			case XCL_GAP_LEFT:
				pattern = cairo_pattern_create_linear (width-2, 0, 1, 0);
				break;
			case XCL_GAP_RIGHT:
				pattern = cairo_pattern_create_linear (1, 0, width-2, 0);
				break;
			default:
				pattern = NULL;
		}

		ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);

		if (params->aqua_tabs == 0)
		{
			if (params->button_style == 0)
			{
			CairoColor low;

			ge_shade_color (fill, 0.96, &middle);
			ge_shade_color (fill, 1.15, &low);

			cairo_pattern_add_color_stop_rgb (pattern, 0.00, middle.r, middle.g, middle.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.35, middle.r, middle.g, middle.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.65, low.r, low.g, low.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.90, low.r, low.g, low.b);
			cairo_set_source (cr, pattern);
			cairo_fill (cr);
			cairo_pattern_destroy (pattern);
			}
			else if (params->button_style == 1)
			{

			CairoColor shade1, shade2, shade3, shade4;
			ge_shade_color (fill, 1.15, &shade1);
			ge_shade_color (fill, 1.25, &shade2);
			ge_shade_color (fill, 1.10, &shade3);
			ge_shade_color (fill, 0.95, &shade4);

			cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
			cairo_set_source (cr, pattern);
			cairo_fill (cr);
			cairo_pattern_destroy (pattern);
			}
		}
		else if (params->aqua_tabs == 1)
		{

			ge_shade_color (fill, 1.15, &shadow);
			ge_shade_color (fill, 1.25, &hilight);
			ge_shade_color (fill, 1.10, &f1);
			ge_shade_color (fill, 0.95, &f2);

			cairo_pattern_add_color_stop_rgb (pattern, 0.00,        hilight.r, hilight.g, hilight.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.35,        f1.r, f1.g, f1.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.65,        f2.r, f2.g, f2.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.90,        shadow.r, shadow.g, shadow.b);
			cairo_set_source (cr, pattern);
			cairo_fill (cr);
			cairo_pattern_destroy (pattern);
		}
}
	else
	{
		CairoColor shadow, hilight, f1, f2;
		/* Draw shade */
		switch (tab->gap_side)
		{
			case XCL_GAP_TOP:
				pattern = cairo_pattern_create_linear (0, height-2, 0, 0);
				break;
			case XCL_GAP_BOTTOM:
				pattern = cairo_pattern_create_linear (0, 0, 0, height);
				break;
			case XCL_GAP_LEFT:
				pattern = cairo_pattern_create_linear (width-2, 0, 0, 0);
				break;
			case XCL_GAP_RIGHT:
				pattern = cairo_pattern_create_linear (0, 0, width, 0);
				break;
			default:
				pattern = NULL;
		}
		ge_cairo_rounded_rectangle (cr, 1, 1, width-3, height-1, radius, params->corners);


		if (params->aqua_tabs == 0)
		{
			if (params->button_style == 0)
			{
			CairoColor low;

			ge_shade_color (stripe_fill, 0.96, &middle);
			ge_shade_color (stripe_fill, 1.15, &low);

			cairo_pattern_add_color_stop_rgb (pattern, 0.00, middle.r, middle.g, middle.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.35, middle.r, middle.g, middle.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.65, low.r, low.g, low.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.90, low.r, low.g, low.b);
			cairo_set_source (cr, pattern);
			cairo_fill (cr);
			cairo_pattern_destroy (pattern);
			}
			else if (params->button_style == 1)
			{
			CairoColor shade1, shade2, shade3, shade4;
			ge_shade_color (stripe_fill, 1.15, &shade1);
			ge_shade_color (stripe_fill, 1.25, &shade2);
			ge_shade_color (stripe_fill, 1.10, &shade3);
			ge_shade_color (stripe_fill, 0.95, &shade4);

			cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
			cairo_set_source (cr, pattern);
			cairo_fill (cr);
			cairo_pattern_destroy (pattern);
			}
		}
		else if (params->aqua_tabs == 1)
		{
			ge_shade_color (fill, 1.15, &shadow);
			ge_shade_color (stripe_fill, 1.25, &hilight);
			ge_shade_color (stripe_fill, 1.10, &f1);
			ge_shade_color (stripe_fill, 0.95, &f2);

			cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
			cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shadow.r, shadow.g, shadow.b);
			cairo_set_source (cr, pattern);
			cairo_fill (cr);
			cairo_pattern_destroy (pattern);
		}
}

	ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);

	if (params->active)
	{
		ge_cairo_set_color (cr, border);
		cairo_stroke (cr);
	}
	else
	{
		switch (tab->gap_side)
		{
			case XCL_GAP_TOP:
				pattern = cairo_pattern_create_linear (2, height-2, 2, 2);
				break;
			case XCL_GAP_BOTTOM:
				pattern = cairo_pattern_create_linear (2, 2, 2, height);
				break;
			case XCL_GAP_LEFT:
				pattern = cairo_pattern_create_linear (width-2, 2, 2, 2);
				break;
			case XCL_GAP_RIGHT:
				pattern = cairo_pattern_create_linear (2, 2, width, 2);
				break;
			default:
				pattern = NULL;
		}

		cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.8, border->r,        border->g,        border->b);
		cairo_set_source (cr, pattern);
		cairo_stroke (cr);

		cairo_restore (cr);
		cairo_pattern_destroy (pattern);

	}

	if (params->random_effect == 1)
	{
		cairo_set_source_rgba(cr, random_color->r, random_color->g, random_color->b, params->random_opacity);
		excelsior_draw_random_stripes(cr,1,1,x,y,width-4,height-4,(width*2.75)/100);
	}
	else if (params->random_effect == 2)
	{
		cairo_set_source_rgba(cr, random_color->r, random_color->g, random_color->b, params->random_opacity);

		excelsior_draw_random_circles(cr,1,1,x*1.5,y/1.5,width-4,height-4,(width*2)/150, 6, 4);
		excelsior_draw_random_circles(cr,1,1,x*2,y*2,width-4,height-4,(width*2)/2250, 4, 2);
		excelsior_draw_random_circles(cr,1,1,x/1.5,y*1.5,width-4,height-4,(width*2)/225, 8, 6);

	}

}

static void
excelsior_draw_separator (cairo_t *cr,
                           const excelsiorColors     *colors,
                           const WidgetParameters     *widget,
                           const SeparatorParameters  *separator,
                           int x, int y, int width, int height)
{

/* We don't want separators to be drawn, therefore leave emtpy */

}

static void
excelsior_draw_list_view_header (cairo_t *cr,
                                  const excelsiorColors          *colors,
                                  const WidgetParameters          *params,
                                  const ListViewHeaderParameters  *header,
                                  int x, int y, int width, int height)
{
	const CairoColor *fill = &colors->bg[GTK_STATE_NORMAL];
	cairo_pattern_t *pattern;

	cairo_translate (cr, x, y);

	if (params->button_style == 0)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.96, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 1)
	{

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (fill, 1.15, &shade1);
		ge_shade_color (fill, 1.25, &shade2);
		ge_shade_color (fill, 1.10, &shade3);
		ge_shade_color (fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (params->button_style == 2)
	{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}

	/* Draw resize grip */
	if ((params->ltr && header->order != XCL_ORDER_LAST) ||
	    (!params->ltr && header->order != XCL_ORDER_FIRST) || header->resizable)
	{
		SeparatorParameters separator;
		separator.horizontal = FALSE;

		if (params->ltr)
			params->style_functions->draw_separator (cr, colors, params, &separator,
			                                         width-1.5, 4.0, 2, height-8.0);
		else
			params->style_functions->draw_separator (cr, colors, params, &separator,
			                                         1.5, 4.0, 2, height-8.0);
	}
}

static void
excelsior_draw_toolbar (cairo_t *cr,
                         const excelsiorColors          *colors,
                         const WidgetParameters          *widget,
                         const ToolbarParameters         *toolbar,
                         int x, int y, int width, int height)
{
	const CairoColor *fill  = &colors->bg[GTK_STATE_NORMAL];
	CairoColor light;
	ge_shade_color (fill, 1.1, &light);

	cairo_set_line_width (cr, 1.0);
	cairo_translate (cr, x, y);

	if (toolbar->style == 2)
	{
		cairo_pattern_t *pattern;
		CairoColor top, lower;

		ge_shade_color (&colors->bg[0], 1.10, &top);
		ge_shade_color (&colors->bg[0], 0.95, &lower);

		/* Draw the fill */
		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.0, top.r,
								top.g,
								top.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.3, top.r,
								top.g,
								top.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.7, lower.r,
								lower.g,
								lower.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r,
								lower.g,
								lower.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_fill (cr);

		cairo_pattern_destroy (pattern);
	}
	if (toolbar->style == 1)
	{
		cairo_pattern_t *pattern;
		CairoColor top, lower;

		ge_shade_color (&colors->bg[0], 0.9, &top);
		ge_shade_color (&colors->bg[0], 1.1, &lower);

		/* Draw the fill */
		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.0, top.r,
								top.g,
								top.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r,
								lower.g,
								lower.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_fill (cr);

		cairo_pattern_destroy (pattern);
	}
	else if (toolbar->style == 0)
	{
		cairo_pattern_t *pattern;
		CairoColor top, lower;

		ge_shade_color (&colors->bg[0], 1.1, &top);
		ge_shade_color (&colors->bg[0], 0.9, &lower);

		/* Draw the fill */
		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.0, top.r,
								top.g,
								top.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower.r,
								lower.g,
								lower.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 0, 0, width, height);
		cairo_fill (cr);

		cairo_pattern_destroy (pattern);
	}
}

static void
excelsior_draw_menuitem (cairo_t *cr,
                          const excelsiorColors          *colors,
                          const WidgetParameters          *widget,
                          int x, int y, int width, int height)
{
	const CairoColor *fill = &colors->bg[GTK_STATE_SELECTED];
	CairoColor border = colors->spot[2];
	cairo_pattern_t *pattern;

	ge_shade_color (&border, 1.05, &border);

	if (widget->button_style == 0)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.96, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 1)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 1.10, &shade1);
		ge_shade_color (fill, 0.95, &shade2);

		pattern = cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.40, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);

		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 2)
	{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);

		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}

	ge_cairo_set_color (cr, &border);
	cairo_stroke (cr);
}

static void
excelsior_draw_menubaritem (cairo_t *cr,
                          const excelsiorColors          *colors,
                          const WidgetParameters          *widget,
                          int x, int y, int width, int height)
{
	const CairoColor *fill = &colors->bg[GTK_STATE_SELECTED];
	CairoColor border = colors->spot[2];
	cairo_pattern_t *pattern;

	ge_shade_color (&border, 1.05, &border);
	cairo_set_line_width (cr, 1.0);

	if (widget->button_style == 0)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.96, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 1)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 1.10, &shade1);
		ge_shade_color (fill, 0.95, &shade2);

		pattern = cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.40, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);

		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 2)
	{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.10, &f1);
		ge_shade_color (fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (x, y, x, y + height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);

		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}

	ge_cairo_set_color (cr, &border);
	cairo_stroke_preserve (cr);
}

static void
excelsior_draw_selected_cell (cairo_t                  *cr,
	                       const excelsiorColors   *colors,
	                       const WidgetParameters   *params,
	                       int x, int y, int width, int height)
{
	CairoColor upper_color;
	CairoColor lower_color;
	CairoColor border;
	cairo_pattern_t *pattern;
	cairo_save (cr);

	cairo_translate (cr, x, y);

	if (params->focus)
		upper_color = colors->base[params->state_type];
	else
		upper_color = colors->base[GTK_STATE_ACTIVE];

	ge_shade_color(&upper_color, 0.92, &lower_color);

	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.0, upper_color.r,
	                                                upper_color.g,
	                                                upper_color.b);
	cairo_pattern_add_color_stop_rgb (pattern, 1.0, lower_color.r,
	                                                lower_color.g,
	                                                lower_color.b);

	cairo_set_source (cr, pattern);
	cairo_rectangle  (cr, 0, 0, width, height);
	cairo_fill       (cr);

	cairo_pattern_destroy (pattern);

	ge_shade_color(&upper_color, 0.8, &border);

	cairo_move_to  (cr, 0, 0.5);
	cairo_rel_line_to (cr, width, 0);
	cairo_move_to  (cr, 0, height-0.5);
	cairo_rel_line_to (cr, width, 0);

	ge_cairo_set_color (cr, &border);
	cairo_stroke (cr);

	cairo_restore (cr);
}

static void
excelsior_draw_scrollbar_trough (cairo_t *cr,
                                  const excelsiorColors           *colors,
                                  const WidgetParameters           *widget,
                                  const ScrollBarParameters        *scrollbar,
                                  int x, int y, int width, int height)
{
	const CairoColor *bg     = &colors->shade[2];
	const CairoColor *border = &colors->shade[5];
	const CairoColor *fill   = &colors->bg[widget->state_type];
	CairoColor        bg_shade;
	cairo_pattern_t *pattern;

	ge_shade_color (bg, 0.95, &bg_shade);

	cairo_set_line_width (cr, 0.5);

	if (scrollbar->horizontal)
		ge_cairo_exchange_axis (cr, &x, &y, &width, &height);

	cairo_translate (cr, x, y+1);

	if (widget->button_style == 0)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 0.94, &shade1);
		ge_shade_color (fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, width, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, 1.0, CR_CORNER_NONE);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 1)
	{

		CairoColor shade1, shade2;
		ge_shade_color (fill, 1.10, &shade1);
		ge_shade_color (fill, 0.92, &shade2);

		pattern = cairo_pattern_create_linear (0, 0, width, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.95, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, 1.0, CR_CORNER_NONE);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 2)
	{
		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (fill, 1.15, &shadow);
		ge_shade_color (fill, 1.25, &hilight);
		ge_shade_color (fill, 1.00, &f1);
		ge_shade_color (fill, 0.85, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		ge_cairo_rounded_rectangle (cr, 0, 0, width, height, 1.0, CR_CORNER_NONE);
		cairo_fill_preserve (cr);
		cairo_pattern_destroy (pattern);
	}

	cairo_rectangle (cr, 0.5, 0.5, width-1, height-1);
	ge_cairo_set_color (cr, border);
	cairo_stroke (cr);

}

static void
excelsior_draw_scrollbar_stepper (cairo_t *cr,
                                   const excelsiorColors            *colors,
                                   const WidgetParameters           *widget,
                                   const ScrollBarParameters        *scrollbar,
                                   const ScrollBarStepperParameters *stepper,
                                   int x, int y, int width, int height)
{

/* we want "transparent" steppers, therefore leave empty! */

}

static void
excelsior_draw_scrollbar_slider (cairo_t *cr,
                                   const excelsiorColors          *colors,
                                   const WidgetParameters          *widget,
                                   const ScrollBarParameters       *scrollbar,
                                   int x, int y, int width, int height)
{

	CairoColor *border = (CairoColor*)&colors->shade[6];

	CairoColor fill = colors->bg[GTK_STATE_SELECTED];

	CairoColor hilight;

	double tile_pos = 0;
	double stroke_width;
	int x_step;
	int offset;
	double arrow_width;
	CairoColor shading;

	if (scrollbar->horizontal)
	{
		cairo_translate (cr, x, y);
	}
	else
	{
		int tmp = height;
		rotate_mirror_translate (cr, G_PI/2, x, y, FALSE, FALSE);
		height = width;
		width = tmp;
	}

	if (widget->prelight)
		ge_shade_color (&fill, 1.1, &fill);

	cairo_set_line_width (cr, 1);

	ge_shade_color (&fill, 1.45, &hilight);

	if (widget->button_style == 0)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2;
		ge_shade_color (&fill, 0.97, &shade1);
		ge_shade_color (&fill, 1.10, &shade2);

		pattern	= cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.35, shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.65, shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 1.00, shade2.r, shade2.g, shade2.b);
		cairo_rectangle (cr, 3, 2, width-6, height-4);
		cairo_set_source (cr, pattern);
		cairo_fill(cr);
		cairo_pattern_destroy (pattern);
	}
	else if (widget->button_style == 1)
	{
		cairo_pattern_t *pattern;

		CairoColor shade1, shade2, shade3, shade4;
		ge_shade_color (&fill, 1.15, &shade1);
		ge_shade_color (&fill, 1.25, &shade2);
		ge_shade_color (&fill, 1.10, &shade3);
		ge_shade_color (&fill, 0.95, &shade4);

		pattern = cairo_pattern_create_linear (0, 0, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	shade2.r, shade2.g, shade2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.50,        shade3.r, shade3.g, shade3.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.60,       	shade1.r, shade1.g, shade1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.90,       	shade4.r, shade4.g, shade4.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 3, 2, width-6, height-4);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);

	}
	else if (widget->button_style == 2)
	{
		cairo_pattern_t *pattern;

		CairoColor shadow, hilight, f1, f2;

		ge_shade_color (&fill, 1.15, &shadow);
		ge_shade_color (&fill, 1.25, &hilight);
		ge_shade_color (&fill, 1.10, &f1);
		ge_shade_color (&fill, 0.95, &f2);

		pattern = cairo_pattern_create_linear (0, 1, 0, height);
		cairo_pattern_add_color_stop_rgb (pattern, 0.00,       	hilight.r, hilight.g, hilight.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.30, 	f1.r, f1.g, f1.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.45,       	f2.r, f2.g, f2.b);
		cairo_pattern_add_color_stop_rgb (pattern, 0.70,       	shadow.r, shadow.g, shadow.b);
		cairo_set_source (cr, pattern);
		cairo_rectangle (cr, 3, 2, width-6, height-4);
		cairo_fill (cr);
		cairo_pattern_destroy (pattern);
	}

		cairo_rectangle (cr, 2.5, 1.5, width-5, height-3);
		cairo_set_source_rgb (cr, hilight.r, hilight.g, hilight.b);
		cairo_stroke (cr);

		ge_cairo_rounded_rectangle (cr, 1.5, 0.5, width-3, height-1, 2, widget->corners);
		cairo_set_source_rgb (cr, border->r, border->g, border->b);
		cairo_stroke (cr);

	if (scrollbar->style == 1)
	{
		stroke_width = 25;
		offset = 1;
		x_step = (((float)stroke_width/10)*offset);
		arrow_width = stroke_width/2;
		while (tile_pos <= width+x_step)
		{
			cairo_move_to (cr, stroke_width/2-x_step, 0);
			cairo_line_to (cr, stroke_width-x_step, height/2);
			cairo_line_to (cr, stroke_width/2-x_step, height);
			cairo_line_to (cr, stroke_width/2-x_step-arrow_width, height);
			cairo_line_to (cr, stroke_width-x_step-arrow_width, height/2);
			cairo_line_to (cr, stroke_width/2-x_step-arrow_width, 0);

			cairo_translate (cr, stroke_width, 0);
			tile_pos += stroke_width;
		}

		cairo_set_source_rgba (cr, colors->spot[2].r,
					colors->spot[2].g,
					colors->spot[2].b,
					 0.15);
		cairo_fill (cr);
		cairo_restore (cr);
		cairo_set_source_rgba (cr, colors->spot[0].r, colors->spot[0].g, colors->spot[0].b, 0.5);
		cairo_rectangle (cr, 0.5, 0.5, width-2, height-1);
		cairo_stroke (cr);
		cairo_reset_clip (cr);
	}
	else if (scrollbar->style == 0)
	{
		double stroke_width = 25;

		x_step = (((float)stroke_width/10)*2);

		/* Draw strokes */
		while (tile_pos <= width+x_step)
		{
			cairo_move_to (cr, stroke_width/2-x_step, 0);
			cairo_line_to (cr, stroke_width-x_step,   0);
			cairo_line_to (cr, stroke_width/2-x_step-2, height);
			cairo_line_to (cr, -x_step, height);
			cairo_translate (cr, stroke_width, 0);
			tile_pos += stroke_width;
		}

		cairo_set_source_rgba (cr, colors->spot[2].r,
						colors->spot[2].g,
						colors->spot[2].b,
						0.15);

		cairo_fill (cr);

		cairo_restore (cr);

		ge_shade_color (&colors->bg[GTK_STATE_SELECTED], 1.00, &shading);

		cairo_set_source_rgba (cr, shading.r, shading.g, shading.b, 0.5);
		cairo_rectangle (cr, 0.5, 0.5, width-2, height-1);
		cairo_stroke (cr);

		cairo_reset_clip (cr);
	}
}

static void
excelsior_draw_statusbar (cairo_t *cr,
                           const excelsiorColors          *colors,
                           const WidgetParameters          *widget,
                           int x, int y, int width, int height)
{
	const CairoColor *dark = &colors->shade[3];
	CairoColor hilight;

	ge_shade_color (dark, 1.4, &hilight);

	cairo_set_line_width  (cr, 1);
	cairo_translate       (cr, x, y+0.5);
	cairo_move_to         (cr, 0, 0);
	cairo_line_to         (cr, width, 0);
	ge_cairo_set_color    (cr, dark);
	cairo_stroke          (cr);

	cairo_translate       (cr, 0, 1);
	cairo_move_to         (cr, 0, 0);
	cairo_line_to         (cr, width, 0);
	ge_cairo_set_color    (cr, &hilight);
	cairo_stroke          (cr);
}

static void
excelsior_draw_menu_frame (cairo_t *cr,
                            const excelsiorColors          *colors,
                            const WidgetParameters          *widget,
                            int x, int y, int width, int height)
{
	const CairoColor *border = &colors->shade[5];
	cairo_translate      (cr, x, y);
	cairo_set_line_width (cr, 1);

	ge_cairo_rounded_rectangle (cr, x+0.75, y+0.75, width - 1, height - 1, widget->radius, widget->corners);

	excelsior_draw_mw_gradient(cr, colors, widget, 0, 0, width, height);

	ge_cairo_set_color (cr, border);
	ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1);
}

static void
excelsior_draw_tooltip (cairo_t *cr,
                         const excelsiorColors          *colors,
                         const WidgetParameters          *widget,
                         int x, int y, int width, int height)
{
	const CairoColor *stripe_fill = &colors->bg[GTK_STATE_SELECTED];
	CairoColor shadow, hilight, middle;
	cairo_pattern_t *pattern;

	if (widget->tooltip_style == 0)
	{

	ge_shade_color (stripe_fill, 1.30, &hilight);
	ge_shade_color (stripe_fill, 1.25, &middle);
	ge_shade_color (stripe_fill, 0.80, &shadow);

	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.00, hilight.r, hilight.g, hilight.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.45, middle.r, middle.g, middle.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.55, middle.r, middle.g, middle.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.74, shadow.r, shadow.g, shadow.b);
	ge_cairo_rounded_rectangle (cr, 0, 0, width, height, widget->radius, widget->corners);
	cairo_set_source (cr, pattern);
	cairo_pattern_destroy (pattern);

	}
	else
	{

	ge_shade_color (stripe_fill, 1.10, &middle);
	ge_shade_color (stripe_fill, 0.90, &shadow);
	ge_shade_color (stripe_fill, 1.35, &hilight);

	pattern = cairo_pattern_create_linear (0, 0, 0, height);
	cairo_pattern_add_color_stop_rgb (pattern, 0.25,        hilight.r, hilight.g, hilight.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.5,        middle.r, middle.g, middle.b);
	cairo_pattern_add_color_stop_rgb (pattern, 0.75,        shadow.r, shadow.g, shadow.b);
	cairo_set_source (cr, pattern);
	cairo_pattern_destroy (pattern);

	}

	if (widget->tooltip_style == 1)
	{

	cairo_move_to  (cr, 0, 0);
	cairo_line_to  (cr, width, 0);
	cairo_line_to  (cr, width, 0);
	cairo_curve_to (cr, width, 0, 0, 0, 0, height);
	cairo_close_path(cr);

	}
	else if (widget->tooltip_style == 2)
	{

	cairo_move_to (cr, 0, 0);
	cairo_line_to (cr, width, height/2);
	cairo_line_to (cr, 0, height);
	cairo_close_path(cr);

	}
	else if (widget->tooltip_style == 3)
	{

	cairo_move_to (cr, width, 0);
	cairo_line_to (cr, 0, height/2);
	cairo_line_to (cr, width, height);
	cairo_close_path(cr);

	}
	else if (widget->tooltip_style == 4)
	{

	cairo_move_to (cr, 0, 0);
	cairo_line_to (cr, width/2, height/2);
	cairo_line_to (cr, width, 0);
	cairo_close_path(cr);

	}
	else if (widget->tooltip_style == 5)
	{

	cairo_move_to (cr, 0, height);
	cairo_line_to (cr, width/2, height/2);
	cairo_line_to (cr, width, height);
	cairo_close_path(cr);

	}

	cairo_fill(cr);

	ge_cairo_set_color(cr, &colors->text[GTK_STATE_NORMAL]);
	cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1);
	cairo_stroke (cr);
}

static void
excelsior_draw_handle (cairo_t *cr,
                        const excelsiorColors          *colors,
                        const WidgetParameters          *params,
                        const HandleParameters          *handle,
                        int x, int y, int width, int height)
{
	const CairoColor *fill  = &colors->bg[params->state_type];
	int num_bars = 6; /* shut up gcc warnings */
	int bar_spacing;

	switch (handle->type)
	{
		case XCL_HANDLE_TOOLBAR:
			num_bars    = 6;
			bar_spacing = 3;
		break;
		case XCL_HANDLE_SPLITTER:
			num_bars    = 16;
			bar_spacing = 3;
		break;
	}

	if (params->prelight)
	{
		cairo_rectangle (cr, x, y, width, height);
		ge_cairo_set_color (cr, fill);
		cairo_fill (cr);
	}

	cairo_translate (cr, x+0.5, y+0.5);

	cairo_set_line_width (cr, 1);

	if (handle->horizontal)
	{
		params->style_functions->draw_gripdots (cr, colors, 0, 0, width, height, num_bars, 2, 0.1);
	}
	else
	{
		params->style_functions->draw_gripdots (cr, colors, 0, 0, width, height, 2, num_bars, 0.1);
	}
}

static void
excelsior_draw_resize_grip (cairo_t *cr,
                             const excelsiorColors          *colors,
                             const WidgetParameters          *widget,
                             const ResizeGripParameters      *grip,
                             int x, int y, int width, int height)
{
	const CairoColor *dark   = &colors->shade[4];
	CairoColor hilight;
	int lx, ly;
	int x_down;
	int y_down;
	int dots;

	ge_shade_color (dark, 0.75, &hilight);

	dots = MIN (width - 2, height - 2) / 2.4;

	cairo_save (cr);

	switch (grip->edge)
	{
		case XCL_WINDOW_EDGE_NORTH_EAST:
			x_down = 0;
			y_down = 0;
			cairo_translate (cr, x + width - 3*dots + 2, y + 1);
		break;
		case XCL_WINDOW_EDGE_SOUTH_EAST:
			x_down = 0;
			y_down = 1;
			cairo_translate (cr, x + width - 3*dots + 2, y + height - 3*dots + 2);
		break;
		case XCL_WINDOW_EDGE_SOUTH_WEST:
			x_down = 1;
			y_down = 1;
			cairo_translate (cr, x + 1, y + height - 3*dots + 2);
		break;
		case XCL_WINDOW_EDGE_NORTH_WEST:
			x_down = 1;
			y_down = 0;
			cairo_translate (cr, x + 1, y + 1);
		break;
		default:
			/* Not implemented. */
			return;
	}

	for (lx = 0; lx < dots; lx++) /* horizontally */
	{
		for (ly = 0; ly <= lx; ly++) /* vertically */
		{
			int mx, my;
			mx = x_down * dots + (1 - x_down * 2) * lx - x_down;
			my = y_down * dots + (1 - y_down * 2) * ly - y_down;

			ge_cairo_set_color (cr, &hilight);
			cairo_rectangle (cr, mx*3-3, my*3-3, 2, 2);
			cairo_fill (cr);

			ge_cairo_set_color (cr, &hilight);
			cairo_rectangle (cr, mx*3-3, my*3-3, 2, 2);
			cairo_fill (cr);
		}
	}

	cairo_restore (cr);
}

static void
excelsior_draw_radiobutton (cairo_t *cr,
                             const excelsiorColors  *colors,
                             const WidgetParameters  *widget,
                             const CheckboxParameters *checkbox,
                             int x, int y, int width, int height)
{
	const CairoColor *border;
	const CairoColor *dot;
	CairoColor shadow;
	CairoColor highlight;
	cairo_pattern_t *pt;
	gboolean inconsistent;
	gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN);

	inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN);
	draw_bullet |= inconsistent;

	if (widget->disabled)
	{
		border = &colors->shade[5];
		dot    = &colors->bg[GTK_STATE_INSENSITIVE];
	}
	else
	{
		border = &colors->shade[6];
		dot    = &colors->bg[GTK_STATE_SELECTED];
	}

	ge_shade_color (&widget->parentbg, 0.9, &shadow);
	ge_shade_color (&widget->parentbg, 1.1, &highlight);

	pt = cairo_pattern_create_linear (0, 0, 13, 13);
	cairo_pattern_add_color_stop_rgb (pt, 1.0, highlight.r, highlight.g, highlight.b);

	cairo_translate (cr, x, y);

	cairo_set_line_width (cr, 1);
	cairo_arc       (cr, 7, 7, 6, 0, G_PI*2);
	cairo_set_source (cr, pt);
	cairo_stroke (cr);
	cairo_pattern_destroy (pt);

	cairo_set_line_width (cr, 1);

	cairo_arc       (cr, 7, 7, 5.75, 0, G_PI*2);

	if (!widget->disabled)
	{
		ge_cairo_set_color (cr, &colors->base[0]);
		cairo_fill_preserve (cr);
	}

	ge_cairo_set_color (cr, border);
	cairo_stroke (cr);

	if (draw_bullet)
	{
		if (inconsistent)
		{
			cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
			cairo_set_line_width (cr, 4);

			cairo_move_to(cr, 5, 7);
			cairo_line_to(cr, 9, 7);

			ge_cairo_set_color (cr, dot);
			cairo_stroke (cr);
		}
		else
		{
			cairo_arc (cr, 7, 7, 3, 0, G_PI*2);
			ge_cairo_set_color (cr, dot);
			cairo_fill (cr);

			cairo_arc (cr, 6, 6, 1, 0, G_PI*2);
			cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5);
			cairo_fill (cr);
		}
	}
}

static void
excelsior_draw_checkbox (cairo_t *cr,
                          const excelsiorColors  *colors,
                          const WidgetParameters  *widget,
                          const CheckboxParameters *checkbox,
                          int x, int y, int width, int height)
{
	const CairoColor *border;
	const CairoColor *dot;
	gboolean inconsistent = FALSE;
	gboolean draw_bullet = (checkbox->shadow_type == GTK_SHADOW_IN);

	inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN);
	draw_bullet |= inconsistent;

	if (widget->disabled)
	{
		border = &colors->shade[5];
		dot    = &colors->bg[GTK_STATE_INSENSITIVE];
	}
	else
	{
		border = &colors->shade[6];
		dot    = &colors->bg[GTK_STATE_SELECTED];
	}

	cairo_translate (cr, x, y);

	if (widget->xthickness > 2 && widget->ythickness > 2)
	{
		widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5, width-1, height-1, 1, CR_CORNER_ALL);

		ge_cairo_rounded_rectangle (cr, 1.5, 1.5, width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
	}
	else
	{
		ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
	}

	if (!widget->disabled)
	{
		ge_cairo_set_color (cr, &colors->base[0]);
		cairo_fill_preserve (cr);
	}

	ge_cairo_set_color (cr, border);
	cairo_stroke (cr);

	if (draw_bullet)
	{
		if (inconsistent)
		{
			cairo_set_line_width (cr, 2.0);
			cairo_move_to (cr, 3, height*0.5);
			cairo_line_to (cr, width-3, height*0.5);

			ge_cairo_set_color (cr, dot);
			cairo_stroke (cr);

		}
		else
		{
			cairo_translate (cr, -4, 0);
			cairo_move_to (cr, 5, 10);
			cairo_rel_line_to (cr, 5, 2);
			cairo_rel_curve_to (cr, 1.4, -7.0, -0.6, -1.95, 5.0, -12.0);
			cairo_rel_curve_to (cr, -5, 5, -5, 5, -6.0, 9.3);
			cairo_rel_line_to (cr, -2.7, -2.0);

			ge_cairo_set_color (cr, dot);
			cairo_fill (cr);
		}
	}
}

static void
excelsior_draw_normal_arrow (cairo_t *cr, const CairoColor *color,
                              double x, double y, double width, double height)
{
	double arrow_width;
	double arrow_height;
	double line_width_2;

	cairo_save (cr);

	arrow_width = MIN (height * 2.0 + MAX (1.0, ceil (height * 2.0 / 6.0 * 2.0) / 2.0) / 2.0, width);
	line_width_2 = MAX (1.0, ceil (arrow_width / 6.0 * 2.0) / 2.0) / 2.0;
	arrow_height = arrow_width / 2.0 + line_width_2;

	cairo_translate (cr, x, y - arrow_height / 2.0);

	cairo_move_to (cr, -arrow_width / 2.0, line_width_2);
	cairo_line_to (cr, -arrow_width / 2.0 + line_width_2, 0);
	cairo_arc_negative (cr, 0, arrow_height - 4*line_width_2 - 2*line_width_2 * sqrt(2), 2*line_width_2, G_PI_2 + G_PI_4, G_PI_4);
	cairo_line_to (cr, arrow_width / 2.0 - line_width_2, 0);
	cairo_line_to (cr, arrow_width / 2.0, line_width_2);
	cairo_line_to (cr, 0, arrow_height);
	cairo_close_path (cr);

	ge_cairo_set_color (cr, color);
	cairo_fill (cr);

	cairo_restore (cr);
}

static void
excelsior_draw_combo_arrow (cairo_t *cr, const CairoColor *color,
                             double x, double y, double width, double height)
{
	double arrow_width = MIN (height * 2 / 3.0, width);
	double arrow_height = arrow_width / 2.0;
	double gap_size = 1.5 * arrow_height;

	cairo_save (cr);
	cairo_translate (cr, x, y - (arrow_height + gap_size) / 2.0);
	excelsior_draw_normal_arrow (cr, color, 0, 0, arrow_width, arrow_height);
	cairo_restore (cr);
	excelsior_draw_normal_arrow (cr, color, x, y + (arrow_height + gap_size) / 2.0, arrow_width, arrow_height);
}

static void
_excelsior_draw_arrow (cairo_t *cr, const CairoColor *color,
                        excelsiorDirection dir, excelsiorArrowType type,
                        double x, double y, double width, double height)
{
	double rotate;

	if (dir == XCL_DIRECTION_LEFT)
		rotate = G_PI*1.5;
	else if (dir == XCL_DIRECTION_RIGHT)
		rotate = G_PI*0.5;
	else if (dir == XCL_DIRECTION_UP)
		rotate = G_PI;
	else if (dir == XCL_DIRECTION_DOWN)
		rotate = 0;
	else
		return;

	if (type == XCL_ARROW_NORMAL)
	{
		cairo_translate (cr, x, y);
		cairo_rotate (cr, -rotate);
		excelsior_draw_normal_arrow (cr, color, 0, 0, width, height);
	}
	else if (type == XCL_ARROW_COMBO)
	{
		cairo_translate (cr, x, y);
		excelsior_draw_combo_arrow (cr, color, 0, 0, width, height);
	}
}

static void
excelsior_draw_arrow (cairo_t *cr,
                       const excelsiorColors *colors,
                       const WidgetParameters *widget,
                       const ArrowParameters  *arrow,
                       int x, int y, int width, int height)
{
	const CairoColor *color = &colors->fg[widget->state_type];

	gdouble tx, ty;

	tx = x + width/2.0;
	ty = y + height/2.0;

	if (widget->disabled)
	{
		_excelsior_draw_arrow (cr, &colors->shade[0],
		                        arrow->direction, arrow->type,
		                        tx+0.5, ty+0.5, width * widget->arrow_size, height * widget->arrow_size);
	}

	cairo_identity_matrix (cr);

	_excelsior_draw_arrow (cr, color, arrow->direction, arrow->type,
	                        tx, ty, width * widget->arrow_size, height * widget->arrow_size);

}

void
excelsior_draw_focus (cairo_t *cr,
                       const excelsiorColors *colors,
                       const WidgetParameters *widget,
                       const FocusParameters  *focus,
                       int x, int y, int width, int height)
{
	if (focus->has_color)
		ge_cairo_set_color (cr, &focus->color);
	else if (focus->type == XCL_FOCUS_COLOR_WHEEL_LIGHT)
		cairo_set_source_rgb (cr, 0., 0., 0.);
	else if (focus->type == XCL_FOCUS_COLOR_WHEEL_DARK)
		cairo_set_source_rgb (cr, 1., 1., 1.);
	else
		cairo_set_source_rgba (cr,
		                       colors->fg[widget->state_type].r,
		                       colors->fg[widget->state_type].g,
		                       colors->fg[widget->state_type].b,
		                       0.7);

	cairo_set_line_width (cr, focus->focus_line_width);

	if (focus->dash_list[0])
	{
		gint n_dashes = strlen ((gchar *)focus->dash_list);
		gdouble *dashes = g_new (gdouble, n_dashes);
		gdouble total_length = 0;
		gdouble dash_offset;
		gint i;

		for (i = 0; i < n_dashes; i++)
		{
			dashes[i] = focus->dash_list[i];
			total_length += focus->dash_list[i];
		}

		dash_offset = -focus->focus_line_width / 2.0;
		while (dash_offset < 0)
			dash_offset += total_length;

		cairo_set_dash (cr, dashes, n_dashes, dash_offset);
		g_free (dashes);
	}

	cairo_rectangle (cr,
	                 x + focus->focus_line_width / 2.0,
	                 y + focus->focus_line_width / 2.0,
	                 width - focus->focus_line_width, height - focus->focus_line_width);
	cairo_stroke (cr);
}

void
excelsior_register_style_classic (excelsiorStyleFunctions *functions)
{
	g_assert (functions);

	functions->draw_button             = excelsior_draw_button;
	functions->draw_scale_trough       = excelsior_draw_scale_trough;
	functions->draw_progressbar_trough = excelsior_draw_progressbar_trough;
	functions->draw_progressbar_fill   = excelsior_draw_progressbar_fill;
	functions->draw_slider_button      = excelsior_draw_slider_button;
	functions->draw_entry              = excelsior_draw_entry;
	functions->draw_mw_gradient        = excelsior_draw_mw_gradient;
	functions->draw_spinbutton         = excelsior_draw_spinbutton;
	functions->draw_spinbutton_down    = excelsior_draw_spinbutton_down;
	functions->draw_optionmenu         = excelsior_draw_optionmenu;
	functions->draw_inset              = excelsior_draw_inset;
	functions->draw_menubar            = excelsior_draw_menubar;
	functions->draw_tab                = excelsior_draw_tab;
	functions->draw_frame              = excelsior_draw_frame;
	functions->draw_separator          = excelsior_draw_separator;
	functions->draw_menu_item_separator = excelsior_draw_menu_item_separator;
	functions->draw_list_view_header   = excelsior_draw_list_view_header;
	functions->draw_toolbar            = excelsior_draw_toolbar;
	functions->draw_menuitem           = excelsior_draw_menuitem;
	functions->draw_menubaritem        = excelsior_draw_menubaritem;
	functions->draw_selected_cell      = excelsior_draw_selected_cell;
	functions->draw_scrollbar_stepper  = excelsior_draw_scrollbar_stepper;
	functions->draw_scrollbar_slider   = excelsior_draw_scrollbar_slider;
	functions->draw_scrollbar_trough   = excelsior_draw_scrollbar_trough;
	functions->draw_statusbar          = excelsior_draw_statusbar;
	functions->draw_menu_frame         = excelsior_draw_menu_frame;
	functions->draw_tooltip            = excelsior_draw_tooltip;
	functions->draw_handle             = excelsior_draw_handle;
	functions->draw_resize_grip        = excelsior_draw_resize_grip;
	functions->draw_arrow              = excelsior_draw_arrow;
	functions->draw_focus              = excelsior_draw_focus;
	functions->draw_checkbox           = excelsior_draw_checkbox;
	functions->draw_radiobutton        = excelsior_draw_radiobutton;
	functions->draw_shadow             = excelsior_draw_shadow;
	functions->draw_slider             = excelsior_draw_slider;
	functions->draw_gripdots           = excelsior_draw_gripdots;
}
