diff options
Diffstat (limited to 'gtk/gtkstyle.c')
-rw-r--r-- | gtk/gtkstyle.c | 1795 |
1 files changed, 1795 insertions, 0 deletions
diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c new file mode 100644 index 000000000..ae8c1a5d9 --- /dev/null +++ b/gtk/gtkstyle.c @@ -0,0 +1,1795 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <math.h> +#include "gtkgc.h" +#include "gtkstyle.h" + + +#define LIGHTNESS_MULT 1.3 +#define DARKNESS_MULT 0.7 + + +typedef struct _GtkStyleKey GtkStyleKey; + +struct _GtkStyleKey +{ + GdkColor fg[5]; + GdkColor bg[5]; + GdkColor text[5]; + GdkColor base[5]; + + GdkPixmap *bg_pixmap[5]; + + GdkFont *font; + + gint depth; + GdkColormap *colormap; + GtkStyleClass *klass; +}; + + +static void gtk_style_init (GtkStyle *style); +static void gtk_styles_init (void); +static void gtk_style_remove (GtkStyle *style); +static GtkStyle* gtk_style_find (GtkStyle *style, + GdkColormap *cmap, + gint depth); +static GtkStyle* gtk_style_new_from_key (GtkStyleKey *key); +static GtkStyleKey* gtk_style_key_dup (GtkStyleKey *key); +static void gtk_style_destroy (GtkStyle *style); +static void gtk_style_key_destroy (GtkStyleKey *key); +static guint gtk_style_key_hash (GtkStyleKey *key); +static guint gtk_style_value_hash (GtkStyle *style); +static gint gtk_style_key_compare (GtkStyleKey *a, + GtkStyleKey *b); + +static void gtk_default_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x1, + gint x2, + gint y); +static void gtk_default_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint y1, + gint y2, + gint x); +static void gtk_default_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkPoint *points, + gint npoints, + gint fill); +static void gtk_default_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GtkArrowType arrow_type, + gint fill, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x, + gint y, + const gchar *string); + +static void gtk_style_shade (GdkColor *a, GdkColor *b, gdouble k); +static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b); +static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s); + + +static GtkStyleClass default_class = +{ + 2, + 2, + gtk_default_draw_hline, + gtk_default_draw_vline, + gtk_default_draw_shadow, + gtk_default_draw_polygon, + gtk_default_draw_arrow, + gtk_default_draw_diamond, + gtk_default_draw_oval, + gtk_default_draw_string, +}; + +static GdkColor gtk_default_normal_fg = { 0, 0, 0, 0 }; +static GdkColor gtk_default_active_fg = { 0, 0, 0, 0 }; +static GdkColor gtk_default_prelight_fg = { 0, 0, 0, 0 }; +static GdkColor gtk_default_selected_fg = { 0, 0xffff, 0xffff, 0xffff }; +static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 }; + +static GdkColor gtk_default_normal_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 }; +static GdkColor gtk_default_active_bg = { 0, 0xc350, 0xc350, 0xc350 }; +static GdkColor gtk_default_prelight_bg = { 0, 0xea60, 0xea60, 0xea60 }; +static GdkColor gtk_default_selected_bg = { 0, 0, 0, 0x9c40 }; +static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 }; + +static GdkFont *default_font = NULL; + +static gint initialize = TRUE; +static GCache *style_cache = NULL; +static GSList *unattached_styles = NULL; + +static GMemChunk *key_mem_chunk = NULL; + + +GtkStyle* +gtk_style_new () +{ + GtkStyle *style; + gint i; + + style = g_new (GtkStyle, 1); + + if (!default_font) + default_font = gdk_font_load ("-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*"); + + style->font = default_font; + gdk_font_ref (style->font); + + style->ref_count = 0; + style->attach_count = 0; + style->colormap = NULL; + style->depth = -1; + style->klass = &default_class; + + style->black.red = 0; + style->black.green = 0; + style->black.blue = 0; + + style->white.red = 65535; + style->white.green = 65535; + style->white.blue = 65535; + + style->black_gc = NULL; + style->white_gc = NULL; + + style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg; + style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg; + style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg; + style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg; + style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg; + + style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg; + style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg; + style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg; + style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg; + style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg; + + for (i = 0; i < 5; i++) + { + style->text[i] = style->fg[i]; + style->base[i] = style->white; + } + + for (i = 0; i < 5; i++) + style->bg_pixmap[i] = NULL; + + for (i = 0; i < 5; i++) + { + style->fg_gc[i] = NULL; + style->bg_gc[i] = NULL; + style->light_gc[i] = NULL; + style->dark_gc[i] = NULL; + style->mid_gc[i] = NULL; + style->text_gc[i] = NULL; + style->base_gc[i] = NULL; + } + + unattached_styles = g_slist_prepend (unattached_styles, style); + + return style; +} + +GtkStyle* +gtk_style_attach (GtkStyle *style, + GdkWindow *window) +{ + GtkStyle *new_style; + GdkColormap *colormap; + gint depth; + + g_return_val_if_fail (style != NULL, NULL); + g_return_val_if_fail (window != NULL, NULL); + + colormap = gdk_window_get_colormap (window); + gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth); + + new_style = gtk_style_find (style, colormap, depth); + + if (new_style && (new_style != style)) + { + gtk_style_unref (style); + style = new_style; + gtk_style_ref (style); + } + + if (style->attach_count == 0) + unattached_styles = g_slist_remove (unattached_styles, style); + + style->attach_count += 1; + + return style; +} + +void +gtk_style_detach (GtkStyle *style) +{ + gint i; + + g_return_if_fail (style != NULL); + + style->attach_count -= 1; + if (style->attach_count == 0) + { + unattached_styles = g_slist_prepend (unattached_styles, style); + + gtk_gc_release (style->black_gc); + gtk_gc_release (style->white_gc); + + style->black_gc = NULL; + style->white_gc = NULL; + + for (i = 0; i < 5; i++) + { + gtk_gc_release (style->fg_gc[i]); + gtk_gc_release (style->bg_gc[i]); + gtk_gc_release (style->light_gc[i]); + gtk_gc_release (style->dark_gc[i]); + gtk_gc_release (style->mid_gc[i]); + gtk_gc_release (style->text_gc[i]); + gtk_gc_release (style->base_gc[i]); + + style->fg_gc[i] = NULL; + style->bg_gc[i] = NULL; + style->light_gc[i] = NULL; + style->dark_gc[i] = NULL; + style->mid_gc[i] = NULL; + style->text_gc[i] = NULL; + style->base_gc[i] = NULL; + } + + style->depth = -1; + style->colormap = NULL; + } + + gtk_style_remove (style); +} + +GtkStyle* +gtk_style_ref (GtkStyle *style) +{ + g_return_val_if_fail (style != NULL, NULL); + + style->ref_count += 1; + return style; +} + +void +gtk_style_unref (GtkStyle *style) +{ + g_return_if_fail (style != NULL); + + style->ref_count -= 1; + if (style->ref_count == 0) + gtk_style_destroy (style); +} + +void +gtk_style_set_background (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type) +{ + GdkPixmap *pixmap; + gint parent_relative; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (style->bg_pixmap[state_type]) + { + if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE) + { + pixmap = NULL; + parent_relative = TRUE; + } + else + { + pixmap = style->bg_pixmap[state_type]; + parent_relative = FALSE; + } + + gdk_window_set_back_pixmap (window, pixmap, parent_relative); + } + else + gdk_window_set_background (window, &style->bg[state_type]); +} + + +void +gtk_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x1, + gint x2, + gint y) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_hline != NULL); + + (*style->klass->draw_hline) (style, window, state_type, x1, x2, y); +} + + +void +gtk_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint y1, + gint y2, + gint x) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_vline != NULL); + + (*style->klass->draw_vline) (style, window, state_type, y1, y2, x); +} + + +void +gtk_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_shadow != NULL); + + (*style->klass->draw_shadow) (style, window, state_type, shadow_type, x, y, width, height); +} + +void +gtk_draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkPoint *points, + gint npoints, + gint fill) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_shadow != NULL); + + (*style->klass->draw_polygon) (style, window, state_type, shadow_type, points, npoints, fill); +} + +void +gtk_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GtkArrowType arrow_type, + gint fill, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_arrow != NULL); + + (*style->klass->draw_arrow) (style, window, state_type, shadow_type, arrow_type, fill, x, y, width, height); +} + + +void +gtk_draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_diamond != NULL); + + (*style->klass->draw_diamond) (style, window, state_type, shadow_type, x, y, width, height); +} + + +void +gtk_draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_oval != NULL); + + (*style->klass->draw_oval) (style, window, state_type, shadow_type, x, y, width, height); +} + +void +gtk_draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x, + gint y, + const gchar *string) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (style->klass != NULL); + g_return_if_fail (style->klass->draw_oval != NULL); + + (*style->klass->draw_string) (style, window, state_type, x, y, string); +} + + +static void +gtk_style_init (GtkStyle *style) +{ + GdkGCValues gc_values; + GdkGCValuesMask gc_values_mask; + GdkColormap *colormap; + gint i; + + g_return_if_fail (style != NULL); + + if (style->attach_count == 0) + { + for (i = 0; i < 5; i++) + { + gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT); + gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT); + + style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2; + style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2; + style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2; + } + + colormap = style->colormap; + + gdk_color_black (colormap, &style->black); + gdk_color_white (colormap, &style->white); + + gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_FONT; + if (style->font->type == GDK_FONT_FONT) + { + gc_values.font = style->font; + } + else if (style->font->type == GDK_FONT_FONTSET) + { + gc_values.font = default_font; + } + + gc_values.foreground = style->black; + style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->white; + style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + for (i = 0; i < 5; i++) + { + if (!gdk_color_alloc (colormap, &style->fg[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->fg[i].red, style->fg[i].green, style->fg[i].blue); + if (!gdk_color_alloc (colormap, &style->bg[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->bg[i].red, style->bg[i].green, style->bg[i].blue); + if (!gdk_color_alloc (colormap, &style->light[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->light[i].red, style->light[i].green, style->light[i].blue); + if (!gdk_color_alloc (colormap, &style->dark[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->dark[i].red, style->dark[i].green, style->dark[i].blue); + if (!gdk_color_alloc (colormap, &style->mid[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->mid[i].red, style->mid[i].green, style->mid[i].blue); + if (!gdk_color_alloc (colormap, &style->text[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->text[i].red, style->text[i].green, style->text[i].blue); + if (!gdk_color_alloc (colormap, &style->base[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->base[i].red, style->base[i].green, style->base[i].blue); + + gc_values.foreground = style->fg[i]; + style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->bg[i]; + style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->light[i]; + style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->dark[i]; + style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->mid[i]; + style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->text[i]; + style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->base[i]; + style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + } + } +} + +static void +gtk_styles_init () +{ + if (initialize) + { + initialize = FALSE; + + style_cache = g_cache_new ((GCacheNewFunc) gtk_style_new_from_key, + (GCacheDestroyFunc) gtk_style_destroy, + (GCacheDupFunc) gtk_style_key_dup, + (GCacheDestroyFunc) gtk_style_key_destroy, + (GHashFunc) gtk_style_key_hash, + (GHashFunc) gtk_style_value_hash, + (GCompareFunc) gtk_style_key_compare); + } +} + +static void +gtk_style_remove (GtkStyle *style) +{ + if (initialize) + gtk_styles_init (); + + g_cache_remove (style_cache, style); +} + +static GtkStyle* +gtk_style_find (GtkStyle *style, + GdkColormap *cmap, + gint depth) +{ + GtkStyleKey key; + gint i; + + if (initialize) + gtk_styles_init (); + + for (i = 0; i < 5; i++) + { + key.fg[i] = style->fg[i]; + key.bg[i] = style->bg[i]; + key.text[i] = style->text[i]; + key.base[i] = style->base[i]; + key.bg_pixmap[i] = style->bg_pixmap[i]; + } + + key.font = style->font; + key.klass = style->klass; + key.depth = depth; + key.colormap = cmap; + + style = g_cache_insert (style_cache, &key); + + return style; +} + +static GtkStyle* +gtk_style_new_from_key (GtkStyleKey *key) +{ + GtkStyle *style; + GSList *list; + gint i; + + style = NULL; + list = unattached_styles; + + while (list) + { + style = list->data; + list = list->next; + + if ((style->depth != -1) && (style->depth != key->depth)) + { + style = NULL; + continue; + } + if (style->colormap && (style->colormap != key->colormap)) + { + style = NULL; + continue; + } + if (style->klass != key->klass) + { + style = NULL; + continue; + } + if (!gdk_font_equal (style->font, key->font)) + { + style = NULL; + continue; + } + + for (i = 0; style && (i < 5); i++) + { + if (style->bg_pixmap[i] != key->bg_pixmap[i]) + { + style = NULL; + continue; + } + + if ((style->fg[i].red != key->fg[i].red) || + (style->fg[i].green != key->fg[i].green) || + (style->fg[i].blue != key->fg[i].blue)) + { + style = NULL; + continue; + } + + if ((style->bg[i].red != key->bg[i].red) || + (style->bg[i].green != key->bg[i].green) || + (style->bg[i].blue != key->bg[i].blue)) + { + style = NULL; + continue; + } + + if ((style->text[i].red != key->text[i].red) || + (style->text[i].green != key->text[i].green) || + (style->text[i].blue != key->text[i].blue)) + { + style = NULL; + continue; + } + + if ((style->base[i].red != key->base[i].red) || + (style->base[i].green != key->base[i].green) || + (style->base[i].blue != key->base[i].blue)) + { + style = NULL; + continue; + } + } + + if (style) + break; + } + + if (!style) + { + style = g_new (GtkStyle, 1); + + style->ref_count = 0; + style->attach_count = 0; + + style->font = key->font; + gdk_font_ref (style->font); + + style->depth = key->depth; + style->colormap = key->colormap; + style->klass = key->klass; + + style->black.red = 0; + style->black.green = 0; + style->black.blue = 0; + + style->white.red = 65535; + style->white.green = 65535; + style->white.blue = 65535; + + style->black_gc = NULL; + style->white_gc = NULL; + + for (i = 0; i < 5; i++) + { + style->fg[i] = key->fg[i]; + style->bg[i] = key->bg[i]; + style->text[i] = key->text[i]; + style->base[i] = key->base[i]; + } + + for (i = 0; i < 5; i++) + style->bg_pixmap[i] = key->bg_pixmap[i]; + + for (i = 0; i < 5; i++) + { + style->fg_gc[i] = NULL; + style->bg_gc[i] = NULL; + style->light_gc[i] = NULL; + style->dark_gc[i] = NULL; + style->mid_gc[i] = NULL; + style->text_gc[i] = NULL; + style->base_gc[i] = NULL; + } + } + + if (style->depth == -1) + style->depth = key->depth; + if (!style->colormap) + style->colormap = key->colormap; + + gtk_style_init (style); + + return style; +} + +static GtkStyleKey* +gtk_style_key_dup (GtkStyleKey *key) +{ + GtkStyleKey *new_key; + + if (!key_mem_chunk) + key_mem_chunk = g_mem_chunk_new ("key mem chunk", sizeof (GtkStyleKey), + 1024, G_ALLOC_AND_FREE); + + new_key = g_chunk_new (GtkStyleKey, key_mem_chunk); + + *new_key = *key; + + return new_key; +} + +static void +gtk_style_destroy (GtkStyle *style) +{ + gint i; + + if (style->ref_count != 0) + return; + + if (style->attach_count > 0) + { + gtk_gc_release (style->black_gc); + gtk_gc_release (style->white_gc); + + for (i = 0; i < 5; i++) + { + gtk_gc_release (style->fg_gc[i]); + gtk_gc_release (style->bg_gc[i]); + gtk_gc_release (style->light_gc[i]); + gtk_gc_release (style->dark_gc[i]); + gtk_gc_release (style->mid_gc[i]); + gtk_gc_release (style->text_gc[i]); + gtk_gc_release (style->base_gc[i]); + } + } + + unattached_styles = g_slist_remove (unattached_styles, style); + + if (style->font->type == GDK_FONT_FONT) + gdk_font_free (style->font); + else if (style->font->type == GDK_FONT_FONTSET) + gdk_fontset_free (style->font); + else + g_error("undefined font type\n"); + + g_free (style); +} + +static void +gtk_style_key_destroy (GtkStyleKey *key) +{ + g_mem_chunk_free (key_mem_chunk, key); +} + +static guint +gtk_style_key_hash (GtkStyleKey *key) +{ + guint hash_val; + gint i; + + hash_val = 0; + + for (i = 0; i < 5; i++) + { + hash_val += key->fg[i].red + key->fg[i].green + key->fg[i].blue; + hash_val += key->bg[i].red + key->bg[i].green + key->bg[i].blue; + hash_val += key->text[i].red + key->text[i].green + key->text[i].blue; + hash_val += key->base[i].red + key->base[i].green + key->base[i].blue; + } + + hash_val += (guint) gdk_font_id (key->font); + hash_val += (guint) key->depth; + hash_val += (gulong) key->colormap; + hash_val += (gulong) key->klass; + + return hash_val; +} + +static guint +gtk_style_value_hash (GtkStyle *style) +{ + guint hash_val; + gint i; + + hash_val = 0; + + for (i = 0; i < 5; i++) + { + hash_val += style->fg[i].red + style->fg[i].green + style->fg[i].blue; + hash_val += style->bg[i].red + style->bg[i].green + style->bg[i].blue; + hash_val += style->text[i].red + style->text[i].green + style->text[i].blue; + hash_val += style->base[i].red + style->base[i].green + style->base[i].blue; + } + + hash_val += (guint) gdk_font_id (style->font); + hash_val += (gulong) style->klass; + + return hash_val; +} + +static gint +gtk_style_key_compare (GtkStyleKey *a, + GtkStyleKey *b) +{ + gint i; + + if (a->depth != b->depth) + return FALSE; + if (a->colormap != b->colormap) + return FALSE; + if (a->klass != b->klass) + return FALSE; + if (!gdk_font_equal (a->font, b->font)) + return FALSE; + + for (i = 0; i < 5; i++) + { + if (a->bg_pixmap[i] != b->bg_pixmap[i]) + return FALSE; + + if ((a->fg[i].red != b->fg[i].red) || + (a->fg[i].green != b->fg[i].green) || + (a->fg[i].blue != b->fg[i].blue)) + return FALSE; + if ((a->bg[i].red != b->bg[i].red) || + (a->bg[i].green != b->bg[i].green) || + (a->bg[i].blue != b->bg[i].blue)) + return FALSE; + if ((a->text[i].red != b->text[i].red) || + (a->text[i].green != b->text[i].green) || + (a->text[i].blue != b->text[i].blue)) + return FALSE; + if ((a->base[i].red != b->base[i].red) || + (a->base[i].green != b->base[i].green) || + (a->base[i].blue != b->base[i].blue)) + return FALSE; + } + + return TRUE; +} + + +static void +gtk_default_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x1, + gint x2, + gint y) +{ + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + thickness_light = style->klass->ythickness / 2; + thickness_dark = style->klass->ythickness - thickness_light; + + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i); + gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i); + } + + y += thickness_dark; + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i); + gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i); + } +} + + +static void +gtk_default_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint y1, + gint y2, + gint x) +{ + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + thickness_light = style->klass->xthickness / 2; + thickness_dark = style->klass->xthickness - thickness_light; + + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2); + gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1); + } + + x += thickness_dark; + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i); + gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2); + } +} + + +static void +gtk_default_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + GdkGC *gc1; + GdkGC *gc2; + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + gc1 = NULL; + gc2 = NULL; + break; + case GTK_SHADOW_IN: + case GTK_SHADOW_ETCHED_IN: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + break; + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + break; + } + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + break; + + case GTK_SHADOW_IN: + gdk_draw_line (window, gc1, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, gc1, + x + width - 1, y, x + width - 1, y + height - 1); + + gdk_draw_line (window, style->bg_gc[state_type], + x + 1, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, style->bg_gc[state_type], + x + width - 2, y + 1, x + width - 2, y + height - 2); + + gdk_draw_line (window, style->black_gc, + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, style->black_gc, + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, gc2, + x, y, x + width - 1, y); + gdk_draw_line (window, gc2, + x, y, x, y + height - 1); + break; + + case GTK_SHADOW_OUT: + gdk_draw_line (window, gc1, + x + 1, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc1, + x + width - 2, y + 1, x + width - 2, y + height - 2); + + gdk_draw_line (window, gc2, + x, y, x + width - 1, y); + gdk_draw_line (window, gc2, + x, y, x, y + height - 1); + + gdk_draw_line (window, style->bg_gc[state_type], + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, style->bg_gc[state_type], + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, style->black_gc, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, style->black_gc, + x + width - 1, y, x + width - 1, y + height - 1); + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + thickness_light = 1; + thickness_dark = 1; + + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, gc1, + x + i, + y + height - i - 1, + x + width - i - 1, + y + height - i - 1); + gdk_draw_line (window, gc1, + x + width - i - 1, + y + i, + x + width - i - 1, + y + height - i - 1); + + gdk_draw_line (window, gc2, + x + i, + y + i, + x + width - i - 2, + y + i); + gdk_draw_line (window, gc2, + x + i, + y + i, + x + i, + y + height - i - 2); + } + + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, gc1, + x + thickness_dark + i, + y + thickness_dark + i, + x + width - thickness_dark - i - 1, + y + thickness_dark + i); + gdk_draw_line (window, gc1, + x + thickness_dark + i, + y + thickness_dark + i, + x + thickness_dark + i, + y + height - thickness_dark - i - 1); + + gdk_draw_line (window, gc2, + x + thickness_dark + i, + y + height - thickness_light - i - 1, + x + width - thickness_light - 1, + y + height - thickness_light - i - 1); + gdk_draw_line (window, gc2, + x + width - thickness_light - i - 1, + y + thickness_dark + i, + x + width - thickness_light - i - 1, + y + height - thickness_light - 1); + } + break; + } +} + + +static void +gtk_default_draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkPoint *points, + gint npoints, + gint fill) +{ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif /* M_PI */ +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 +#endif /* M_PI_4 */ + + static const gdouble pi_over_4 = M_PI_4; + static const gdouble pi_3_over_4 = M_PI_4 * 3; + + GdkGC *gc1; + GdkGC *gc2; + GdkGC *gc3; + GdkGC *gc4; + gdouble angle; + gint xadjust; + gint yadjust; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + g_return_if_fail (points != NULL); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + gc1 = style->bg_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->black_gc; + gc4 = style->bg_gc[state_type]; + break; + default: + return; + } + + if (fill) + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints); + + npoints -= 1; + for (i = 0; i < npoints; i++) + { + if ((points[i].x == points[i+1].x) && + (points[i].y == points[i+1].y)) + { + angle = 0; + } + else + { + angle = atan2 (points[i+1].y - points[i].y, + points[i+1].x - points[i].x); + } + + if ((angle > -pi_3_over_4) && (angle < pi_over_4)) + { + while (angle < 0) + angle += M_PI; + while (angle > M_PI) + angle -= M_PI; + + if ((angle > pi_3_over_4) || (angle < pi_over_4)) + { + xadjust = 0; + yadjust = 1; + } + else + { + xadjust = 1; + yadjust = 0; + } + + gdk_draw_line (window, gc1, + points[i].x-xadjust, points[i].y-yadjust, + points[i+1].x-xadjust, points[i+1].y-yadjust); + gdk_draw_line (window, gc3, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + } + } + + for (i = 0; i < npoints; i++) + { + if ((points[i].x == points[i+1].x) && + (points[i].y == points[i+1].y)) + { + angle = 0; + } + else + { + angle = atan2 (points[i+1].y - points[i].y, + points[i+1].x - points[i].x); + } + + if ((angle <= -pi_3_over_4) || (angle >= pi_over_4)) + { + while (angle < 0) + angle += M_PI; + while (angle > M_PI) + angle -= M_PI; + + if ((angle > pi_3_over_4) || (angle < pi_over_4)) + { + xadjust = 0; + yadjust = 1; + } + else + { + xadjust = 1; + yadjust = 0; + } + + gdk_draw_line (window, gc4, + points[i].x+xadjust, points[i].y+yadjust, + points[i+1].x+xadjust, points[i+1].y+yadjust); + gdk_draw_line (window, gc2, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + } + } +} + + +static void +gtk_default_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GtkArrowType arrow_type, + gint fill, + gint x, + gint y, + gint width, + gint height) +{ + GdkGC *gc1; + GdkGC *gc2; + GdkGC *gc3; + GdkGC *gc4; + gint half_width; + gint half_height; + GdkPoint points[3]; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + gc1 = style->bg_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->black_gc; + gc4 = style->bg_gc[state_type]; + break; + default: + return; + } + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + half_width = width / 2; + half_height = height / 2; + + switch (arrow_type) + { + case GTK_ARROW_UP: + if (fill) + { + points[0].x = x + half_width; + points[0].y = y; + points[1].x = x; + points[1].y = y + height - 1; + points[2].x = x + width - 1; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + gdk_draw_line (window, gc1, + x + 1, y + height - 2, + x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + 0, y + height - 1, + x + width - 1, y + height - 1); + + gdk_draw_line (window, gc1, + x + width - 2, y + height - 1, + x + half_width, y + 1); + gdk_draw_line (window, gc3, + x + width - 1, y + height - 1, + x + half_width, y); + + gdk_draw_line (window, gc4, + x + half_width, y + 1, + x + 1, y + height - 1); + gdk_draw_line (window, gc2, + x + half_width, y, + x, y + height - 1); + break; + case GTK_ARROW_DOWN: + if (fill) + { + points[0].x = x + width - 1; + points[0].y = y; + points[1].x = x; + points[1].y = y; + points[2].x = x + half_width; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + gdk_draw_line (window, gc4, + x + width - 2, + y + 1, x + 1, y + 1); + gdk_draw_line (window, gc2, + x + width - 1, y, + x, y); + + gdk_draw_line (window, gc4, + x + 1, y, + x + half_width, y + height - 2); + gdk_draw_line (window, gc2, + x, y, + x + half_width, y + height - 1); + + gdk_draw_line (window, gc1, + x + half_width, y + height - 2, + x + width - 2, y); + gdk_draw_line (window, gc3, + x + half_width, y + height - 1, + x + width - 1, y); + break; + case GTK_ARROW_LEFT: + if (fill) + { + points[0].x = x; + points[0].y = y + half_height; + points[1].x = x + width - 1; + points[1].y = y + height - 1; + points[2].x = x + width - 1; + points[2].y = y; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + gdk_draw_line (window, gc1, + x + 1, y + half_height, + x + width - 1, y + height - 1); + gdk_draw_line (window, gc3, + x, y + half_height, + x + width - 1, y + height - 1); + + gdk_draw_line (window, gc1, + x + width - 2, y + height - 1, + x + width - 2, y + 1); + gdk_draw_line (window, gc3, + x + width - 1, y + height - 1, + x + width - 1, y); + + gdk_draw_line (window, gc4, + x + width - 1, y + 1, + x + 1, y + half_width); + gdk_draw_line (window, gc2, + x + width - 1, y, + x, y + half_width); + break; + case GTK_ARROW_RIGHT: + if (fill) + { + points[0].x = x + width - 1; + points[0].y = y + half_height; + points[1].x = x; + points[1].y = y; + points[2].x = x; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + gdk_draw_line (window, gc4, + x + width - 1, y + half_height, + x + 1, y + 1); + gdk_draw_line (window, gc2, + x + width - 1, y + half_height, + x, y); + + gdk_draw_line (window, gc4, + x + 1, y + 1, + x + 1, y + height - 2); + gdk_draw_line (window, gc2, + x, y, + x, y + height - 1); + + gdk_draw_line (window, gc1, + x + 1, y + height - 2, + x + width - 1, y + half_height); + gdk_draw_line (window, gc3, + x, y + height - 1, + x + width - 1, y + half_height); + break; + } +} + + +static void +gtk_default_draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + gint half_width; + gint half_height; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + half_width = width / 2; + half_height = height / 2; + + switch (shadow_type) + { + case GTK_SHADOW_IN: + gdk_draw_line (window, style->bg_gc[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + gdk_draw_line (window, style->bg_gc[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x, y + half_height, + x + half_width, y + height); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height, + x + width, y + half_height); + + gdk_draw_line (window, style->black_gc, + x + 2, y + half_height, + x + half_width, y + 2); + gdk_draw_line (window, style->black_gc, + x + half_width, y + 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x + 1, y + half_height, + x + half_width, y + 1); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x, y + half_height, + x + half_width, y); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y, + x + width, y + half_height); + break; + case GTK_SHADOW_OUT: + gdk_draw_line (window, style->dark_gc[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->black_gc, + x, y + half_height, + x + half_width, y + height); + gdk_draw_line (window, style->black_gc, + x + half_width, y + height, + x + width, y + half_height); + + gdk_draw_line (window, style->bg_gc[state_type], + x + 2, y + half_height, + x + half_width, y + 2); + gdk_draw_line (window, style->bg_gc[state_type], + x + half_width, y + 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x + 1, y + half_height, + x + half_width, y + 1); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x, y + half_height, + x + half_width, y); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y, + x + width, y + half_height); + break; + default: + break; + } +} + + +static void +gtk_default_draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); +} + +static void +gtk_default_draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x, + gint y, + const gchar *string) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (state_type == GTK_STATE_INSENSITIVE) + gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, string); + gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, string); +} + + +static void +gtk_style_shade (GdkColor *a, + GdkColor *b, + gdouble k) +{ + gdouble red; + gdouble green; + gdouble blue; + + red = (gdouble) a->red / 65535.0; + green = (gdouble) a->green / 65535.0; + blue = (gdouble) a->blue / 65535.0; + + rgb_to_hls (&red, &green, &blue); + + green *= k; + if (green > 1.0) + green = 1.0; + else if (green < 0.0) + green = 0.0; + + blue *= k; + if (blue > 1.0) + blue = 1.0; + else if (blue < 0.0) + blue = 0.0; + + hls_to_rgb (&red, &green, &blue); + + b->red = red * 65535.0; + b->green = green * 65535.0; + b->blue = blue * 65535.0; +} + +static void +rgb_to_hls (gdouble *r, + gdouble *g, + gdouble *b) +{ + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble h, l, s; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - max - min); + + delta = max -min; + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2 + (blue - red) / delta; + else if (blue == max) + h = 4 + (red - green) / delta; + + h *= 60; + if (h < 0.0) + h += 360; + } + + *r = h; + *g = l; + *b = s; +} + +static void +hls_to_rgb (gdouble *h, + gdouble *l, + gdouble *s) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + gdouble r, g, b; + + lightness = *l; + saturation = *s; + + if (lightness <= 0.5) + m2 = lightness * (1 + saturation); + else + m2 = lightness + saturation - lightness * saturation; + m1 = 2 * lightness - m2; + + if (saturation == 0) + { + *h = lightness; + *l = lightness; + *s = lightness; + } + else + { + hue = *h + 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + r = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + r = m2; + else if (hue < 240) + r = m1 + (m2 - m1) * (240 - hue) / 60; + else + r = m1; + + hue = *h; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + g = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + g = m2; + else if (hue < 240) + g = m1 + (m2 - m1) * (240 - hue) / 60; + else + g = m1; + + hue = *h - 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + b = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + b = m2; + else if (hue < 240) + b = m1 + (m2 - m1) * (240 - hue) / 60; + else + b = m1; + + *h = r; + *l = g; + *s = b; + } +} |