]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
Initial revision
[~andy/gtk] / gtk / gtkstyle.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <math.h>
19 #include "gtkgc.h"
20 #include "gtkstyle.h"
21
22
23 #define LIGHTNESS_MULT  1.3
24 #define DARKNESS_MULT   0.7
25
26
27 typedef struct _GtkStyleKey GtkStyleKey;
28
29 struct _GtkStyleKey
30 {
31   GdkColor fg[5];
32   GdkColor bg[5];
33   GdkColor text[5];
34   GdkColor base[5];
35
36   GdkPixmap *bg_pixmap[5];
37
38   GdkFont *font;
39
40   gint depth;
41   GdkColormap *colormap;
42   GtkStyleClass *klass;
43 };
44
45
46 static void         gtk_style_init         (GtkStyle    *style);
47 static void         gtk_styles_init        (void);
48 static void         gtk_style_remove       (GtkStyle    *style);
49 static GtkStyle*    gtk_style_find         (GtkStyle    *style,
50                                             GdkColormap *cmap,
51                                             gint         depth);
52 static GtkStyle*    gtk_style_new_from_key (GtkStyleKey *key);
53 static GtkStyleKey* gtk_style_key_dup      (GtkStyleKey *key);
54 static void         gtk_style_destroy      (GtkStyle    *style);
55 static void         gtk_style_key_destroy  (GtkStyleKey *key);
56 static guint        gtk_style_key_hash     (GtkStyleKey *key);
57 static guint        gtk_style_value_hash   (GtkStyle    *style);
58 static gint         gtk_style_key_compare  (GtkStyleKey *a,
59                                             GtkStyleKey *b);
60
61 static void gtk_default_draw_hline   (GtkStyle      *style,
62                                       GdkWindow     *window,
63                                       GtkStateType   state_type,
64                                       gint           x1,
65                                       gint           x2,
66                                       gint           y);
67 static void gtk_default_draw_vline   (GtkStyle      *style,
68                                       GdkWindow     *window,
69                                       GtkStateType   state_type,
70                                       gint           y1,
71                                       gint           y2,
72                                       gint           x);
73 static void gtk_default_draw_shadow  (GtkStyle      *style,
74                                       GdkWindow     *window,
75                                       GtkStateType   state_type,
76                                       GtkShadowType  shadow_type,
77                                       gint           x,
78                                       gint           y,
79                                       gint           width,
80                                       gint           height);
81 static void gtk_default_draw_polygon (GtkStyle      *style,
82                                       GdkWindow     *window,
83                                       GtkStateType   state_type,
84                                       GtkShadowType  shadow_type,
85                                       GdkPoint      *points,
86                                       gint           npoints,
87                                       gint           fill);
88 static void gtk_default_draw_arrow   (GtkStyle      *style,
89                                       GdkWindow     *window,
90                                       GtkStateType   state_type,
91                                       GtkShadowType  shadow_type,
92                                       GtkArrowType   arrow_type,
93                                       gint           fill,
94                                       gint           x,
95                                       gint           y,
96                                       gint           width,
97                                       gint           height);
98 static void gtk_default_draw_diamond (GtkStyle      *style,
99                                       GdkWindow     *window,
100                                       GtkStateType   state_type,
101                                       GtkShadowType  shadow_type,
102                                       gint           x,
103                                       gint           y,
104                                       gint           width,
105                                       gint           height);
106 static void gtk_default_draw_oval    (GtkStyle      *style,
107                                       GdkWindow     *window,
108                                       GtkStateType   state_type,
109                                       GtkShadowType  shadow_type,
110                                       gint           x,
111                                       gint           y,
112                                       gint           width,
113                                       gint           height);
114 static void gtk_default_draw_string  (GtkStyle      *style,
115                                       GdkWindow     *window,
116                                       GtkStateType   state_type,
117                                       gint           x,
118                                       gint           y,
119                                       const gchar   *string);
120
121 static void gtk_style_shade (GdkColor *a, GdkColor *b, gdouble k);
122 static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b);
123 static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s);
124
125
126 static GtkStyleClass default_class =
127 {
128   2,
129   2,
130   gtk_default_draw_hline,
131   gtk_default_draw_vline,
132   gtk_default_draw_shadow,
133   gtk_default_draw_polygon,
134   gtk_default_draw_arrow,
135   gtk_default_draw_diamond,
136   gtk_default_draw_oval,
137   gtk_default_draw_string,
138 };
139
140 static GdkColor gtk_default_normal_fg =      { 0,      0,      0,      0 };
141 static GdkColor gtk_default_active_fg =      { 0,      0,      0,      0 };
142 static GdkColor gtk_default_prelight_fg =    { 0,      0,      0,      0 };
143 static GdkColor gtk_default_selected_fg =    { 0, 0xffff, 0xffff, 0xffff };
144 static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 };
145
146 static GdkColor gtk_default_normal_bg =      { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
147 static GdkColor gtk_default_active_bg =      { 0, 0xc350, 0xc350, 0xc350 };
148 static GdkColor gtk_default_prelight_bg =    { 0, 0xea60, 0xea60, 0xea60 };
149 static GdkColor gtk_default_selected_bg =    { 0,      0,      0, 0x9c40 };
150 static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
151
152 static GdkFont *default_font = NULL;
153
154 static gint initialize = TRUE;
155 static GCache *style_cache = NULL;
156 static GSList *unattached_styles = NULL;
157
158 static GMemChunk *key_mem_chunk = NULL;
159
160
161 GtkStyle*
162 gtk_style_new ()
163 {
164   GtkStyle *style;
165   gint i;
166
167   style = g_new (GtkStyle, 1);
168
169   if (!default_font)
170     default_font = gdk_font_load ("-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*");
171
172   style->font = default_font;
173   gdk_font_ref (style->font);
174
175   style->ref_count = 0;
176   style->attach_count = 0;
177   style->colormap = NULL;
178   style->depth = -1;
179   style->klass = &default_class;
180
181   style->black.red = 0;
182   style->black.green = 0;
183   style->black.blue = 0;
184
185   style->white.red = 65535;
186   style->white.green = 65535;
187   style->white.blue = 65535;
188
189   style->black_gc = NULL;
190   style->white_gc = NULL;
191
192   style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
193   style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
194   style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
195   style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
196   style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
197
198   style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
199   style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
200   style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
201   style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
202   style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
203
204   for (i = 0; i < 5; i++)
205     {
206       style->text[i] = style->fg[i];
207       style->base[i] = style->white;
208     }
209
210   for (i = 0; i < 5; i++)
211     style->bg_pixmap[i] = NULL;
212
213   for (i = 0; i < 5; i++)
214     {
215       style->fg_gc[i] = NULL;
216       style->bg_gc[i] = NULL;
217       style->light_gc[i] = NULL;
218       style->dark_gc[i] = NULL;
219       style->mid_gc[i] = NULL;
220       style->text_gc[i] = NULL;
221       style->base_gc[i] = NULL;
222     }
223
224   unattached_styles = g_slist_prepend (unattached_styles, style);
225
226   return style;
227 }
228
229 GtkStyle*
230 gtk_style_attach (GtkStyle  *style,
231                   GdkWindow *window)
232 {
233   GtkStyle *new_style;
234   GdkColormap *colormap;
235   gint depth;
236
237   g_return_val_if_fail (style != NULL, NULL);
238   g_return_val_if_fail (window != NULL, NULL);
239
240   colormap = gdk_window_get_colormap (window);
241   gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
242
243   new_style = gtk_style_find (style, colormap, depth);
244
245   if (new_style && (new_style != style))
246     {
247       gtk_style_unref (style);
248       style = new_style;
249       gtk_style_ref (style);
250     }
251
252   if (style->attach_count == 0)
253     unattached_styles = g_slist_remove (unattached_styles, style);
254
255   style->attach_count += 1;
256
257   return style;
258 }
259
260 void
261 gtk_style_detach (GtkStyle *style)
262 {
263   gint i;
264
265   g_return_if_fail (style != NULL);
266
267   style->attach_count -= 1;
268   if (style->attach_count == 0)
269     {
270       unattached_styles = g_slist_prepend (unattached_styles, style);
271
272       gtk_gc_release (style->black_gc);
273       gtk_gc_release (style->white_gc);
274
275       style->black_gc = NULL;
276       style->white_gc = NULL;
277
278       for (i = 0; i < 5; i++)
279         {
280           gtk_gc_release (style->fg_gc[i]);
281           gtk_gc_release (style->bg_gc[i]);
282           gtk_gc_release (style->light_gc[i]);
283           gtk_gc_release (style->dark_gc[i]);
284           gtk_gc_release (style->mid_gc[i]);
285           gtk_gc_release (style->text_gc[i]);
286           gtk_gc_release (style->base_gc[i]);
287
288           style->fg_gc[i] = NULL;
289           style->bg_gc[i] = NULL;
290           style->light_gc[i] = NULL;
291           style->dark_gc[i] = NULL;
292           style->mid_gc[i] = NULL;
293           style->text_gc[i] = NULL;
294           style->base_gc[i] = NULL;
295         }
296
297       style->depth = -1;
298       style->colormap = NULL;
299     }
300
301   gtk_style_remove (style);
302 }
303
304 GtkStyle*
305 gtk_style_ref (GtkStyle *style)
306 {
307   g_return_val_if_fail (style != NULL, NULL);
308
309   style->ref_count += 1;
310   return style;
311 }
312
313 void
314 gtk_style_unref (GtkStyle *style)
315 {
316   g_return_if_fail (style != NULL);
317
318   style->ref_count -= 1;
319   if (style->ref_count == 0)
320     gtk_style_destroy (style);
321 }
322
323 void
324 gtk_style_set_background (GtkStyle     *style,
325                           GdkWindow    *window,
326                           GtkStateType  state_type)
327 {
328   GdkPixmap *pixmap;
329   gint parent_relative;
330
331   g_return_if_fail (style != NULL);
332   g_return_if_fail (window != NULL);
333
334   if (style->bg_pixmap[state_type])
335     {
336       if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
337         {
338           pixmap = NULL;
339           parent_relative = TRUE;
340         }
341       else
342         {
343           pixmap = style->bg_pixmap[state_type];
344           parent_relative = FALSE;
345         }
346
347       gdk_window_set_back_pixmap (window, pixmap, parent_relative);
348     }
349   else
350     gdk_window_set_background (window, &style->bg[state_type]);
351 }
352
353
354 void
355 gtk_draw_hline (GtkStyle     *style,
356                 GdkWindow    *window,
357                 GtkStateType  state_type,
358                 gint          x1,
359                 gint          x2,
360                 gint          y)
361 {
362   g_return_if_fail (style != NULL);
363   g_return_if_fail (style->klass != NULL);
364   g_return_if_fail (style->klass->draw_hline != NULL);
365
366   (*style->klass->draw_hline) (style, window, state_type, x1, x2, y);
367 }
368
369
370 void
371 gtk_draw_vline (GtkStyle     *style,
372                 GdkWindow    *window,
373                 GtkStateType  state_type,
374                 gint          y1,
375                 gint          y2,
376                 gint          x)
377 {
378   g_return_if_fail (style != NULL);
379   g_return_if_fail (style->klass != NULL);
380   g_return_if_fail (style->klass->draw_vline != NULL);
381
382   (*style->klass->draw_vline) (style, window, state_type, y1, y2, x);
383 }
384
385
386 void
387 gtk_draw_shadow (GtkStyle      *style,
388                  GdkWindow     *window,
389                  GtkStateType   state_type,
390                  GtkShadowType  shadow_type,
391                  gint           x,
392                  gint           y,
393                  gint           width,
394                  gint           height)
395 {
396   g_return_if_fail (style != NULL);
397   g_return_if_fail (style->klass != NULL);
398   g_return_if_fail (style->klass->draw_shadow != NULL);
399
400   (*style->klass->draw_shadow) (style, window, state_type, shadow_type, x, y, width, height);
401 }
402
403 void
404 gtk_draw_polygon (GtkStyle      *style,
405                   GdkWindow     *window,
406                   GtkStateType   state_type,
407                   GtkShadowType  shadow_type,
408                   GdkPoint      *points,
409                   gint           npoints,
410                   gint           fill)
411 {
412   g_return_if_fail (style != NULL);
413   g_return_if_fail (style->klass != NULL);
414   g_return_if_fail (style->klass->draw_shadow != NULL);
415
416   (*style->klass->draw_polygon) (style, window, state_type, shadow_type, points, npoints, fill);
417 }
418
419 void
420 gtk_draw_arrow (GtkStyle      *style,
421                 GdkWindow     *window,
422                 GtkStateType   state_type,
423                 GtkShadowType  shadow_type,
424                 GtkArrowType   arrow_type,
425                 gint           fill,
426                 gint           x,
427                 gint           y,
428                 gint           width,
429                 gint           height)
430 {
431   g_return_if_fail (style != NULL);
432   g_return_if_fail (style->klass != NULL);
433   g_return_if_fail (style->klass->draw_arrow != NULL);
434
435   (*style->klass->draw_arrow) (style, window, state_type, shadow_type, arrow_type, fill, x, y, width, height);
436 }
437
438
439 void
440 gtk_draw_diamond (GtkStyle      *style,
441                   GdkWindow     *window,
442                   GtkStateType   state_type,
443                   GtkShadowType  shadow_type,
444                   gint           x,
445                   gint           y,
446                   gint           width,
447                   gint           height)
448 {
449   g_return_if_fail (style != NULL);
450   g_return_if_fail (style->klass != NULL);
451   g_return_if_fail (style->klass->draw_diamond != NULL);
452
453   (*style->klass->draw_diamond) (style, window, state_type, shadow_type, x, y, width, height);
454 }
455
456
457 void
458 gtk_draw_oval (GtkStyle      *style,
459                GdkWindow     *window,
460                GtkStateType   state_type,
461                GtkShadowType  shadow_type,
462                gint           x,
463                gint           y,
464                gint           width,
465                gint           height)
466 {
467   g_return_if_fail (style != NULL);
468   g_return_if_fail (style->klass != NULL);
469   g_return_if_fail (style->klass->draw_oval != NULL);
470
471   (*style->klass->draw_oval) (style, window, state_type, shadow_type, x, y, width, height);
472 }
473
474 void
475 gtk_draw_string (GtkStyle      *style,
476                  GdkWindow     *window,
477                  GtkStateType   state_type,
478                  gint           x,
479                  gint           y,
480                  const gchar   *string)
481 {
482   g_return_if_fail (style != NULL);
483   g_return_if_fail (style->klass != NULL);
484   g_return_if_fail (style->klass->draw_oval != NULL);
485
486   (*style->klass->draw_string) (style, window, state_type, x, y, string);
487 }
488
489
490 static void
491 gtk_style_init (GtkStyle *style)
492 {
493   GdkGCValues gc_values;
494   GdkGCValuesMask gc_values_mask;
495   GdkColormap *colormap;
496   gint i;
497
498   g_return_if_fail (style != NULL);
499
500   if (style->attach_count == 0)
501     {
502       for (i = 0; i < 5; i++)
503         {
504           gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
505           gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
506
507           style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
508           style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
509           style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
510         }
511
512       colormap = style->colormap;
513
514       gdk_color_black (colormap, &style->black);
515       gdk_color_white (colormap, &style->white);
516
517       gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_FONT;
518       if (style->font->type == GDK_FONT_FONT)
519         {
520           gc_values.font = style->font;
521         }
522       else if (style->font->type == GDK_FONT_FONTSET)
523         {
524           gc_values.font = default_font;
525         }
526
527       gc_values.foreground = style->black;
528       style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
529
530       gc_values.foreground = style->white;
531       style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
532
533       for (i = 0; i < 5; i++)
534         {
535           if (!gdk_color_alloc (colormap, &style->fg[i]))
536             g_warning ("unable to allocate color: ( %d %d %d )",
537                        style->fg[i].red, style->fg[i].green, style->fg[i].blue);
538           if (!gdk_color_alloc (colormap, &style->bg[i]))
539             g_warning ("unable to allocate color: ( %d %d %d )",
540                        style->bg[i].red, style->bg[i].green, style->bg[i].blue);
541           if (!gdk_color_alloc (colormap, &style->light[i]))
542             g_warning ("unable to allocate color: ( %d %d %d )",
543                        style->light[i].red, style->light[i].green, style->light[i].blue);
544           if (!gdk_color_alloc (colormap, &style->dark[i]))
545             g_warning ("unable to allocate color: ( %d %d %d )",
546                        style->dark[i].red, style->dark[i].green, style->dark[i].blue);
547           if (!gdk_color_alloc (colormap, &style->mid[i]))
548             g_warning ("unable to allocate color: ( %d %d %d )",
549                        style->mid[i].red, style->mid[i].green, style->mid[i].blue);
550           if (!gdk_color_alloc (colormap, &style->text[i]))
551             g_warning ("unable to allocate color: ( %d %d %d )",
552                        style->text[i].red, style->text[i].green, style->text[i].blue);
553           if (!gdk_color_alloc (colormap, &style->base[i]))
554             g_warning ("unable to allocate color: ( %d %d %d )",
555                        style->base[i].red, style->base[i].green, style->base[i].blue);
556
557           gc_values.foreground = style->fg[i];
558           style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
559
560           gc_values.foreground = style->bg[i];
561           style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
562
563           gc_values.foreground = style->light[i];
564           style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
565
566           gc_values.foreground = style->dark[i];
567           style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
568
569           gc_values.foreground = style->mid[i];
570           style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
571
572           gc_values.foreground = style->text[i];
573           style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
574
575           gc_values.foreground = style->base[i];
576           style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
577         }
578     }
579 }
580
581 static void
582 gtk_styles_init ()
583 {
584   if (initialize)
585     {
586       initialize = FALSE;
587
588       style_cache = g_cache_new ((GCacheNewFunc) gtk_style_new_from_key,
589                                  (GCacheDestroyFunc) gtk_style_destroy,
590                                  (GCacheDupFunc) gtk_style_key_dup,
591                                  (GCacheDestroyFunc) gtk_style_key_destroy,
592                                  (GHashFunc) gtk_style_key_hash,
593                                  (GHashFunc) gtk_style_value_hash,
594                                  (GCompareFunc) gtk_style_key_compare);
595     }
596 }
597
598 static void
599 gtk_style_remove (GtkStyle *style)
600 {
601   if (initialize)
602     gtk_styles_init ();
603
604   g_cache_remove (style_cache, style);
605 }
606
607 static GtkStyle*
608 gtk_style_find (GtkStyle    *style,
609                 GdkColormap *cmap,
610                 gint         depth)
611 {
612   GtkStyleKey key;
613   gint i;
614
615   if (initialize)
616     gtk_styles_init ();
617
618   for (i = 0; i < 5; i++)
619     {
620       key.fg[i] = style->fg[i];
621       key.bg[i] = style->bg[i];
622       key.text[i] = style->text[i];
623       key.base[i] = style->base[i];
624       key.bg_pixmap[i] = style->bg_pixmap[i];
625     }
626
627   key.font = style->font;
628   key.klass = style->klass;
629   key.depth = depth;
630   key.colormap = cmap;
631
632   style = g_cache_insert (style_cache, &key);
633
634   return style;
635 }
636
637 static GtkStyle*
638 gtk_style_new_from_key (GtkStyleKey *key)
639 {
640   GtkStyle *style;
641   GSList *list;
642   gint i;
643
644   style = NULL;
645   list = unattached_styles;
646
647   while (list)
648     {
649       style = list->data;
650       list = list->next;
651
652       if ((style->depth != -1) && (style->depth != key->depth))
653         {
654           style = NULL;
655           continue;
656         }
657       if (style->colormap && (style->colormap != key->colormap))
658         {
659           style = NULL;
660           continue;
661         }
662       if (style->klass != key->klass)
663         {
664           style = NULL;
665           continue;
666         }
667       if (!gdk_font_equal (style->font, key->font))
668         {
669           style = NULL;
670           continue;
671         }
672
673       for (i = 0; style && (i < 5); i++)
674         {
675           if (style->bg_pixmap[i] != key->bg_pixmap[i])
676             {
677               style = NULL;
678               continue;
679             }
680
681           if ((style->fg[i].red != key->fg[i].red) ||
682               (style->fg[i].green != key->fg[i].green) ||
683               (style->fg[i].blue != key->fg[i].blue))
684             {
685               style = NULL;
686               continue;
687             }
688
689           if ((style->bg[i].red != key->bg[i].red) ||
690               (style->bg[i].green != key->bg[i].green) ||
691               (style->bg[i].blue != key->bg[i].blue))
692             {
693               style = NULL;
694               continue;
695             }
696
697           if ((style->text[i].red != key->text[i].red) ||
698               (style->text[i].green != key->text[i].green) ||
699               (style->text[i].blue != key->text[i].blue))
700             {
701               style = NULL;
702               continue;
703             }
704
705           if ((style->base[i].red != key->base[i].red) ||
706               (style->base[i].green != key->base[i].green) ||
707               (style->base[i].blue != key->base[i].blue))
708             {
709               style = NULL;
710               continue;
711             }
712         }
713
714       if (style)
715         break;
716     }
717
718   if (!style)
719     {
720       style = g_new (GtkStyle, 1);
721
722       style->ref_count = 0;
723       style->attach_count = 0;
724
725       style->font = key->font;
726       gdk_font_ref (style->font);
727
728       style->depth = key->depth;
729       style->colormap = key->colormap;
730       style->klass = key->klass;
731
732       style->black.red = 0;
733       style->black.green = 0;
734       style->black.blue = 0;
735
736       style->white.red = 65535;
737       style->white.green = 65535;
738       style->white.blue = 65535;
739
740       style->black_gc = NULL;
741       style->white_gc = NULL;
742
743       for (i = 0; i < 5; i++)
744         {
745           style->fg[i] = key->fg[i];
746           style->bg[i] = key->bg[i];
747           style->text[i] = key->text[i];
748           style->base[i] = key->base[i];
749         }
750
751       for (i = 0; i < 5; i++)
752         style->bg_pixmap[i] = key->bg_pixmap[i];
753
754       for (i = 0; i < 5; i++)
755         {
756           style->fg_gc[i] = NULL;
757           style->bg_gc[i] = NULL;
758           style->light_gc[i] = NULL;
759           style->dark_gc[i] = NULL;
760           style->mid_gc[i] = NULL;
761           style->text_gc[i] = NULL;
762           style->base_gc[i] = NULL;
763         }
764     }
765
766   if (style->depth == -1)
767     style->depth = key->depth;
768   if (!style->colormap)
769     style->colormap = key->colormap;
770
771   gtk_style_init (style);
772
773   return style;
774 }
775
776 static GtkStyleKey*
777 gtk_style_key_dup (GtkStyleKey *key)
778 {
779   GtkStyleKey *new_key;
780
781   if (!key_mem_chunk)
782     key_mem_chunk = g_mem_chunk_new ("key mem chunk", sizeof (GtkStyleKey),
783                                      1024, G_ALLOC_AND_FREE);
784
785   new_key = g_chunk_new (GtkStyleKey, key_mem_chunk);
786
787   *new_key = *key;
788
789   return new_key;
790 }
791
792 static void
793 gtk_style_destroy (GtkStyle *style)
794 {
795   gint i;
796
797   if (style->ref_count != 0)
798     return;
799
800   if (style->attach_count > 0)
801     {
802       gtk_gc_release (style->black_gc);
803       gtk_gc_release (style->white_gc);
804
805       for (i = 0; i < 5; i++)
806         {
807           gtk_gc_release (style->fg_gc[i]);
808           gtk_gc_release (style->bg_gc[i]);
809           gtk_gc_release (style->light_gc[i]);
810           gtk_gc_release (style->dark_gc[i]);
811           gtk_gc_release (style->mid_gc[i]);
812           gtk_gc_release (style->text_gc[i]);
813           gtk_gc_release (style->base_gc[i]);
814         }
815     }
816
817   unattached_styles = g_slist_remove (unattached_styles, style);
818
819   if (style->font->type == GDK_FONT_FONT)
820     gdk_font_free (style->font);
821   else if (style->font->type == GDK_FONT_FONTSET)
822     gdk_fontset_free (style->font);
823   else
824     g_error("undefined font type\n");
825
826   g_free (style);
827 }
828
829 static void
830 gtk_style_key_destroy (GtkStyleKey *key)
831 {
832   g_mem_chunk_free (key_mem_chunk, key);
833 }
834
835 static guint
836 gtk_style_key_hash (GtkStyleKey *key)
837 {
838   guint hash_val;
839   gint i;
840
841   hash_val = 0;
842
843   for (i = 0; i < 5; i++)
844     {
845       hash_val += key->fg[i].red + key->fg[i].green + key->fg[i].blue;
846       hash_val += key->bg[i].red + key->bg[i].green + key->bg[i].blue;
847       hash_val += key->text[i].red + key->text[i].green + key->text[i].blue;
848       hash_val += key->base[i].red + key->base[i].green + key->base[i].blue;
849     }
850
851   hash_val += (guint) gdk_font_id (key->font);
852   hash_val += (guint) key->depth;
853   hash_val += (gulong) key->colormap;
854   hash_val += (gulong) key->klass;
855
856   return hash_val;
857 }
858
859 static guint
860 gtk_style_value_hash (GtkStyle *style)
861 {
862   guint hash_val;
863   gint i;
864
865   hash_val = 0;
866
867   for (i = 0; i < 5; i++)
868     {
869       hash_val += style->fg[i].red + style->fg[i].green + style->fg[i].blue;
870       hash_val += style->bg[i].red + style->bg[i].green + style->bg[i].blue;
871       hash_val += style->text[i].red + style->text[i].green + style->text[i].blue;
872       hash_val += style->base[i].red + style->base[i].green + style->base[i].blue;
873     }
874
875   hash_val += (guint) gdk_font_id (style->font);
876   hash_val += (gulong) style->klass;
877
878   return hash_val;
879 }
880
881 static gint
882 gtk_style_key_compare (GtkStyleKey *a,
883                        GtkStyleKey *b)
884 {
885   gint i;
886
887   if (a->depth != b->depth)
888     return FALSE;
889   if (a->colormap != b->colormap)
890     return FALSE;
891   if (a->klass != b->klass)
892     return FALSE;
893   if (!gdk_font_equal (a->font, b->font))
894     return FALSE;
895
896   for (i = 0; i < 5; i++)
897     {
898       if (a->bg_pixmap[i] != b->bg_pixmap[i])
899         return FALSE;
900
901       if ((a->fg[i].red != b->fg[i].red) ||
902           (a->fg[i].green != b->fg[i].green) ||
903           (a->fg[i].blue != b->fg[i].blue))
904         return FALSE;
905       if ((a->bg[i].red != b->bg[i].red) ||
906           (a->bg[i].green != b->bg[i].green) ||
907           (a->bg[i].blue != b->bg[i].blue))
908         return FALSE;
909       if ((a->text[i].red != b->text[i].red) ||
910           (a->text[i].green != b->text[i].green) ||
911           (a->text[i].blue != b->text[i].blue))
912         return FALSE;
913       if ((a->base[i].red != b->base[i].red) ||
914           (a->base[i].green != b->base[i].green) ||
915           (a->base[i].blue != b->base[i].blue))
916         return FALSE;
917     }
918
919   return TRUE;
920 }
921
922
923 static void
924 gtk_default_draw_hline (GtkStyle     *style,
925                         GdkWindow    *window,
926                         GtkStateType  state_type,
927                         gint          x1,
928                         gint          x2,
929                         gint          y)
930 {
931   gint thickness_light;
932   gint thickness_dark;
933   gint i;
934
935   g_return_if_fail (style != NULL);
936   g_return_if_fail (window != NULL);
937
938   thickness_light = style->klass->ythickness / 2;
939   thickness_dark = style->klass->ythickness - thickness_light;
940
941   for (i = 0; i < thickness_dark; i++)
942     {
943       gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
944       gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
945     }
946
947   y += thickness_dark;
948   for (i = 0; i < thickness_light; i++)
949     {
950       gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
951       gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
952     }
953 }
954
955
956 static void
957 gtk_default_draw_vline (GtkStyle     *style,
958                         GdkWindow    *window,
959                         GtkStateType  state_type,
960                         gint          y1,
961                         gint          y2,
962                         gint          x)
963 {
964   gint thickness_light;
965   gint thickness_dark;
966   gint i;
967
968   g_return_if_fail (style != NULL);
969   g_return_if_fail (window != NULL);
970
971   thickness_light = style->klass->xthickness / 2;
972   thickness_dark = style->klass->xthickness - thickness_light;
973
974   for (i = 0; i < thickness_dark; i++)
975     {
976       gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
977       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
978     }
979
980   x += thickness_dark;
981   for (i = 0; i < thickness_light; i++)
982     {
983       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
984       gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
985     }
986 }
987
988
989 static void
990 gtk_default_draw_shadow (GtkStyle      *style,
991                          GdkWindow     *window,
992                          GtkStateType   state_type,
993                          GtkShadowType  shadow_type,
994                          gint           x,
995                          gint           y,
996                          gint           width,
997                          gint           height)
998 {
999   GdkGC *gc1;
1000   GdkGC *gc2;
1001   gint thickness_light;
1002   gint thickness_dark;
1003   gint i;
1004
1005   g_return_if_fail (style != NULL);
1006   g_return_if_fail (window != NULL);
1007
1008   if ((width == -1) && (height == -1))
1009     gdk_window_get_size (window, &width, &height);
1010   else if (width == -1)
1011     gdk_window_get_size (window, &width, NULL);
1012   else if (height == -1)
1013     gdk_window_get_size (window, NULL, &height);
1014
1015   switch (shadow_type)
1016     {
1017     case GTK_SHADOW_NONE:
1018       gc1 = NULL;
1019       gc2 = NULL;
1020       break;
1021     case GTK_SHADOW_IN:
1022     case GTK_SHADOW_ETCHED_IN:
1023       gc1 = style->light_gc[state_type];
1024       gc2 = style->dark_gc[state_type];
1025       break;
1026     case GTK_SHADOW_OUT:
1027     case GTK_SHADOW_ETCHED_OUT:
1028       gc1 = style->dark_gc[state_type];
1029       gc2 = style->light_gc[state_type];
1030       break;
1031     }
1032
1033   switch (shadow_type)
1034     {
1035     case GTK_SHADOW_NONE:
1036       break;
1037
1038     case GTK_SHADOW_IN:
1039       gdk_draw_line (window, gc1,
1040                      x, y + height - 1, x + width - 1, y + height - 1);
1041       gdk_draw_line (window, gc1,
1042                      x + width - 1, y, x + width - 1, y + height - 1);
1043
1044       gdk_draw_line (window, style->bg_gc[state_type],
1045                      x + 1, y + height - 2, x + width - 2, y + height - 2);
1046       gdk_draw_line (window, style->bg_gc[state_type],
1047                      x + width - 2, y + 1, x + width - 2, y + height - 2);
1048
1049       gdk_draw_line (window, style->black_gc,
1050                      x + 1, y + 1, x + width - 2, y + 1);
1051       gdk_draw_line (window, style->black_gc,
1052                      x + 1, y + 1, x + 1, y + height - 2);
1053
1054       gdk_draw_line (window, gc2,
1055                      x, y, x + width - 1, y);
1056       gdk_draw_line (window, gc2,
1057                      x, y, x, y + height - 1);
1058       break;
1059
1060     case GTK_SHADOW_OUT:
1061       gdk_draw_line (window, gc1,
1062                      x + 1, y + height - 2, x + width - 2, y + height - 2);
1063       gdk_draw_line (window, gc1,
1064                      x + width - 2, y + 1, x + width - 2, y + height - 2);
1065
1066       gdk_draw_line (window, gc2,
1067                      x, y, x + width - 1, y);
1068       gdk_draw_line (window, gc2,
1069                      x, y, x, y + height - 1);
1070
1071       gdk_draw_line (window, style->bg_gc[state_type],
1072                      x + 1, y + 1, x + width - 2, y + 1);
1073       gdk_draw_line (window, style->bg_gc[state_type],
1074                      x + 1, y + 1, x + 1, y + height - 2);
1075
1076       gdk_draw_line (window, style->black_gc,
1077                      x, y + height - 1, x + width - 1, y + height - 1);
1078       gdk_draw_line (window, style->black_gc,
1079                      x + width - 1, y, x + width - 1, y + height - 1);
1080       break;
1081
1082     case GTK_SHADOW_ETCHED_IN:
1083     case GTK_SHADOW_ETCHED_OUT:
1084       thickness_light = 1;
1085       thickness_dark = 1;
1086
1087       for (i = 0; i < thickness_dark; i++)
1088         {
1089           gdk_draw_line (window, gc1,
1090                          x + i,
1091                          y + height - i - 1,
1092                          x + width - i - 1,
1093                          y + height - i - 1);
1094           gdk_draw_line (window, gc1,
1095                          x + width - i - 1,
1096                          y + i,
1097                          x + width - i - 1,
1098                          y + height - i - 1);
1099
1100           gdk_draw_line (window, gc2,
1101                          x + i,
1102                          y + i,
1103                          x + width - i - 2,
1104                          y + i);
1105           gdk_draw_line (window, gc2,
1106                          x + i,
1107                          y + i,
1108                          x + i,
1109                          y + height - i - 2);
1110         }
1111
1112       for (i = 0; i < thickness_light; i++)
1113         {
1114           gdk_draw_line (window, gc1,
1115                          x + thickness_dark + i,
1116                          y + thickness_dark + i,
1117                          x + width - thickness_dark - i - 1,
1118                          y + thickness_dark + i);
1119           gdk_draw_line (window, gc1,
1120                          x + thickness_dark + i,
1121                          y + thickness_dark + i,
1122                          x + thickness_dark + i,
1123                          y + height - thickness_dark - i - 1);
1124
1125           gdk_draw_line (window, gc2,
1126                          x + thickness_dark + i,
1127                          y + height - thickness_light - i - 1,
1128                          x + width - thickness_light - 1,
1129                          y + height - thickness_light - i - 1);
1130           gdk_draw_line (window, gc2,
1131                          x + width - thickness_light - i - 1,
1132                          y + thickness_dark + i,
1133                          x + width - thickness_light - i - 1,
1134                          y + height - thickness_light - 1);
1135         }
1136       break;
1137     }
1138 }
1139
1140
1141 static void
1142 gtk_default_draw_polygon (GtkStyle      *style,
1143                           GdkWindow     *window,
1144                           GtkStateType   state_type,
1145                           GtkShadowType  shadow_type,
1146                           GdkPoint      *points,
1147                           gint           npoints,
1148                           gint           fill)
1149 {
1150 #ifndef M_PI
1151 #define M_PI    3.14159265358979323846
1152 #endif /* M_PI */
1153 #ifndef M_PI_4
1154 #define M_PI_4  0.78539816339744830962
1155 #endif /* M_PI_4 */
1156
1157   static const gdouble pi_over_4 = M_PI_4;
1158   static const gdouble pi_3_over_4 = M_PI_4 * 3;
1159
1160   GdkGC *gc1;
1161   GdkGC *gc2;
1162   GdkGC *gc3;
1163   GdkGC *gc4;
1164   gdouble angle;
1165   gint xadjust;
1166   gint yadjust;
1167   gint i;
1168
1169   g_return_if_fail (style != NULL);
1170   g_return_if_fail (window != NULL);
1171   g_return_if_fail (points != NULL);
1172
1173   switch (shadow_type)
1174     {
1175     case GTK_SHADOW_IN:
1176       gc1 = style->bg_gc[state_type];
1177       gc2 = style->dark_gc[state_type];
1178       gc3 = style->light_gc[state_type];
1179       gc4 = style->black_gc;
1180       break;
1181     case GTK_SHADOW_OUT:
1182       gc1 = style->dark_gc[state_type];
1183       gc2 = style->light_gc[state_type];
1184       gc3 = style->black_gc;
1185       gc4 = style->bg_gc[state_type];
1186       break;
1187     default:
1188       return;
1189     }
1190
1191   if (fill)
1192     gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
1193
1194   npoints -= 1;
1195   for (i = 0; i < npoints; i++)
1196     {
1197       if ((points[i].x == points[i+1].x) &&
1198           (points[i].y == points[i+1].y))
1199         {
1200           angle = 0;
1201         }
1202       else
1203         {
1204           angle = atan2 (points[i+1].y - points[i].y,
1205                          points[i+1].x - points[i].x);
1206         }
1207
1208       if ((angle > -pi_3_over_4) && (angle < pi_over_4))
1209         {
1210           while (angle < 0)
1211             angle += M_PI;
1212           while (angle > M_PI)
1213             angle -= M_PI;
1214
1215           if ((angle > pi_3_over_4) || (angle < pi_over_4))
1216             {
1217               xadjust = 0;
1218               yadjust = 1;
1219             }
1220           else
1221             {
1222               xadjust = 1;
1223               yadjust = 0;
1224             }
1225
1226           gdk_draw_line (window, gc1,
1227                          points[i].x-xadjust, points[i].y-yadjust,
1228                          points[i+1].x-xadjust, points[i+1].y-yadjust);
1229           gdk_draw_line (window, gc3,
1230                          points[i].x, points[i].y,
1231                          points[i+1].x, points[i+1].y);
1232         }
1233     }
1234
1235   for (i = 0; i < npoints; i++)
1236     {
1237       if ((points[i].x == points[i+1].x) &&
1238           (points[i].y == points[i+1].y))
1239         {
1240           angle = 0;
1241         }
1242       else
1243         {
1244           angle = atan2 (points[i+1].y - points[i].y,
1245                          points[i+1].x - points[i].x);
1246         }
1247
1248       if ((angle <= -pi_3_over_4) || (angle >= pi_over_4))
1249         {
1250           while (angle < 0)
1251             angle += M_PI;
1252           while (angle > M_PI)
1253             angle -= M_PI;
1254
1255           if ((angle > pi_3_over_4) || (angle < pi_over_4))
1256             {
1257               xadjust = 0;
1258               yadjust = 1;
1259             }
1260           else
1261             {
1262               xadjust = 1;
1263               yadjust = 0;
1264             }
1265
1266           gdk_draw_line (window, gc4,
1267                          points[i].x+xadjust, points[i].y+yadjust,
1268                          points[i+1].x+xadjust, points[i+1].y+yadjust);
1269           gdk_draw_line (window, gc2,
1270                          points[i].x, points[i].y,
1271                          points[i+1].x, points[i+1].y);
1272         }
1273     }
1274 }
1275
1276
1277 static void
1278 gtk_default_draw_arrow (GtkStyle      *style,
1279                         GdkWindow     *window,
1280                         GtkStateType   state_type,
1281                         GtkShadowType  shadow_type,
1282                         GtkArrowType   arrow_type,
1283                         gint           fill,
1284                         gint           x,
1285                         gint           y,
1286                         gint           width,
1287                         gint           height)
1288 {
1289   GdkGC *gc1;
1290   GdkGC *gc2;
1291   GdkGC *gc3;
1292   GdkGC *gc4;
1293   gint half_width;
1294   gint half_height;
1295   GdkPoint points[3];
1296
1297   g_return_if_fail (style != NULL);
1298   g_return_if_fail (window != NULL);
1299
1300   switch (shadow_type)
1301     {
1302     case GTK_SHADOW_IN:
1303       gc1 = style->bg_gc[state_type];
1304       gc2 = style->dark_gc[state_type];
1305       gc3 = style->light_gc[state_type];
1306       gc4 = style->black_gc;
1307       break;
1308     case GTK_SHADOW_OUT:
1309       gc1 = style->dark_gc[state_type];
1310       gc2 = style->light_gc[state_type];
1311       gc3 = style->black_gc;
1312       gc4 = style->bg_gc[state_type];
1313       break;
1314     default:
1315       return;
1316     }
1317
1318   if ((width == -1) && (height == -1))
1319     gdk_window_get_size (window, &width, &height);
1320   else if (width == -1)
1321     gdk_window_get_size (window, &width, NULL);
1322   else if (height == -1)
1323     gdk_window_get_size (window, NULL, &height);
1324
1325   half_width = width / 2;
1326   half_height = height / 2;
1327
1328   switch (arrow_type)
1329     {
1330     case GTK_ARROW_UP:
1331       if (fill)
1332         {
1333           points[0].x = x + half_width;
1334           points[0].y = y;
1335           points[1].x = x;
1336           points[1].y = y + height - 1;
1337           points[2].x = x + width - 1;
1338           points[2].y = y + height - 1;
1339
1340           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1341         }
1342
1343       gdk_draw_line (window, gc1,
1344                      x + 1, y + height - 2,
1345                      x + width - 2, y + height - 2);
1346       gdk_draw_line (window, gc3,
1347                      x + 0, y + height - 1,
1348                      x + width - 1, y + height - 1);
1349
1350       gdk_draw_line (window, gc1,
1351                      x + width - 2, y + height - 1,
1352                      x + half_width, y + 1);
1353       gdk_draw_line (window, gc3,
1354                      x + width - 1, y + height - 1,
1355                      x + half_width, y);
1356
1357       gdk_draw_line (window, gc4,
1358                      x + half_width, y + 1,
1359                      x + 1, y + height - 1);
1360       gdk_draw_line (window, gc2,
1361                      x + half_width, y,
1362                      x, y + height - 1);
1363       break;
1364     case GTK_ARROW_DOWN:
1365       if (fill)
1366         {
1367           points[0].x = x + width - 1;
1368           points[0].y = y;
1369           points[1].x = x;
1370           points[1].y = y;
1371           points[2].x = x + half_width;
1372           points[2].y = y + height - 1;
1373
1374           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1375         }
1376
1377       gdk_draw_line (window, gc4,
1378                      x + width - 2,
1379                      y + 1, x + 1, y + 1);
1380       gdk_draw_line (window, gc2,
1381                      x + width - 1, y,
1382                      x, y);
1383
1384       gdk_draw_line (window, gc4,
1385                      x + 1, y,
1386                      x + half_width, y + height - 2);
1387       gdk_draw_line (window, gc2,
1388                      x, y,
1389                      x + half_width, y + height - 1);
1390
1391       gdk_draw_line (window, gc1,
1392                      x + half_width, y + height - 2,
1393                      x + width - 2, y);
1394       gdk_draw_line (window, gc3,
1395                      x + half_width, y + height - 1,
1396                      x + width - 1, y);
1397       break;
1398     case GTK_ARROW_LEFT:
1399       if (fill)
1400         {
1401           points[0].x = x;
1402           points[0].y = y + half_height;
1403           points[1].x = x + width - 1;
1404           points[1].y = y + height - 1;
1405           points[2].x = x + width - 1;
1406           points[2].y = y;
1407
1408           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1409         }
1410
1411       gdk_draw_line (window, gc1,
1412                      x + 1, y + half_height,
1413                      x + width - 1, y + height - 1);
1414       gdk_draw_line (window, gc3,
1415                      x, y + half_height,
1416                      x + width - 1, y + height - 1);
1417
1418       gdk_draw_line (window, gc1,
1419                      x + width - 2, y + height - 1,
1420                      x + width - 2, y + 1);
1421       gdk_draw_line (window, gc3,
1422                      x + width - 1, y + height - 1,
1423                      x + width - 1, y);
1424
1425       gdk_draw_line (window, gc4,
1426                      x + width - 1, y + 1,
1427                      x + 1, y + half_width);
1428       gdk_draw_line (window, gc2,
1429                      x + width - 1, y,
1430                      x, y + half_width);
1431       break;
1432     case GTK_ARROW_RIGHT:
1433       if (fill)
1434         {
1435           points[0].x = x + width - 1;
1436           points[0].y = y + half_height;
1437           points[1].x = x;
1438           points[1].y = y;
1439           points[2].x = x;
1440           points[2].y = y + height - 1;
1441
1442           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1443         }
1444
1445       gdk_draw_line (window, gc4,
1446                      x + width - 1, y + half_height,
1447                      x + 1, y + 1);
1448       gdk_draw_line (window, gc2,
1449                      x + width - 1, y + half_height,
1450                      x, y);
1451
1452       gdk_draw_line (window, gc4,
1453                      x + 1, y + 1,
1454                      x + 1, y + height - 2);
1455       gdk_draw_line (window, gc2,
1456                      x, y,
1457                      x, y + height - 1);
1458
1459       gdk_draw_line (window, gc1,
1460                      x + 1, y + height - 2,
1461                      x + width - 1, y + half_height);
1462       gdk_draw_line (window, gc3,
1463                      x, y + height - 1,
1464                      x + width - 1, y + half_height);
1465       break;
1466     }
1467 }
1468
1469
1470 static void
1471 gtk_default_draw_diamond (GtkStyle      *style,
1472                           GdkWindow     *window,
1473                           GtkStateType   state_type,
1474                           GtkShadowType  shadow_type,
1475                           gint           x,
1476                           gint           y,
1477                           gint           width,
1478                           gint           height)
1479 {
1480   gint half_width;
1481   gint half_height;
1482
1483   g_return_if_fail (style != NULL);
1484   g_return_if_fail (window != NULL);
1485
1486   if ((width == -1) && (height == -1))
1487     gdk_window_get_size (window, &width, &height);
1488   else if (width == -1)
1489     gdk_window_get_size (window, &width, NULL);
1490   else if (height == -1)
1491     gdk_window_get_size (window, NULL, &height);
1492
1493   half_width = width / 2;
1494   half_height = height / 2;
1495
1496   switch (shadow_type)
1497     {
1498     case GTK_SHADOW_IN:
1499       gdk_draw_line (window, style->bg_gc[state_type],
1500                      x + 2, y + half_height,
1501                      x + half_width, y + height - 2);
1502       gdk_draw_line (window, style->bg_gc[state_type],
1503                      x + half_width, y + height - 2,
1504                      x + width - 2, y + half_height);
1505       gdk_draw_line (window, style->light_gc[state_type],
1506                      x + 1, y + half_height,
1507                      x + half_width, y + height - 1);
1508       gdk_draw_line (window, style->light_gc[state_type],
1509                      x + half_width, y + height - 1,
1510                      x + width - 1, y + half_height);
1511       gdk_draw_line (window, style->light_gc[state_type],
1512                      x, y + half_height,
1513                      x + half_width, y + height);
1514       gdk_draw_line (window, style->light_gc[state_type],
1515                      x + half_width, y + height,
1516                      x + width, y + half_height);
1517
1518       gdk_draw_line (window, style->black_gc,
1519                      x + 2, y + half_height,
1520                      x + half_width, y + 2);
1521       gdk_draw_line (window, style->black_gc,
1522                      x + half_width, y + 2,
1523                      x + width - 2, y + half_height);
1524       gdk_draw_line (window, style->dark_gc[state_type],
1525                      x + 1, y + half_height,
1526                      x + half_width, y + 1);
1527       gdk_draw_line (window, style->dark_gc[state_type],
1528                      x + half_width, y + 1,
1529                      x + width - 1, y + half_height);
1530       gdk_draw_line (window, style->dark_gc[state_type],
1531                      x, y + half_height,
1532                      x + half_width, y);
1533       gdk_draw_line (window, style->dark_gc[state_type],
1534                      x + half_width, y,
1535                      x + width, y + half_height);
1536       break;
1537     case GTK_SHADOW_OUT:
1538       gdk_draw_line (window, style->dark_gc[state_type],
1539                      x + 2, y + half_height,
1540                      x + half_width, y + height - 2);
1541       gdk_draw_line (window, style->dark_gc[state_type],
1542                      x + half_width, y + height - 2,
1543                      x + width - 2, y + half_height);
1544       gdk_draw_line (window, style->dark_gc[state_type],
1545                      x + 1, y + half_height,
1546                      x + half_width, y + height - 1);
1547       gdk_draw_line (window, style->dark_gc[state_type],
1548                      x + half_width, y + height - 1,
1549                      x + width - 1, y + half_height);
1550       gdk_draw_line (window, style->black_gc,
1551                      x, y + half_height,
1552                      x + half_width, y + height);
1553       gdk_draw_line (window, style->black_gc,
1554                      x + half_width, y + height,
1555                      x + width, y + half_height);
1556
1557       gdk_draw_line (window, style->bg_gc[state_type],
1558                      x + 2, y + half_height,
1559                      x + half_width, y + 2);
1560       gdk_draw_line (window, style->bg_gc[state_type],
1561                      x + half_width, y + 2,
1562                      x + width - 2, y + half_height);
1563       gdk_draw_line (window, style->light_gc[state_type],
1564                      x + 1, y + half_height,
1565                      x + half_width, y + 1);
1566       gdk_draw_line (window, style->light_gc[state_type],
1567                      x + half_width, y + 1,
1568                      x + width - 1, y + half_height);
1569       gdk_draw_line (window, style->light_gc[state_type],
1570                      x, y + half_height,
1571                      x + half_width, y);
1572       gdk_draw_line (window, style->light_gc[state_type],
1573                      x + half_width, y,
1574                      x + width, y + half_height);
1575       break;
1576     default:
1577       break;
1578     }
1579 }
1580
1581
1582 static void
1583 gtk_default_draw_oval (GtkStyle      *style,
1584                        GdkWindow     *window,
1585                        GtkStateType   state_type,
1586                        GtkShadowType  shadow_type,
1587                        gint           x,
1588                        gint           y,
1589                        gint           width,
1590                        gint           height)
1591 {
1592   g_return_if_fail (style != NULL);
1593   g_return_if_fail (window != NULL);
1594 }
1595
1596 static void
1597 gtk_default_draw_string (GtkStyle      *style,
1598                          GdkWindow     *window,
1599                          GtkStateType   state_type,
1600                          gint           x,
1601                          gint           y,
1602                          const gchar   *string)
1603 {
1604   g_return_if_fail (style != NULL);
1605   g_return_if_fail (window != NULL);
1606
1607   if (state_type == GTK_STATE_INSENSITIVE)
1608     gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, string);
1609   gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, string);
1610 }
1611
1612
1613 static void
1614 gtk_style_shade (GdkColor *a,
1615                  GdkColor *b,
1616                  gdouble   k)
1617 {
1618   gdouble red;
1619   gdouble green;
1620   gdouble blue;
1621
1622   red = (gdouble) a->red / 65535.0;
1623   green = (gdouble) a->green / 65535.0;
1624   blue = (gdouble) a->blue / 65535.0;
1625
1626   rgb_to_hls (&red, &green, &blue);
1627
1628   green *= k;
1629   if (green > 1.0)
1630     green = 1.0;
1631   else if (green < 0.0)
1632     green = 0.0;
1633
1634   blue *= k;
1635   if (blue > 1.0)
1636     blue = 1.0;
1637   else if (blue < 0.0)
1638     blue = 0.0;
1639
1640   hls_to_rgb (&red, &green, &blue);
1641
1642   b->red = red * 65535.0;
1643   b->green = green * 65535.0;
1644   b->blue = blue * 65535.0;
1645 }
1646
1647 static void
1648 rgb_to_hls (gdouble *r,
1649             gdouble *g,
1650             gdouble *b)
1651 {
1652   gdouble min;
1653   gdouble max;
1654   gdouble red;
1655   gdouble green;
1656   gdouble blue;
1657   gdouble h, l, s;
1658   gdouble delta;
1659
1660   red = *r;
1661   green = *g;
1662   blue = *b;
1663
1664   if (red > green)
1665     {
1666       if (red > blue)
1667         max = red;
1668       else
1669         max = blue;
1670
1671       if (green < blue)
1672         min = green;
1673       else
1674         min = blue;
1675     }
1676   else
1677     {
1678       if (green > blue)
1679         max = green;
1680       else
1681         max = blue;
1682
1683       if (red < blue)
1684         min = red;
1685       else
1686         min = blue;
1687     }
1688
1689   l = (max + min) / 2;
1690   s = 0;
1691   h = 0;
1692
1693   if (max != min)
1694     {
1695       if (l <= 0.5)
1696         s = (max - min) / (max + min);
1697       else
1698         s = (max - min) / (2 - max - min);
1699
1700       delta = max -min;
1701       if (red == max)
1702         h = (green - blue) / delta;
1703       else if (green == max)
1704         h = 2 + (blue - red) / delta;
1705       else if (blue == max)
1706         h = 4 + (red - green) / delta;
1707
1708       h *= 60;
1709       if (h < 0.0)
1710         h += 360;
1711     }
1712
1713   *r = h;
1714   *g = l;
1715   *b = s;
1716 }
1717
1718 static void
1719 hls_to_rgb (gdouble *h,
1720             gdouble *l,
1721             gdouble *s)
1722 {
1723   gdouble hue;
1724   gdouble lightness;
1725   gdouble saturation;
1726   gdouble m1, m2;
1727   gdouble r, g, b;
1728
1729   lightness = *l;
1730   saturation = *s;
1731
1732   if (lightness <= 0.5)
1733     m2 = lightness * (1 + saturation);
1734   else
1735     m2 = lightness + saturation - lightness * saturation;
1736   m1 = 2 * lightness - m2;
1737
1738   if (saturation == 0)
1739     {
1740       *h = lightness;
1741       *l = lightness;
1742       *s = lightness;
1743     }
1744   else
1745     {
1746       hue = *h + 120;
1747       while (hue > 360)
1748         hue -= 360;
1749       while (hue < 0)
1750         hue += 360;
1751
1752       if (hue < 60)
1753         r = m1 + (m2 - m1) * hue / 60;
1754       else if (hue < 180)
1755         r = m2;
1756       else if (hue < 240)
1757         r = m1 + (m2 - m1) * (240 - hue) / 60;
1758       else
1759         r = m1;
1760
1761       hue = *h;
1762       while (hue > 360)
1763         hue -= 360;
1764       while (hue < 0)
1765         hue += 360;
1766
1767       if (hue < 60)
1768         g = m1 + (m2 - m1) * hue / 60;
1769       else if (hue < 180)
1770         g = m2;
1771       else if (hue < 240)
1772         g = m1 + (m2 - m1) * (240 - hue) / 60;
1773       else
1774         g = m1;
1775
1776       hue = *h - 120;
1777       while (hue > 360)
1778         hue -= 360;
1779       while (hue < 0)
1780         hue += 360;
1781
1782       if (hue < 60)
1783         b = m1 + (m2 - m1) * hue / 60;
1784       else if (hue < 180)
1785         b = m2;
1786       else if (hue < 240)
1787         b = m1 + (m2 - m1) * (240 - hue) / 60;
1788       else
1789         b = m1;
1790
1791       *h = r;
1792       *l = g;
1793       *s = b;
1794     }
1795 }