]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
[broadway] Add initial keyboard event support
[~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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28 #include <math.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <gobject/gvaluecollector.h>
32 #include "gtkmarshalers.h"
33 #include "gtkpango.h"
34 #include "gtkrc.h"
35 #include "gtkspinbutton.h"
36 #include "gtkstyle.h"
37 #include "gtkwidget.h"
38 #include "gtkthemes.h"
39 #include "gtkiconfactory.h"
40 #include "gtksettings.h"        /* _gtk_settings_parse_convert() */
41 #include "gtkintl.h"
42 #include "gtkdebug.h"
43 #include "gtkspinner.h"
44
45
46 /**
47  * SECTION:gtkstyle
48  * @Short_description: An object that hold style information for widgets
49  * @Title: GtkStyle
50  *
51  * A #GtkStyle object encapsulates the information that provides the look and
52  * feel for a widget. Each #GtkWidget has an associated #GTkStyle object that
53  * is used when rendering that widget. Also, a #GtkStyle holds information for
54  * the five possible widget states though not every widget supports all five
55  * states; see #GtkStateType.
56  *
57  * Usually the #GtkStyle for a widget is the same as the default style that is
58  * set by GTK+ and modified the theme engine.
59  *
60  * Usually applications should not need to use or modify the #GtkStyle of their
61  * widgets.
62  */
63
64
65 #define LIGHTNESS_MULT  1.3
66 #define DARKNESS_MULT   0.7
67
68 /* --- typedefs & structures --- */
69 typedef struct {
70   GType       widget_type;
71   GParamSpec *pspec;
72   GValue      value;
73 } PropertyValue;
74
75 #define GTK_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_STYLE, GtkStylePrivate))
76
77 typedef struct _GtkStylePrivate GtkStylePrivate;
78
79 struct _GtkStylePrivate {
80   GSList *color_hashes;
81 };
82
83 /* --- prototypes --- */
84 static void      gtk_style_finalize             (GObject        *object);
85 static void      gtk_style_realize              (GtkStyle       *style,
86                                                  GdkVisual      *visual);
87 static void      gtk_style_real_realize        (GtkStyle        *style);
88 static void      gtk_style_real_unrealize      (GtkStyle        *style);
89 static void      gtk_style_real_copy           (GtkStyle        *style,
90                                                 GtkStyle        *src);
91 static void      gtk_style_real_set_background (GtkStyle        *style,
92                                                 GdkWindow       *window,
93                                                 GtkStateType     state_type);
94 static GtkStyle *gtk_style_real_clone          (GtkStyle        *style);
95 static void      gtk_style_real_init_from_rc   (GtkStyle        *style,
96                                                 GtkRcStyle      *rc_style);
97 static GdkPixbuf *gtk_default_render_icon      (GtkStyle            *style,
98                                                 const GtkIconSource *source,
99                                                 GtkTextDirection     direction,
100                                                 GtkStateType         state,
101                                                 GtkIconSize          size,
102                                                 GtkWidget           *widget,
103                                                 const gchar         *detail);
104 static void gtk_default_draw_hline      (GtkStyle        *style,
105                                          cairo_t         *cr,
106                                          GtkStateType     state_type,
107                                          GtkWidget       *widget,
108                                          const gchar     *detail,
109                                          gint             x1,
110                                          gint             x2,
111                                          gint             y);
112 static void gtk_default_draw_vline      (GtkStyle        *style,
113                                          cairo_t         *cr,
114                                          GtkStateType     state_type,
115                                          GtkWidget       *widget,
116                                          const gchar     *detail,
117                                          gint             y1,
118                                          gint             y2,
119                                          gint             x);
120 static void gtk_default_draw_shadow     (GtkStyle        *style,
121                                          cairo_t         *cr,
122                                          GtkStateType     state_type,
123                                          GtkShadowType    shadow_type,
124                                          GtkWidget       *widget,
125                                          const gchar     *detail,
126                                          gint             x,
127                                          gint             y,
128                                          gint             width,
129                                          gint             height);
130 static void gtk_default_draw_arrow      (GtkStyle        *style,
131                                          cairo_t         *cr,
132                                          GtkStateType     state_type,
133                                          GtkShadowType    shadow_type,
134                                          GtkWidget       *widget,
135                                          const gchar     *detail,
136                                          GtkArrowType     arrow_type,
137                                          gboolean         fill,
138                                          gint             x,
139                                          gint             y,
140                                          gint             width,
141                                          gint             height);
142 static void gtk_default_draw_diamond    (GtkStyle        *style,
143                                          cairo_t         *cr,
144                                          GtkStateType     state_type,
145                                          GtkShadowType    shadow_type,
146                                          GtkWidget       *widget,
147                                          const gchar     *detail,
148                                          gint             x,
149                                          gint             y,
150                                          gint             width,
151                                          gint             height);
152 static void gtk_default_draw_box        (GtkStyle        *style,
153                                          cairo_t         *cr,
154                                          GtkStateType     state_type,
155                                          GtkShadowType    shadow_type,
156                                          GtkWidget       *widget,
157                                          const gchar     *detail,
158                                          gint             x,
159                                          gint             y,
160                                          gint             width,
161                                          gint             height);
162 static void gtk_default_draw_flat_box   (GtkStyle        *style,
163                                          cairo_t         *cr,
164                                          GtkStateType     state_type,
165                                          GtkShadowType    shadow_type,
166                                          GtkWidget       *widget,
167                                          const gchar     *detail,
168                                          gint             x,
169                                          gint             y,
170                                          gint             width,
171                                          gint             height);
172 static void gtk_default_draw_check      (GtkStyle        *style,
173                                          cairo_t         *cr,
174                                          GtkStateType     state_type,
175                                          GtkShadowType    shadow_type,
176                                          GtkWidget       *widget,
177                                          const gchar     *detail,
178                                          gint             x,
179                                          gint             y,
180                                          gint             width,
181                                          gint             height);
182 static void gtk_default_draw_option     (GtkStyle        *style,
183                                          cairo_t         *cr,
184                                          GtkStateType     state_type,
185                                          GtkShadowType    shadow_type,
186                                          GtkWidget       *widget,
187                                          const gchar     *detail,
188                                          gint             x,
189                                          gint             y,
190                                          gint             width,
191                                          gint             height);
192 static void gtk_default_draw_tab        (GtkStyle        *style,
193                                          cairo_t         *cr,
194                                          GtkStateType     state_type,
195                                          GtkShadowType    shadow_type,
196                                          GtkWidget       *widget,
197                                          const gchar     *detail,
198                                          gint             x,
199                                          gint             y,
200                                          gint             width,
201                                          gint             height);
202 static void gtk_default_draw_shadow_gap (GtkStyle        *style,
203                                          cairo_t         *cr,
204                                          GtkStateType     state_type,
205                                          GtkShadowType    shadow_type,
206                                          GtkWidget       *widget,
207                                          const gchar     *detail,
208                                          gint             x,
209                                          gint             y,
210                                          gint             width,
211                                          gint             height,
212                                          GtkPositionType  gap_side,
213                                          gint             gap_x,
214                                          gint             gap_width);
215 static void gtk_default_draw_box_gap    (GtkStyle        *style,
216                                          cairo_t         *cr,
217                                          GtkStateType     state_type,
218                                          GtkShadowType    shadow_type,
219                                          GtkWidget       *widget,
220                                          const gchar     *detail,
221                                          gint             x,
222                                          gint             y,
223                                          gint             width,
224                                          gint             height,
225                                          GtkPositionType  gap_side,
226                                          gint             gap_x,
227                                          gint             gap_width);
228 static void gtk_default_draw_extension  (GtkStyle        *style,
229                                          cairo_t         *cr,
230                                          GtkStateType     state_type,
231                                          GtkShadowType    shadow_type,
232                                          GtkWidget       *widget,
233                                          const gchar     *detail,
234                                          gint             x,
235                                          gint             y,
236                                          gint             width,
237                                          gint             height,
238                                          GtkPositionType  gap_side);
239 static void gtk_default_draw_focus      (GtkStyle        *style,
240                                          cairo_t         *cr,
241                                          GtkStateType     state_type,
242                                          GtkWidget       *widget,
243                                          const gchar     *detail,
244                                          gint             x,
245                                          gint             y,
246                                          gint             width,
247                                          gint             height);
248 static void gtk_default_draw_slider     (GtkStyle        *style,
249                                          cairo_t         *cr,
250                                          GtkStateType     state_type,
251                                          GtkShadowType    shadow_type,
252                                          GtkWidget       *widget,
253                                          const gchar     *detail,
254                                          gint             x,
255                                          gint             y,
256                                          gint             width,
257                                          gint             height,
258                                          GtkOrientation   orientation);
259 static void gtk_default_draw_handle     (GtkStyle        *style,
260                                          cairo_t         *cr,
261                                          GtkStateType     state_type,
262                                          GtkShadowType    shadow_type,
263                                          GtkWidget       *widget,
264                                          const gchar     *detail,
265                                          gint             x,
266                                          gint             y,
267                                          gint             width,
268                                          gint             height,
269                                          GtkOrientation   orientation);
270 static void gtk_default_draw_expander   (GtkStyle        *style,
271                                          cairo_t         *cr,
272                                          GtkStateType     state_type,
273                                          GtkWidget       *widget,
274                                          const gchar     *detail,
275                                          gint             x,
276                                          gint             y,
277                                          GtkExpanderStyle expander_style);
278 static void gtk_default_draw_layout     (GtkStyle        *style,
279                                          cairo_t         *cr,
280                                          GtkStateType     state_type,
281                                          gboolean         use_text,
282                                          GtkWidget       *widget,
283                                          const gchar     *detail,
284                                          gint             x,
285                                          gint             y,
286                                          PangoLayout     *layout);
287 static void gtk_default_draw_resize_grip (GtkStyle       *style,
288                                           cairo_t        *cr,
289                                           GtkStateType    state_type,
290                                           GtkWidget      *widget,
291                                           const gchar    *detail,
292                                           GdkWindowEdge   edge,
293                                           gint            x,
294                                           gint            y,
295                                           gint            width,
296                                           gint            height);
297 static void gtk_default_draw_spinner     (GtkStyle       *style,
298                                           cairo_t        *cr,
299                                           GtkStateType    state_type,
300                                           GtkWidget      *widget,
301                                           const gchar    *detail,
302                                           guint           step,
303                                           gint            x,
304                                           gint            y,
305                                           gint            width,
306                                           gint            height);
307
308 static void rgb_to_hls                  (gdouble         *r,
309                                          gdouble         *g,
310                                          gdouble         *b);
311 static void hls_to_rgb                  (gdouble         *h,
312                                          gdouble         *l,
313                                          gdouble         *s);
314
315 static void style_unrealize_cursors     (GtkStyle *style);
316
317 /*
318  * Data for default check and radio buttons
319  */
320
321 static const GtkRequisition default_option_indicator_size = { 7, 13 };
322 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
323
324 #define GTK_GRAY                0xdcdc, 0xdada, 0xd5d5
325 #define GTK_DARK_GRAY           0xc4c4, 0xc2c2, 0xbdbd
326 #define GTK_LIGHT_GRAY          0xeeee, 0xebeb, 0xe7e7
327 #define GTK_WHITE               0xffff, 0xffff, 0xffff
328 #define GTK_BLUE                0x4b4b, 0x6969, 0x8383
329 #define GTK_VERY_DARK_GRAY      0x9c9c, 0x9a9a, 0x9494
330 #define GTK_BLACK               0x0000, 0x0000, 0x0000
331 #define GTK_WEAK_GRAY           0x7530, 0x7530, 0x7530
332
333 /* --- variables --- */
334 static const GdkColor gtk_default_normal_fg =      { 0, GTK_BLACK };
335 static const GdkColor gtk_default_active_fg =      { 0, GTK_BLACK };
336 static const GdkColor gtk_default_prelight_fg =    { 0, GTK_BLACK };
337 static const GdkColor gtk_default_selected_fg =    { 0, GTK_WHITE };
338 static const GdkColor gtk_default_insensitive_fg = { 0, GTK_WEAK_GRAY };
339
340 static const GdkColor gtk_default_normal_bg =      { 0, GTK_GRAY };
341 static const GdkColor gtk_default_active_bg =      { 0, GTK_DARK_GRAY };
342 static const GdkColor gtk_default_prelight_bg =    { 0, GTK_LIGHT_GRAY };
343 static const GdkColor gtk_default_selected_bg =    { 0, GTK_BLUE };
344 static const GdkColor gtk_default_insensitive_bg = { 0, GTK_GRAY };
345 static const GdkColor gtk_default_selected_base =  { 0, GTK_BLUE };
346 static const GdkColor gtk_default_active_base =    { 0, GTK_VERY_DARK_GRAY };
347
348 /* --- signals --- */
349 static guint realize_signal = 0;
350 static guint unrealize_signal = 0;
351
352 G_DEFINE_TYPE (GtkStyle, gtk_style, G_TYPE_OBJECT)
353
354 /* --- functions --- */
355
356 /**
357  * _gtk_style_init_for_settings:
358  * @style: a #GtkStyle
359  * @settings: a #GtkSettings
360  * 
361  * Initializes the font description in @style according to the default
362  * font name of @settings. This is called for gtk_style_new() with
363  * the settings for the default screen (if any); if we are creating
364  * a style for a particular screen, we then call it again in a
365  * location where we know the correct settings.
366  * The reason for this is that gtk_rc_style_create_style() doesn't
367  * take the screen for an argument.
368  **/
369 void
370 _gtk_style_init_for_settings (GtkStyle    *style,
371                               GtkSettings *settings)
372 {
373   const gchar *font_name = _gtk_rc_context_get_default_font_name (settings);
374
375   if (style->font_desc)
376     pango_font_description_free (style->font_desc);
377   
378   style->font_desc = pango_font_description_from_string (font_name);
379       
380   if (!pango_font_description_get_family (style->font_desc))
381     {
382       g_warning ("Default font does not have a family set");
383       pango_font_description_set_family (style->font_desc, "Sans");
384     }
385   if (pango_font_description_get_size (style->font_desc) <= 0)
386     {
387       g_warning ("Default font does not have a positive size");
388       pango_font_description_set_size (style->font_desc, 10 * PANGO_SCALE);
389     }
390 }
391
392 static void
393 gtk_style_init (GtkStyle *style)
394 {
395   gint i;
396   
397   GtkSettings *settings = gtk_settings_get_default ();
398   
399   if (settings)
400     _gtk_style_init_for_settings (style, settings);
401   else
402     style->font_desc = pango_font_description_from_string ("Sans 10");
403   
404   style->attach_count = 0;
405   
406   style->black.red = 0;
407   style->black.green = 0;
408   style->black.blue = 0;
409   
410   style->white.red = 65535;
411   style->white.green = 65535;
412   style->white.blue = 65535;
413   
414   style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
415   style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
416   style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
417   style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
418   style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
419   
420   style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
421   style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
422   style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
423   style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
424   style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
425   
426   for (i = 0; i < 4; i++)
427     {
428       style->text[i] = style->fg[i];
429       style->base[i] = style->white;
430     }
431
432   style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
433   style->text[GTK_STATE_SELECTED] = style->white;
434   style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
435   style->text[GTK_STATE_ACTIVE] = style->white;
436   style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
437   style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
438   
439   style->rc_style = NULL;
440   
441   style->xthickness = 2;
442   style->ythickness = 2;
443
444   style->property_cache = NULL;
445 }
446
447 static void
448 gtk_style_class_init (GtkStyleClass *klass)
449 {
450   GObjectClass *object_class = G_OBJECT_CLASS (klass);
451   
452   object_class->finalize = gtk_style_finalize;
453
454   klass->clone = gtk_style_real_clone;
455   klass->copy = gtk_style_real_copy;
456   klass->init_from_rc = gtk_style_real_init_from_rc;
457   klass->realize = gtk_style_real_realize;
458   klass->unrealize = gtk_style_real_unrealize;
459   klass->set_background = gtk_style_real_set_background;
460   klass->render_icon = gtk_default_render_icon;
461
462   klass->draw_hline = gtk_default_draw_hline;
463   klass->draw_vline = gtk_default_draw_vline;
464   klass->draw_shadow = gtk_default_draw_shadow;
465   klass->draw_arrow = gtk_default_draw_arrow;
466   klass->draw_diamond = gtk_default_draw_diamond;
467   klass->draw_box = gtk_default_draw_box;
468   klass->draw_flat_box = gtk_default_draw_flat_box;
469   klass->draw_check = gtk_default_draw_check;
470   klass->draw_option = gtk_default_draw_option;
471   klass->draw_tab = gtk_default_draw_tab;
472   klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
473   klass->draw_box_gap = gtk_default_draw_box_gap;
474   klass->draw_extension = gtk_default_draw_extension;
475   klass->draw_focus = gtk_default_draw_focus;
476   klass->draw_slider = gtk_default_draw_slider;
477   klass->draw_handle = gtk_default_draw_handle;
478   klass->draw_expander = gtk_default_draw_expander;
479   klass->draw_layout = gtk_default_draw_layout;
480   klass->draw_resize_grip = gtk_default_draw_resize_grip;
481   klass->draw_spinner = gtk_default_draw_spinner;
482
483   g_type_class_add_private (object_class, sizeof (GtkStylePrivate));
484
485   /**
486    * GtkStyle::realize:
487    * @style: the object which received the signal
488    *
489    * Emitted when the style has been initialized for a particular
490    * visual. Connecting to this signal is probably seldom
491    * useful since most of the time applications and widgets only
492    * deal with styles that have been already realized.
493    *
494    * Since: 2.4
495    */
496   realize_signal = g_signal_new (I_("realize"),
497                                  G_TYPE_FROM_CLASS (object_class),
498                                  G_SIGNAL_RUN_FIRST,
499                                  G_STRUCT_OFFSET (GtkStyleClass, realize),
500                                  NULL, NULL,
501                                  _gtk_marshal_VOID__VOID,
502                                  G_TYPE_NONE, 0);
503   /**
504    * GtkStyle::unrealize:
505    * @style: the object which received the signal
506    *
507    * Emitted when the aspects of the style specific to a particular visual
508    * is being cleaned up. A connection to this signal can be useful
509    * if a widget wants to cache objects as object data on #GtkStyle.
510    * This signal provides a convenient place to free such cached objects.
511    *
512    * Since: 2.4
513    */
514   unrealize_signal = g_signal_new (I_("unrealize"),
515                                    G_TYPE_FROM_CLASS (object_class),
516                                    G_SIGNAL_RUN_FIRST,
517                                    G_STRUCT_OFFSET (GtkStyleClass, unrealize),
518                                    NULL, NULL,
519                                    _gtk_marshal_VOID__VOID,
520                                    G_TYPE_NONE, 0);
521 }
522
523 static void
524 clear_property_cache (GtkStyle *style)
525 {
526   if (style->property_cache)
527     {
528       guint i;
529
530       for (i = 0; i < style->property_cache->len; i++)
531         {
532           PropertyValue *node = &g_array_index (style->property_cache, PropertyValue, i);
533
534           g_param_spec_unref (node->pspec);
535           g_value_unset (&node->value);
536         }
537       g_array_free (style->property_cache, TRUE);
538       style->property_cache = NULL;
539     }
540 }
541
542 static void
543 gtk_style_finalize (GObject *object)
544 {
545   GtkStyle *style = GTK_STYLE (object);
546   GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
547
548   g_return_if_fail (style->attach_count == 0);
549
550   clear_property_cache (style);
551   
552   /* All the styles in the list have the same 
553    * style->styles pointer. If we delete the 
554    * *first* style from the list, we need to update
555    * the style->styles pointers from all the styles.
556    * Otherwise we simply remove the node from
557    * the list.
558    */
559   if (style->styles)
560     {
561       if (style->styles->data != style)
562         style->styles = g_slist_remove (style->styles, style);
563       else
564         {
565           GSList *tmp_list = style->styles->next;
566           
567           while (tmp_list)
568             {
569               GTK_STYLE (tmp_list->data)->styles = style->styles->next;
570               tmp_list = tmp_list->next;
571             }
572           g_slist_free_1 (style->styles);
573         }
574     }
575
576   g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
577   g_slist_free (style->icon_factories);
578
579   g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
580   g_slist_free (priv->color_hashes);
581
582   pango_font_description_free (style->font_desc);
583
584   if (style->private_font_desc)
585     pango_font_description_free (style->private_font_desc);
586
587   if (style->rc_style)
588     g_object_unref (style->rc_style);
589
590   G_OBJECT_CLASS (gtk_style_parent_class)->finalize (object);
591 }
592
593
594 /**
595  * gtk_style_copy:
596  * @style: a #GtkStyle
597  *
598  * Creates a copy of the passed in #GtkStyle object.
599  *
600  * Returns: (transfer full): a copy of @style
601  */
602 GtkStyle*
603 gtk_style_copy (GtkStyle *style)
604 {
605   GtkStyle *new_style;
606   
607   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
608   
609   new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
610   GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
611
612   return new_style;
613 }
614
615 static GtkStyle*
616 gtk_style_duplicate (GtkStyle *style)
617 {
618   GtkStyle *new_style;
619   
620   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
621   
622   new_style = gtk_style_copy (style);
623   
624   /* All the styles in the list have the same 
625    * style->styles pointer. When we insert a new 
626    * style, we append it to the list to avoid having 
627    * to update the existing ones. 
628    */
629   style->styles = g_slist_append (style->styles, new_style);
630   new_style->styles = style->styles;  
631   
632   return new_style;
633 }
634
635 /**
636  * gtk_style_new:
637  * @returns: a new #GtkStyle.
638  *
639  * Creates a new #GtkStyle.
640  **/
641 GtkStyle*
642 gtk_style_new (void)
643 {
644   GtkStyle *style;
645   
646   style = g_object_new (GTK_TYPE_STYLE, NULL);
647   
648   return style;
649 }
650
651 /**
652  * gtk_style_attach:
653  * @style: a #GtkStyle.
654  * @window: a #GdkWindow.
655  *
656  * Attaches a style to a window; this process allocates the
657  * colors and creates the GC's for the style - it specializes
658  * it to a particular visual. The process may involve the creation
659  * of a new style if the style has already been attached to a
660  * window with a different style and visual.
661  *
662  * Since this function may return a new object, you have to use it
663  * in the following way:
664  * <literal>style = gtk_style_attach (style, window)</literal>
665  *
666  * Returns: Either @style, or a newly-created #GtkStyle.
667  *   If the style is newly created, the style parameter
668  *   will be unref'ed, and the new style will have
669  *   a reference count belonging to the caller.
670  */
671 GtkStyle*
672 gtk_style_attach (GtkStyle  *style,
673                   GdkWindow *window)
674 {
675   GSList *styles;
676   GtkStyle *new_style = NULL;
677   GdkVisual *visual;
678   
679   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
680   g_return_val_if_fail (window != NULL, NULL);
681   
682   visual = gdk_window_get_visual (window);
683   
684   if (!style->styles)
685     style->styles = g_slist_append (NULL, style);
686   
687   styles = style->styles;
688   while (styles)
689     {
690       new_style = styles->data;
691       
692       if (new_style->visual == visual)
693         break;
694
695       new_style = NULL;
696       styles = styles->next;
697     }
698
699   if (!new_style)
700     {
701       styles = style->styles;
702       
703       while (styles)
704         {
705           new_style = styles->data;
706           
707           if (new_style->attach_count == 0)
708             {
709               gtk_style_realize (new_style, visual);
710               break;
711             }
712           
713           new_style = NULL;
714           styles = styles->next;
715         }
716     }
717   
718   if (!new_style)
719     {
720       new_style = gtk_style_duplicate (style);
721       gtk_style_realize (new_style, visual);
722     }
723
724   /* A style gets a refcount from being attached */
725   if (new_style->attach_count == 0)
726     g_object_ref (new_style);
727
728   /* Another refcount belongs to the parent */
729   if (style != new_style) 
730     {
731       g_object_unref (style);
732       g_object_ref (new_style);
733     }
734   
735   new_style->attach_count++;
736   
737   return new_style;
738 }
739
740 /**
741  * gtk_style_detach:
742  * @style: a #GtkStyle
743  *
744  * Detaches a style from a window. If the style is not attached
745  * to any windows anymore, it is unrealized. See gtk_style_attach().
746  * 
747  */
748 void
749 gtk_style_detach (GtkStyle *style)
750 {
751   g_return_if_fail (GTK_IS_STYLE (style));
752   g_return_if_fail (style->attach_count > 0);
753   
754   style->attach_count -= 1;
755   if (style->attach_count == 0)
756     {
757       g_signal_emit (style, unrealize_signal, 0);
758       
759       g_object_unref (style->visual);
760       style->visual = NULL;
761
762       if (style->private_font_desc)
763         {
764           pango_font_description_free (style->private_font_desc);
765           style->private_font_desc = NULL;
766         }
767
768       g_object_unref (style);
769     }
770 }
771
772 static void
773 gtk_style_realize (GtkStyle  *style,
774                    GdkVisual *visual)
775 {
776   style->visual = g_object_ref (visual);
777
778   g_signal_emit (style, realize_signal, 0);
779 }
780
781 /**
782  * gtk_style_lookup_icon_set:
783  * @style: a #GtkStyle
784  * @stock_id: an icon name
785  *
786  * Looks up @stock_id in the icon factories associated with @style
787  * and the default icon factory, returning an icon set if found,
788  * otherwise %NULL.
789  *
790  * Return value: icon set of @stock_id
791  */
792 GtkIconSet*
793 gtk_style_lookup_icon_set (GtkStyle   *style,
794                            const char *stock_id)
795 {
796   GSList *iter;
797
798   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
799   g_return_val_if_fail (stock_id != NULL, NULL);
800   
801   iter = style->icon_factories;
802   while (iter != NULL)
803     {
804       GtkIconSet *icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
805                                                       stock_id);
806       if (icon_set)
807         return icon_set;
808       
809       iter = g_slist_next (iter);
810     }
811
812   return gtk_icon_factory_lookup_default (stock_id);
813 }
814
815 /**
816  * gtk_style_lookup_color:
817  * @style: a #GtkStyle
818  * @color_name: the name of the logical color to look up
819  * @color: the #GdkColor to fill in
820  *
821  * Looks up @color_name in the style's logical color mappings,
822  * filling in @color and returning %TRUE if found, otherwise
823  * returning %FALSE. Do not cache the found mapping, because
824  * it depends on the #GtkStyle and might change when a theme
825  * switch occurs.
826  *
827  * Return value: %TRUE if the mapping was found.
828  *
829  * Since: 2.10
830  **/
831 gboolean
832 gtk_style_lookup_color (GtkStyle   *style,
833                         const char *color_name,
834                         GdkColor   *color)
835 {
836   GtkStylePrivate *priv;
837   GSList *iter;
838
839   g_return_val_if_fail (GTK_IS_STYLE (style), FALSE);
840   g_return_val_if_fail (color_name != NULL, FALSE);
841   g_return_val_if_fail (color != NULL, FALSE);
842
843   priv = GTK_STYLE_GET_PRIVATE (style);
844
845   for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
846     {
847       GHashTable *hash    = iter->data;
848       GdkColor   *mapping = g_hash_table_lookup (hash, color_name);
849
850       if (mapping)
851         {
852           color->red = mapping->red;
853           color->green = mapping->green;
854           color->blue = mapping->blue;
855           return TRUE;
856         }
857     }
858
859   return FALSE;
860 }
861
862 /**
863  * gtk_style_set_background:
864  * @style: a #GtkStyle
865  * @window: a #GdkWindow
866  * @state_type: a state
867  * 
868  * Sets the background of @window to the background color or pixmap
869  * specified by @style for the given state.
870  */
871 void
872 gtk_style_set_background (GtkStyle    *style,
873                           GdkWindow   *window,
874                           GtkStateType state_type)
875 {
876   g_return_if_fail (GTK_IS_STYLE (style));
877   g_return_if_fail (window != NULL);
878   
879   GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
880 }
881
882 /* Default functions */
883 static GtkStyle *
884 gtk_style_real_clone (GtkStyle *style)
885 {
886   return g_object_new (G_OBJECT_TYPE (style), NULL);
887 }
888
889 static void
890 gtk_style_real_copy (GtkStyle *style,
891                      GtkStyle *src)
892 {
893   GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
894   GtkStylePrivate *src_priv = GTK_STYLE_GET_PRIVATE (src);
895   gint i;
896   
897   for (i = 0; i < 5; i++)
898     {
899       style->fg[i] = src->fg[i];
900       style->bg[i] = src->bg[i];
901       style->text[i] = src->text[i];
902       style->base[i] = src->base[i];
903
904       if (style->background[i])
905         cairo_pattern_destroy (style->background[i]),
906       style->background[i] = src->background[i];
907       if (style->background[i])
908         cairo_pattern_reference (style->background[i]);
909     }
910
911   if (style->font_desc)
912     pango_font_description_free (style->font_desc);
913   if (src->font_desc)
914     style->font_desc = pango_font_description_copy (src->font_desc);
915   else
916     style->font_desc = NULL;
917   
918   style->xthickness = src->xthickness;
919   style->ythickness = src->ythickness;
920
921   if (style->rc_style)
922     g_object_unref (style->rc_style);
923   style->rc_style = src->rc_style;
924   if (src->rc_style)
925     g_object_ref (src->rc_style);
926
927   g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
928   g_slist_free (style->icon_factories);
929   style->icon_factories = g_slist_copy (src->icon_factories);
930   g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
931
932   g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
933   g_slist_free (priv->color_hashes);
934   priv->color_hashes = g_slist_copy (src_priv->color_hashes);
935   g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
936
937   /* don't copy, just clear cache */
938   clear_property_cache (style);
939 }
940
941 static void
942 gtk_style_real_init_from_rc (GtkStyle   *style,
943                              GtkRcStyle *rc_style)
944 {
945   GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
946   gint i;
947
948   /* cache _should_ be still empty */
949   clear_property_cache (style);
950
951   if (rc_style->font_desc)
952     pango_font_description_merge (style->font_desc, rc_style->font_desc, TRUE);
953     
954   for (i = 0; i < 5; i++)
955     {
956       if (rc_style->color_flags[i] & GTK_RC_FG)
957         style->fg[i] = rc_style->fg[i];
958       if (rc_style->color_flags[i] & GTK_RC_BG)
959         style->bg[i] = rc_style->bg[i];
960       if (rc_style->color_flags[i] & GTK_RC_TEXT)
961         style->text[i] = rc_style->text[i];
962       if (rc_style->color_flags[i] & GTK_RC_BASE)
963         style->base[i] = rc_style->base[i];
964     }
965
966   if (rc_style->xthickness >= 0)
967     style->xthickness = rc_style->xthickness;
968   if (rc_style->ythickness >= 0)
969     style->ythickness = rc_style->ythickness;
970
971   style->icon_factories = g_slist_copy (rc_style->icon_factories);
972   g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
973
974   priv->color_hashes = g_slist_copy (_gtk_rc_style_get_color_hashes (rc_style));
975   g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
976 }
977
978 static gint
979 style_property_values_cmp (gconstpointer bsearch_node1,
980                            gconstpointer bsearch_node2)
981 {
982   const PropertyValue *val1 = bsearch_node1;
983   const PropertyValue *val2 = bsearch_node2;
984
985   if (val1->widget_type == val2->widget_type)
986     return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
987   else
988     return val1->widget_type < val2->widget_type ? -1 : 1;
989 }
990
991 /**
992  * gtk_style_get_style_property:
993  * @style: a #GtkStyle
994  * @widget_type: the #GType of a descendant of #GtkWidget
995  * @property_name: the name of the style property to get
996  * @value: a #GValue where the value of the property being
997  *     queried will be stored
998  *
999  * Queries the value of a style property corresponding to a
1000  * widget class is in the given style.
1001  *
1002  * Since: 2.16
1003  */
1004 void 
1005 gtk_style_get_style_property (GtkStyle     *style,
1006                               GType        widget_type,
1007                               const gchar *property_name,
1008                               GValue      *value)
1009 {
1010   GtkWidgetClass *klass;
1011   GParamSpec *pspec;
1012   GtkRcPropertyParser parser;
1013   const GValue *peek_value;
1014
1015   klass = g_type_class_ref (widget_type);
1016   pspec = gtk_widget_class_find_style_property (klass, property_name);
1017   g_type_class_unref (klass);
1018
1019   if (!pspec)
1020     {
1021       g_warning ("%s: widget class `%s' has no property named `%s'",
1022                  G_STRLOC,
1023                  g_type_name (widget_type),
1024                  property_name);
1025       return;
1026     }
1027
1028   parser = g_param_spec_get_qdata (pspec,
1029                                    g_quark_from_static_string ("gtk-rc-property-parser"));
1030
1031   peek_value = _gtk_style_peek_property_value (style, widget_type, pspec, parser);
1032
1033   if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
1034     g_value_copy (peek_value, value);
1035   else if (g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
1036     g_value_transform (peek_value, value);
1037   else
1038     g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
1039                pspec->name,
1040                g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1041                G_VALUE_TYPE_NAME (value));
1042 }
1043
1044 /**
1045  * gtk_style_get_valist:
1046  * @style: a #GtkStyle
1047  * @widget_type: the #GType of a descendant of #GtkWidget
1048  * @first_property_name: the name of the first style property to get
1049  * @var_args: a <type>va_list</type> of pairs of property names and
1050  *     locations to return the property values, starting with the
1051  *     location for @first_property_name.
1052  *
1053  * Non-vararg variant of gtk_style_get().
1054  * Used primarily by language bindings.
1055  *
1056  * Since: 2.16
1057  */
1058 void 
1059 gtk_style_get_valist (GtkStyle    *style,
1060                       GType        widget_type,
1061                       const gchar *first_property_name,
1062                       va_list      var_args)
1063 {
1064   const char *property_name;
1065   GtkWidgetClass *klass;
1066
1067   g_return_if_fail (GTK_IS_STYLE (style));
1068
1069   klass = g_type_class_ref (widget_type);
1070
1071   property_name = first_property_name;
1072   while (property_name)
1073     {
1074       GParamSpec *pspec;
1075       GtkRcPropertyParser parser;
1076       const GValue *peek_value;
1077       gchar *error;
1078
1079       pspec = gtk_widget_class_find_style_property (klass, property_name);
1080
1081       if (!pspec)
1082         {
1083           g_warning ("%s: widget class `%s' has no property named `%s'",
1084                      G_STRLOC,
1085                      g_type_name (widget_type),
1086                      property_name);
1087           break;
1088         }
1089
1090       parser = g_param_spec_get_qdata (pspec,
1091                                        g_quark_from_static_string ("gtk-rc-property-parser"));
1092
1093       peek_value = _gtk_style_peek_property_value (style, widget_type, pspec, parser);
1094       G_VALUE_LCOPY (peek_value, var_args, 0, &error);
1095       if (error)
1096         {
1097           g_warning ("%s: %s", G_STRLOC, error);
1098           g_free (error);
1099           break;
1100         }
1101
1102       property_name = va_arg (var_args, gchar*);
1103     }
1104
1105   g_type_class_unref (klass);
1106 }
1107
1108 /**
1109  * gtk_style_get:
1110  * @style: a #GtkStyle
1111  * @widget_type: the #GType of a descendant of #GtkWidget
1112  * @first_property_name: the name of the first style property to get
1113  * @Varargs: pairs of property names and locations to
1114  *   return the property values, starting with the location for
1115  *   @first_property_name, terminated by %NULL.
1116  *
1117  * Gets the values of a multiple style properties for @widget_type
1118  * from @style.
1119  *
1120  * Since: 2.16
1121  */
1122 void
1123 gtk_style_get (GtkStyle    *style,
1124                GType        widget_type,
1125                const gchar *first_property_name,
1126                ...)
1127 {
1128   va_list var_args;
1129
1130   va_start (var_args, first_property_name);
1131   gtk_style_get_valist (style, widget_type, first_property_name, var_args);
1132   va_end (var_args);
1133 }
1134
1135 const GValue*
1136 _gtk_style_peek_property_value (GtkStyle           *style,
1137                                 GType               widget_type,
1138                                 GParamSpec         *pspec,
1139                                 GtkRcPropertyParser parser)
1140 {
1141   PropertyValue *pcache, key = { 0, NULL, { 0, } };
1142   const GtkRcProperty *rcprop = NULL;
1143   guint i;
1144
1145   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1146   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1147   g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1148   g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1149
1150   key.widget_type = widget_type;
1151   key.pspec = pspec;
1152
1153   /* need value cache array */
1154   if (!style->property_cache)
1155     style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1156   else
1157     {
1158       pcache = bsearch (&key,
1159                         style->property_cache->data, style->property_cache->len,
1160                         sizeof (PropertyValue), style_property_values_cmp);
1161       if (pcache)
1162         return &pcache->value;
1163     }
1164
1165   i = 0;
1166   while (i < style->property_cache->len &&
1167          style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1168     i++;
1169
1170   g_array_insert_val (style->property_cache, i, key);
1171   pcache = &g_array_index (style->property_cache, PropertyValue, i);
1172
1173   /* cache miss, initialize value type, then set contents */
1174   g_param_spec_ref (pcache->pspec);
1175   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1176
1177   /* value provided by rc style? */
1178   if (style->rc_style)
1179     {
1180       GQuark prop_quark = g_quark_from_string (pspec->name);
1181
1182       do
1183         {
1184           rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1185                                                      g_type_qname (widget_type),
1186                                                      prop_quark);
1187           if (rcprop)
1188             break;
1189           widget_type = g_type_parent (widget_type);
1190         }
1191       while (g_type_is_a (widget_type, pspec->owner_type));
1192     }
1193
1194   /* when supplied by rc style, we need to convert */
1195   if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1196                                               pspec, &pcache->value))
1197     {
1198       gchar *contents = g_strdup_value_contents (&rcprop->value);
1199       
1200       g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1201                  rcprop->origin ? rcprop->origin : "(for origin information, set GTK_DEBUG)",
1202                  g_type_name (pspec->owner_type), pspec->name,
1203                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1204                  contents,
1205                  G_VALUE_TYPE_NAME (&rcprop->value));
1206       g_free (contents);
1207       rcprop = NULL; /* needs default */
1208     }
1209   
1210   /* not supplied by rc style (or conversion failed), revert to default */
1211   if (!rcprop)
1212     g_param_value_set_default (pspec, &pcache->value);
1213
1214   return &pcache->value;
1215 }
1216
1217 static cairo_pattern_t *
1218 load_background (GdkVisual   *visual,
1219                  GdkColor    *bg_color,
1220                  const gchar *filename)
1221 {
1222   if (filename == NULL)
1223     {
1224       return cairo_pattern_create_rgb (bg_color->red   / 65535.0,
1225                                        bg_color->green / 65535.0,
1226                                        bg_color->blue  / 65535.0);
1227     }
1228   if (strcmp (filename, "<parent>") == 0)
1229     return NULL;
1230   else
1231     {
1232       GdkPixbuf *pixbuf;
1233       cairo_surface_t *surface;
1234       cairo_pattern_t *pattern;
1235       cairo_t *cr;
1236       GdkScreen *screen = gdk_visual_get_screen (visual);
1237   
1238       pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1239       if (!pixbuf)
1240         return NULL;
1241
1242       surface = gdk_window_create_similar_surface (gdk_screen_get_root_window (screen),
1243                                                    CAIRO_CONTENT_COLOR,
1244                                                    gdk_pixbuf_get_width (pixbuf),
1245                                                    gdk_pixbuf_get_height (pixbuf));
1246   
1247       cr = cairo_create (surface);
1248
1249       gdk_cairo_set_source_color (cr, bg_color);
1250       cairo_paint (cr);
1251
1252       gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
1253       cairo_paint (cr);
1254
1255       cairo_destroy (cr);
1256       g_object_unref (pixbuf);
1257
1258       pattern = cairo_pattern_create_for_surface (surface);
1259
1260       cairo_surface_destroy (surface);
1261
1262       return pattern;
1263     }
1264 }
1265
1266 static void
1267 gtk_style_real_realize (GtkStyle *style)
1268 {
1269   gint i;
1270
1271   for (i = 0; i < 5; i++)
1272     {
1273       _gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1274       _gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1275
1276       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1277       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1278       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1279
1280       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1281       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1282       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1283     }
1284
1285   style->black.red = 0x0000;
1286   style->black.green = 0x0000;
1287   style->black.blue = 0x0000;
1288
1289   style->white.red = 0xffff;
1290   style->white.green = 0xffff;
1291   style->white.blue = 0xffff;
1292
1293   for (i = 0; i < 5; i++)
1294     {
1295       const char *image_name;
1296
1297       if (style->rc_style)
1298         image_name = style->rc_style->bg_pixmap_name[i];
1299       else
1300         image_name = NULL;
1301
1302       style->background[i] = load_background (style->visual,
1303                                               &style->bg[i],
1304                                               image_name);
1305     }
1306 }
1307
1308 static void
1309 gtk_style_real_unrealize (GtkStyle *style)
1310 {
1311   int i;
1312
1313   for (i = 0; i < 5; i++)
1314     {
1315       if (style->background[i])
1316         {
1317           cairo_pattern_destroy (style->background[i]);
1318           style->background[i] = NULL;
1319         }
1320       
1321     }
1322   
1323   style_unrealize_cursors (style);
1324 }
1325
1326 static void
1327 gtk_style_real_set_background (GtkStyle    *style,
1328                                GdkWindow   *window,
1329                                GtkStateType state_type)
1330 {
1331   gdk_window_set_background_pattern (window, style->background[state_type]);
1332 }
1333
1334 /**
1335  * gtk_style_render_icon:
1336  * @style: a #GtkStyle
1337  * @source: the #GtkIconSource specifying the icon to render
1338  * @direction: a text direction
1339  * @state: a state
1340  * @size: (type int): the size to render the icon at. A size of
1341  *     (GtkIconSize)-1 means render at the size of the source and
1342  *     don't scale.
1343  * @widget: (allow-none): the widget
1344  * @detail: (allow-none): a style detail
1345  *
1346  * Renders the icon specified by @source at the given @size
1347  * according to the given parameters and returns the result in a
1348  * pixbuf.
1349  *
1350  * Return value: (transfer full): a newly-created #GdkPixbuf
1351  *     containing the rendered icon
1352  */
1353 GdkPixbuf *
1354 gtk_style_render_icon (GtkStyle            *style,
1355                        const GtkIconSource *source,
1356                        GtkTextDirection     direction,
1357                        GtkStateType         state,
1358                        GtkIconSize          size,
1359                        GtkWidget           *widget,
1360                        const gchar         *detail)
1361 {
1362   GdkPixbuf *pixbuf;
1363   
1364   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1365   g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1366   
1367   pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1368                                                      size, widget, detail);
1369
1370   g_return_val_if_fail (pixbuf != NULL, NULL);
1371
1372   return pixbuf;
1373 }
1374
1375 /* Default functions */
1376
1377 /**
1378  * gtk_style_apply_default_background:
1379  * @style:
1380  * @cr: 
1381  * @window:
1382  * @set_bg:
1383  * @state_type:
1384  * @area: (allow-none):
1385  * @x:
1386  * @y:
1387  * @width:
1388  * @height:
1389  */
1390 void
1391 gtk_style_apply_default_background (GtkStyle          *style,
1392                                     cairo_t           *cr,
1393                                     GdkWindow         *window,
1394                                     GtkStateType       state_type,
1395                                     gint               x,
1396                                     gint               y,
1397                                     gint               width,
1398                                     gint               height)
1399 {
1400   cairo_save (cr);
1401
1402   if (style->background[state_type] == NULL)
1403     {
1404       GdkWindow *parent = gdk_window_get_parent (window);
1405       int x_offset, y_offset;
1406
1407       if (parent)
1408         {
1409           gdk_window_get_position (window, &x_offset, &y_offset);
1410           cairo_translate (cr, -x_offset, -y_offset);
1411           gtk_style_apply_default_background (style, cr,
1412                                               parent, state_type,
1413                                               x + x_offset, y + y_offset,
1414                                               width, height);
1415           goto out;
1416         }
1417       else
1418         gdk_cairo_set_source_color (cr, &style->bg[state_type]);
1419     }
1420   else
1421     cairo_set_source (cr, style->background[state_type]);
1422
1423   cairo_rectangle (cr, x, y, width, height);
1424   cairo_fill (cr);
1425
1426 out:
1427   cairo_restore (cr);
1428 }
1429
1430 static GdkPixbuf *
1431 scale_or_ref (GdkPixbuf *src,
1432               gint       width,
1433               gint       height)
1434 {
1435   if (width == gdk_pixbuf_get_width (src) &&
1436       height == gdk_pixbuf_get_height (src))
1437     {
1438       return g_object_ref (src);
1439     }
1440   else
1441     {
1442       return gdk_pixbuf_scale_simple (src,
1443                                       width, height,
1444                                       GDK_INTERP_BILINEAR);
1445     }
1446 }
1447
1448 static gboolean
1449 lookup_icon_size (GtkStyle    *style,
1450                   GtkWidget   *widget,
1451                   GtkIconSize  size,
1452                   gint        *width,
1453                   gint        *height)
1454 {
1455   GdkScreen *screen;
1456   GtkSettings *settings;
1457
1458   if (widget && gtk_widget_has_screen (widget))
1459     {
1460       screen = gtk_widget_get_screen (widget);
1461       settings = gtk_settings_get_for_screen (screen);
1462     }
1463   else if (style && style->visual)
1464     {
1465       screen = gdk_visual_get_screen (style->visual);
1466       settings = gtk_settings_get_for_screen (screen);
1467     }
1468   else
1469     {
1470       settings = gtk_settings_get_default ();
1471       GTK_NOTE (MULTIHEAD,
1472                 g_warning ("Using the default screen for gtk_default_render_icon()"));
1473     }
1474
1475   return gtk_icon_size_lookup_for_settings (settings, size, width, height);
1476 }
1477
1478 static GdkPixbuf *
1479 gtk_default_render_icon (GtkStyle            *style,
1480                          const GtkIconSource *source,
1481                          GtkTextDirection     direction,
1482                          GtkStateType         state,
1483                          GtkIconSize          size,
1484                          GtkWidget           *widget,
1485                          const gchar         *detail)
1486 {
1487   gint width = 1;
1488   gint height = 1;
1489   GdkPixbuf *scaled;
1490   GdkPixbuf *stated;
1491   GdkPixbuf *base_pixbuf;
1492
1493   /* Oddly, style can be NULL in this function, because
1494    * GtkIconSet can be used without a style and if so
1495    * it uses this function.
1496    */
1497
1498   base_pixbuf = gtk_icon_source_get_pixbuf (source);
1499
1500   g_return_val_if_fail (base_pixbuf != NULL, NULL);
1501
1502   if (size != (GtkIconSize) -1 && !lookup_icon_size(style, widget, size, &width, &height))
1503     {
1504       g_warning (G_STRLOC ": invalid icon size '%d'", size);
1505       return NULL;
1506     }
1507
1508   /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
1509    * leave it alone.
1510    */
1511   if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))
1512     scaled = scale_or_ref (base_pixbuf, width, height);
1513   else
1514     scaled = g_object_ref (base_pixbuf);
1515
1516   /* If the state was wildcarded, then generate a state. */
1517   if (gtk_icon_source_get_state_wildcarded (source))
1518     {
1519       if (state == GTK_STATE_INSENSITIVE)
1520         {
1521           stated = gdk_pixbuf_copy (scaled);      
1522           
1523           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1524                                             0.8, TRUE);
1525           
1526           g_object_unref (scaled);
1527         }
1528       else if (state == GTK_STATE_PRELIGHT)
1529         {
1530           stated = gdk_pixbuf_copy (scaled);      
1531           
1532           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1533                                             1.2, FALSE);
1534           
1535           g_object_unref (scaled);
1536         }
1537       else
1538         {
1539           stated = scaled;
1540         }
1541     }
1542   else
1543     stated = scaled;
1544   
1545   return stated;
1546 }
1547
1548 static void
1549 _cairo_draw_line (cairo_t  *cr,
1550                   GdkColor *color,
1551                   gint      x1,
1552                   gint      y1,
1553                   gint      x2,
1554                   gint      y2)
1555 {
1556   cairo_save (cr);
1557
1558   gdk_cairo_set_source_color (cr, color);
1559   cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
1560
1561   cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
1562   cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
1563   cairo_stroke (cr);
1564
1565   cairo_restore (cr);
1566 }
1567
1568 static void
1569 _cairo_draw_rectangle (cairo_t *cr,
1570                        GdkColor *color,
1571                        gboolean filled,
1572                        gint x,
1573                        gint y,
1574                        gint width,
1575                        gint height)
1576 {
1577   gdk_cairo_set_source_color (cr, color);
1578
1579   if (filled)
1580     {
1581       cairo_rectangle (cr, x, y, width, height);
1582       cairo_fill (cr);
1583     }
1584   else
1585     {
1586       cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
1587       cairo_stroke (cr);
1588     }
1589 }
1590
1591 static void
1592 _cairo_draw_point (cairo_t *cr,
1593                    GdkColor *color,
1594                    gint x,
1595                    gint y)
1596 {
1597   gdk_cairo_set_source_color (cr, color);
1598   cairo_rectangle (cr, x, y, 1, 1);
1599   cairo_fill (cr);
1600 }
1601
1602 static void
1603 gtk_default_draw_hline (GtkStyle      *style,
1604                         cairo_t       *cr,
1605                         GtkStateType  state_type,
1606                         GtkWidget     *widget,
1607                         const gchar   *detail,
1608                         gint          x1,
1609                         gint          x2,
1610                         gint          y)
1611 {
1612   gint thickness_light;
1613   gint thickness_dark;
1614   gint i;
1615   
1616   thickness_light = style->ythickness / 2;
1617   thickness_dark = style->ythickness - thickness_light;
1618   
1619   cairo_set_line_width (cr, 1.0);
1620
1621   if (detail && !strcmp (detail, "label"))
1622     {
1623       if (state_type == GTK_STATE_INSENSITIVE)
1624         _cairo_draw_line (cr, &style->white, x1 + 1, y + 1, x2 + 1, y + 1);
1625       _cairo_draw_line (cr, &style->fg[state_type], x1, y, x2, y);
1626     }
1627   else
1628     {
1629       for (i = 0; i < thickness_dark; i++)
1630         {
1631           _cairo_draw_line (cr, &style->dark[state_type], x1, y + i, x2 - i - 1, y + i);
1632           _cairo_draw_line (cr, &style->light[state_type], x2 - i, y + i, x2, y + i);
1633         }
1634       
1635       y += thickness_dark;
1636       for (i = 0; i < thickness_light; i++)
1637         {
1638           _cairo_draw_line (cr, &style->dark[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
1639           _cairo_draw_line (cr, &style->light[state_type], x1 + thickness_light - i, y + i, x2, y + i);
1640         }
1641     }
1642 }
1643
1644
1645 static void
1646 gtk_default_draw_vline (GtkStyle      *style,
1647                         cairo_t       *cr,
1648                         GtkStateType  state_type,
1649                         GtkWidget     *widget,
1650                         const gchar   *detail,
1651                         gint          y1,
1652                         gint          y2,
1653                         gint          x)
1654 {
1655   gint thickness_light;
1656   gint thickness_dark;
1657   gint i;
1658   
1659   thickness_light = style->xthickness / 2;
1660   thickness_dark = style->xthickness - thickness_light;
1661
1662   cairo_set_line_width (cr, 1.0);
1663
1664   for (i = 0; i < thickness_dark; i++)
1665     { 
1666       _cairo_draw_line (cr, &style->dark[state_type],
1667                         x + i, y1, x + i, y2 - i - 1);
1668       _cairo_draw_line (cr, &style->light[state_type],
1669                         x + i, y2 - i, x + i, y2);
1670     }
1671   
1672   x += thickness_dark;
1673   for (i = 0; i < thickness_light; i++)
1674     {
1675       _cairo_draw_line (cr, &style->dark[state_type],
1676                         x + i, y1, x + i, y1 + thickness_light - i - 1);
1677       _cairo_draw_line (cr, &style->light[state_type],
1678                         x + i, y1 + thickness_light - i, x + i, y2);
1679     }
1680 }
1681
1682 static void
1683 draw_thin_shadow (GtkStyle      *style,
1684                   cairo_t       *cr,
1685                   GtkStateType   state,
1686                   gint           x,
1687                   gint           y,
1688                   gint           width,
1689                   gint           height)
1690 {
1691   GdkColor *gc1, *gc2;
1692
1693   gc1 = &style->light[state];
1694   gc2 = &style->dark[state];
1695
1696   _cairo_draw_line (cr, gc1,
1697                     x, y + height - 1, x + width - 1, y + height - 1);
1698   _cairo_draw_line (cr, gc1,
1699                     x + width - 1, y,  x + width - 1, y + height - 1);
1700       
1701   _cairo_draw_line (cr, gc2,
1702                     x, y, x + width - 2, y);
1703   _cairo_draw_line (cr, gc2,
1704                     x, y, x, y + height - 2);
1705 }
1706
1707 static void
1708 draw_spinbutton_shadow (GtkStyle        *style,
1709                         cairo_t         *cr,
1710                         GtkStateType     state,
1711                         GtkTextDirection direction,
1712                         gint             x,
1713                         gint             y,
1714                         gint             width,
1715                         gint             height)
1716 {
1717
1718   if (direction == GTK_TEXT_DIR_LTR)
1719     {
1720       _cairo_draw_line (cr, &style->dark[state],
1721                         x, y, x + width - 1, y);
1722       _cairo_draw_line (cr, &style->black,
1723                         x, y + 1, x + width - 2, y + 1);
1724       _cairo_draw_line (cr, &style->black,
1725                         x + width - 2, y + 2, x + width - 2, y + height - 3);
1726       _cairo_draw_line (cr, &style->light[state],
1727                         x + width - 1, y + 1, x + width - 1, y + height - 2);
1728       _cairo_draw_line (cr, &style->light[state],
1729                         x, y + height - 1, x + width - 1, y + height - 1);
1730       _cairo_draw_line (cr, &style->bg[state],
1731                         x, y + height - 2, x + width - 2, y + height - 2);
1732       _cairo_draw_line (cr, &style->black,
1733                         x, y + 2, x, y + height - 3);
1734     }
1735   else
1736     {
1737       _cairo_draw_line (cr, &style->dark[state],
1738                         x, y, x + width - 1, y);
1739       _cairo_draw_line (cr, &style->dark[state],
1740                         x, y + 1, x, y + height - 1);
1741       _cairo_draw_line (cr, &style->black,
1742                         x + 1, y + 1, x + width - 1, y + 1);
1743       _cairo_draw_line (cr, &style->black,
1744                         x + 1, y + 2, x + 1, y + height - 2);
1745       _cairo_draw_line (cr, &style->black,
1746                         x + width - 1, y + 2, x + width - 1, y + height - 3);
1747       _cairo_draw_line (cr, &style->light[state],
1748                         x + 1, y + height - 1, x + width - 1, y + height - 1);
1749       _cairo_draw_line (cr, &style->bg[state],
1750                         x + 2, y + height - 2, x + width - 1, y + height - 2);
1751     }
1752 }
1753
1754 static void
1755 draw_menu_shadow (GtkStyle        *style,
1756                   cairo_t         *cr,
1757                   GtkStateType     state,
1758                   gint             x,
1759                   gint             y,
1760                   gint             width,
1761                   gint             height)
1762 {
1763   if (style->ythickness > 0)
1764     {
1765       if (style->ythickness > 1)
1766         {
1767           _cairo_draw_line (cr, &style->dark[state],
1768                             x + 1, y + height - 2,
1769                             x + width - 2, y + height - 2);
1770           _cairo_draw_line (cr, &style->black,
1771                             x, y + height - 1, x + width - 1, y + height - 1);
1772         }
1773       else
1774         {
1775           _cairo_draw_line (cr, &style->dark[state],
1776                             x + 1, y + height - 1, x + width - 1, y + height - 1);
1777         }
1778     }
1779   
1780   if (style->xthickness > 0)
1781     {
1782       if (style->xthickness > 1)
1783         {
1784           _cairo_draw_line (cr, &style->dark[state],
1785                             x + width - 2, y + 1,
1786                             x + width - 2, y + height - 2);
1787
1788           _cairo_draw_line (cr, &style->black,
1789                             x + width - 1, y, x + width - 1, y + height - 1);
1790         }
1791       else
1792         {
1793           _cairo_draw_line (cr, &style->dark[state],
1794                             x + width - 1, y + 1, x + width - 1, y + height - 1);
1795         }
1796     }
1797   
1798   /* Light around top and left */
1799   
1800   if (style->ythickness > 0)
1801     _cairo_draw_line (cr, &style->black,
1802                    x, y, x + width - 2, y);
1803   if (style->xthickness > 0)
1804     _cairo_draw_line (cr, &style->black,
1805                       x, y, x, y + height - 2);
1806   
1807   if (style->ythickness > 1)
1808     _cairo_draw_line (cr, &style->light[state],
1809                       x + 1, y + 1, x + width - 3, y + 1);
1810   if (style->xthickness > 1)
1811     _cairo_draw_line (cr, &style->light[state],
1812                       x + 1, y + 1, x + 1, y + height - 3);
1813 }
1814
1815 static GtkTextDirection
1816 get_direction (GtkWidget *widget)
1817 {
1818   GtkTextDirection dir;
1819   
1820   if (widget)
1821     dir = gtk_widget_get_direction (widget);
1822   else
1823     dir = GTK_TEXT_DIR_LTR;
1824   
1825   return dir;
1826 }
1827
1828
1829 static void
1830 gtk_default_draw_shadow (GtkStyle      *style,
1831                          cairo_t       *cr,
1832                          GtkStateType   state_type,
1833                          GtkShadowType  shadow_type,
1834                          GtkWidget     *widget,
1835                          const gchar   *detail,
1836                          gint           x,
1837                          gint           y,
1838                          gint           width,
1839                          gint           height)
1840 {
1841   GdkColor *gc1 = NULL;
1842   GdkColor *gc2 = NULL;
1843   gint thickness_light;
1844   gint thickness_dark;
1845   gint i;
1846
1847   cairo_set_line_width (cr, 1.0);
1848
1849   if (shadow_type == GTK_SHADOW_IN)
1850     {
1851       if (detail && strcmp (detail, "buttondefault") == 0)
1852         {
1853           _cairo_draw_rectangle (cr, &style->black, FALSE,
1854                                  x, y, width - 1, height - 1);
1855
1856           return;
1857         }
1858       if (detail && strcmp (detail, "trough") == 0)
1859         {
1860           draw_thin_shadow (style, cr, state_type,
1861                             x, y, width, height);
1862
1863           return;
1864         }
1865       if (GTK_IS_SPIN_BUTTON (widget) &&
1866          detail && strcmp (detail, "spinbutton") == 0)
1867         {
1868           draw_spinbutton_shadow (style, cr, state_type, 
1869                                   get_direction (widget), x, y, width, height);
1870           
1871           return;
1872         }
1873     }
1874
1875   if (shadow_type == GTK_SHADOW_OUT && detail && strcmp (detail, "menu") == 0)
1876     {
1877       draw_menu_shadow (style, cr, state_type, x, y, width, height);
1878       return;
1879     }
1880   
1881   switch (shadow_type)
1882     {
1883     case GTK_SHADOW_NONE:
1884       return;
1885     case GTK_SHADOW_IN:
1886     case GTK_SHADOW_ETCHED_IN:
1887       gc1 = &style->light[state_type];
1888       gc2 = &style->dark[state_type];
1889       break;
1890     case GTK_SHADOW_OUT:
1891     case GTK_SHADOW_ETCHED_OUT:
1892       gc1 = &style->dark[state_type];
1893       gc2 = &style->light[state_type];
1894       break;
1895     }
1896   
1897   switch (shadow_type)
1898     {
1899     case GTK_SHADOW_NONE:
1900       break;
1901       
1902     case GTK_SHADOW_IN:
1903       /* Light around right and bottom edge */
1904
1905       if (style->ythickness > 0)
1906         _cairo_draw_line (cr, gc1,
1907                           x, y + height - 1, x + width - 1, y + height - 1);
1908       if (style->xthickness > 0)
1909         _cairo_draw_line (cr, gc1,
1910                           x + width - 1, y, x + width - 1, y + height - 1);
1911
1912       if (style->ythickness > 1)
1913         _cairo_draw_line (cr, &style->bg[state_type],
1914                           x + 1, y + height - 2, x + width - 2, y + height - 2);
1915       if (style->xthickness > 1)
1916         _cairo_draw_line (cr, &style->bg[state_type],
1917                           x + width - 2, y + 1, x + width - 2, y + height - 2);
1918
1919       /* Dark around left and top */
1920
1921       if (style->ythickness > 1)
1922         _cairo_draw_line (cr, &style->black,
1923                           x + 1, y + 1, x + width - 2, y + 1);
1924       if (style->xthickness > 1)
1925         _cairo_draw_line (cr, &style->black,
1926                           x + 1, y + 1, x + 1, y + height - 2);
1927
1928       if (style->ythickness > 0)
1929         _cairo_draw_line (cr, gc2,
1930                           x, y, x + width - 1, y);
1931       if (style->xthickness > 0)
1932         _cairo_draw_line (cr, gc2,
1933                           x, y, x, y + height - 1);
1934       break;
1935       
1936     case GTK_SHADOW_OUT:
1937       /* Dark around right and bottom edge */
1938
1939       if (style->ythickness > 0)
1940         {
1941           if (style->ythickness > 1)
1942             {
1943               _cairo_draw_line (cr, gc1,
1944                                 x + 1, y + height - 2, x + width - 2, y + height - 2);
1945               _cairo_draw_line (cr, &style->black,
1946                                 x, y + height - 1, x + width - 1, y + height - 1);
1947             }
1948           else
1949             {
1950               _cairo_draw_line (cr, gc1,
1951                                 x + 1, y + height - 1, x + width - 1, y + height - 1);
1952             }
1953         }
1954
1955       if (style->xthickness > 0)
1956         {
1957           if (style->xthickness > 1)
1958             {
1959               _cairo_draw_line (cr, gc1,
1960                                 x + width - 2, y + 1, x + width - 2, y + height - 2);
1961               
1962               _cairo_draw_line (cr, &style->black,
1963                                 x + width - 1, y, x + width - 1, y + height - 1);
1964             }
1965           else
1966             {
1967               _cairo_draw_line (cr, gc1,
1968                                 x + width - 1, y + 1, x + width - 1, y + height - 1);
1969             }
1970         }
1971       
1972       /* Light around top and left */
1973
1974       if (style->ythickness > 0)
1975         _cairo_draw_line (cr, gc2,
1976                           x, y, x + width - 2, y);
1977       if (style->xthickness > 0)
1978         _cairo_draw_line (cr, gc2,
1979                           x, y, x, y + height - 2);
1980
1981       if (style->ythickness > 1)
1982         _cairo_draw_line (cr, &style->bg[state_type],
1983                           x + 1, y + 1, x + width - 3, y + 1);
1984       if (style->xthickness > 1)
1985         _cairo_draw_line (cr, &style->bg[state_type],
1986                           x + 1, y + 1, x + 1, y + height - 3);
1987       break;
1988       
1989     case GTK_SHADOW_ETCHED_IN:
1990     case GTK_SHADOW_ETCHED_OUT:
1991       if (style->xthickness > 0)
1992         {
1993           if (style->xthickness > 1)
1994             {
1995               thickness_light = 1;
1996               thickness_dark = 1;
1997       
1998               for (i = 0; i < thickness_dark; i++)
1999                 {
2000                   _cairo_draw_line (cr, gc1,
2001                                     x + width - i - 1,
2002                                     y + i,
2003                                     x + width - i - 1,
2004                                     y + height - i - 1);
2005                   _cairo_draw_line (cr, gc2,
2006                                     x + i,
2007                                     y + i,
2008                                     x + i,
2009                                     y + height - i - 2);
2010                 }
2011       
2012               for (i = 0; i < thickness_light; i++)
2013                 {
2014                   _cairo_draw_line (cr, gc1,
2015                                     x + thickness_dark + i,
2016                                     y + thickness_dark + i,
2017                                     x + thickness_dark + i,
2018                                     y + height - thickness_dark - i - 1);
2019                   _cairo_draw_line (cr, gc2,
2020                                     x + width - thickness_light - i - 1,
2021                                     y + thickness_dark + i,
2022                                     x + width - thickness_light - i - 1,
2023                                     y + height - thickness_light - 1);
2024                 }
2025             }
2026           else
2027             {
2028               _cairo_draw_line (cr,
2029                                 &style->dark[state_type],
2030                                 x, y, x, y + height);
2031               _cairo_draw_line (cr,
2032                                 &style->dark[state_type],
2033                                 x + width, y, x + width, y + height);
2034             }
2035         }
2036
2037       if (style->ythickness > 0)
2038         {
2039           if (style->ythickness > 1)
2040             {
2041               thickness_light = 1;
2042               thickness_dark = 1;
2043       
2044               for (i = 0; i < thickness_dark; i++)
2045                 {
2046                   _cairo_draw_line (cr, gc1,
2047                                     x + i,
2048                                     y + height - i - 1,
2049                                     x + width - i - 1,
2050                                     y + height - i - 1);
2051           
2052                   _cairo_draw_line (cr, gc2,
2053                                     x + i,
2054                                     y + i,
2055                                     x + width - i - 2,
2056                                     y + i);
2057                 }
2058       
2059               for (i = 0; i < thickness_light; i++)
2060                 {
2061                   _cairo_draw_line (cr, gc1,
2062                                     x + thickness_dark + i,
2063                                     y + thickness_dark + i,
2064                                     x + width - thickness_dark - i - 2,
2065                                     y + thickness_dark + i);
2066           
2067                   _cairo_draw_line (cr, gc2,
2068                                     x + thickness_dark + i,
2069                                     y + height - thickness_light - i - 1,
2070                                     x + width - thickness_light - 1,
2071                                     y + height - thickness_light - i - 1);
2072                 }
2073             }
2074           else
2075             {
2076               _cairo_draw_line (cr,
2077                                 &style->dark[state_type],
2078                                 x, y, x + width, y);
2079               _cairo_draw_line (cr,
2080                                 &style->dark[state_type],
2081                                 x, y + height, x + width, y + height);
2082             }
2083         }
2084       
2085       break;
2086     }
2087
2088   if (shadow_type == GTK_SHADOW_IN &&
2089       GTK_IS_SPIN_BUTTON (widget) &&
2090       detail && strcmp (detail, "entry") == 0)
2091     {
2092       if (get_direction (widget) == GTK_TEXT_DIR_LTR)
2093         {
2094           _cairo_draw_line (cr,
2095                             &style->base[state_type],
2096                             x + width - 1, y + 2,
2097                             x + width - 1, y + height - 3);
2098           _cairo_draw_line (cr,
2099                             &style->base[state_type],
2100                             x + width - 2, y + 2,
2101                             x + width - 2, y + height - 3);
2102           /* draw point */
2103           _cairo_draw_point (cr,
2104                              &style->black,
2105                              x + width - 1, y + 1);
2106           _cairo_draw_point (cr,
2107                              &style->bg[state_type],
2108                              x + width - 1, y + height - 2);
2109         }
2110       else
2111         {
2112           _cairo_draw_line (cr,
2113                             &style->base[state_type],
2114                             x, y + 2,
2115                             x, y + height - 3);
2116           _cairo_draw_line (cr,
2117                             &style->base[state_type],
2118                             x + 1, y + 2,
2119                             x + 1, y + height - 3);
2120
2121           _cairo_draw_point (cr,
2122                              &style->black,
2123                              x, y + 1);
2124
2125           _cairo_draw_line (cr,
2126                             &style->bg[state_type],
2127                             x, y + height - 2,
2128                             x + 1, y + height - 2);
2129           _cairo_draw_point (cr,
2130                              &style->light[state_type],
2131                              x, y + height - 1);
2132         }
2133     }
2134 }
2135
2136 static void
2137 draw_arrow (cairo_t       *cr,
2138             GdkColor      *color,
2139             GtkArrowType   arrow_type,
2140             gint           x,
2141             gint           y,
2142             gint           width,
2143             gint           height)
2144 {
2145   gdk_cairo_set_source_color (cr, color);
2146   cairo_save (cr);
2147     
2148   if (arrow_type == GTK_ARROW_DOWN)
2149     {
2150       cairo_move_to (cr, x,              y);
2151       cairo_line_to (cr, x + width,      y);
2152       cairo_line_to (cr, x + width / 2., y + height);
2153     }
2154   else if (arrow_type == GTK_ARROW_UP)
2155     {
2156       cairo_move_to (cr, x,              y + height);
2157       cairo_line_to (cr, x + width / 2., y);
2158       cairo_line_to (cr, x + width,      y + height);
2159     }
2160   else if (arrow_type == GTK_ARROW_LEFT)
2161     {
2162       cairo_move_to (cr, x + width,      y);
2163       cairo_line_to (cr, x + width,      y + height);
2164       cairo_line_to (cr, x,              y + height / 2.);
2165     }
2166   else if (arrow_type == GTK_ARROW_RIGHT)
2167     {
2168       cairo_move_to (cr, x,              y);
2169       cairo_line_to (cr, x + width,      y + height / 2.);
2170       cairo_line_to (cr, x,              y + height);
2171     }
2172
2173   cairo_close_path (cr);
2174   cairo_fill (cr);
2175
2176   cairo_restore (cr);
2177 }
2178
2179 static void
2180 calculate_arrow_geometry (GtkArrowType  arrow_type,
2181                           gint         *x,
2182                           gint         *y,
2183                           gint         *width,
2184                           gint         *height)
2185 {
2186   gint w = *width;
2187   gint h = *height;
2188   
2189   switch (arrow_type)
2190     {
2191     case GTK_ARROW_UP:
2192     case GTK_ARROW_DOWN:
2193       w += (w % 2) - 1;
2194       h = (w / 2 + 1);
2195       
2196       if (h > *height)
2197         {
2198           h = *height;
2199           w = 2 * h - 1;
2200         }
2201       
2202       if (arrow_type == GTK_ARROW_DOWN)
2203         {
2204           if (*height % 2 == 1 || h % 2 == 0)
2205             *height += 1;
2206         }
2207       else
2208         {
2209           if (*height % 2 == 0 || h % 2 == 0)
2210             *height -= 1;
2211         }
2212       break;
2213
2214     case GTK_ARROW_RIGHT:
2215     case GTK_ARROW_LEFT:
2216       h += (h % 2) - 1;
2217       w = (h / 2 + 1);
2218       
2219       if (w > *width)
2220         {
2221           w = *width;
2222           h = 2 * w - 1;
2223         }
2224       
2225       if (arrow_type == GTK_ARROW_RIGHT)
2226         {
2227           if (*width % 2 == 1 || w % 2 == 0)
2228             *width += 1;
2229         }
2230       else
2231         {
2232           if (*width % 2 == 0 || w % 2 == 0)
2233             *width -= 1;
2234         }
2235       break;
2236       
2237     default:
2238       /* should not be reached */
2239       break;
2240     }
2241
2242   *x += (*width - w) / 2;
2243   *y += (*height - h) / 2;
2244   *height = h;
2245   *width = w;
2246 }
2247
2248 static void
2249 gtk_default_draw_arrow (GtkStyle      *style,
2250                         cairo_t       *cr,
2251                         GtkStateType   state,
2252                         GtkShadowType  shadow,
2253                         GtkWidget     *widget,
2254                         const gchar   *detail,
2255                         GtkArrowType   arrow_type,
2256                         gboolean       fill,
2257                         gint           x,
2258                         gint           y,
2259                         gint           width,
2260                         gint           height)
2261 {
2262   calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
2263
2264   if (detail && strcmp (detail, "menu_scroll_arrow_up") == 0)
2265     y++;
2266
2267   if (state == GTK_STATE_INSENSITIVE)
2268     draw_arrow (cr, &style->white, arrow_type,
2269                 x + 1, y + 1, width, height);
2270   draw_arrow (cr, &style->fg[state], arrow_type,
2271               x, y, width, height);
2272 }
2273
2274 static void
2275 gtk_default_draw_diamond (GtkStyle      *style,
2276                           cairo_t       *cr,
2277                           GtkStateType   state_type,
2278                           GtkShadowType  shadow_type,
2279                           GtkWidget     *widget,
2280                           const gchar   *detail,
2281                           gint           x,
2282                           gint           y,
2283                           gint           width,
2284                           gint           height)
2285 {
2286   gint half_width;
2287   gint half_height;
2288   GdkColor *outer_nw = NULL;
2289   GdkColor *outer_ne = NULL;
2290   GdkColor *outer_sw = NULL;
2291   GdkColor *outer_se = NULL;
2292   GdkColor *middle_nw = NULL;
2293   GdkColor *middle_ne = NULL;
2294   GdkColor *middle_sw = NULL;
2295   GdkColor *middle_se = NULL;
2296   GdkColor *inner_nw = NULL;
2297   GdkColor *inner_ne = NULL;
2298   GdkColor *inner_sw = NULL;
2299   GdkColor *inner_se = NULL;
2300   
2301   half_width = width / 2;
2302   half_height = height / 2;
2303   
2304   switch (shadow_type)
2305     {
2306     case GTK_SHADOW_IN:
2307       inner_sw = inner_se = &style->bg[state_type];
2308       middle_sw = middle_se = &style->light[state_type];
2309       outer_sw = outer_se = &style->light[state_type];
2310       inner_nw = inner_ne = &style->black;
2311       middle_nw = middle_ne = &style->dark[state_type];
2312       outer_nw = outer_ne = &style->dark[state_type];
2313       break;
2314           
2315     case GTK_SHADOW_OUT:
2316       inner_sw = inner_se = &style->dark[state_type];
2317       middle_sw = middle_se = &style->dark[state_type];
2318       outer_sw = outer_se = &style->black;
2319       inner_nw = inner_ne = &style->bg[state_type];
2320       middle_nw = middle_ne = &style->light[state_type];
2321       outer_nw = outer_ne = &style->light[state_type];
2322       break;
2323
2324     case GTK_SHADOW_ETCHED_IN:
2325       inner_sw = inner_se = &style->bg[state_type];
2326       middle_sw = middle_se = &style->dark[state_type];
2327       outer_sw = outer_se = &style->light[state_type];
2328       inner_nw = inner_ne = &style->bg[state_type];
2329       middle_nw = middle_ne = &style->light[state_type];
2330       outer_nw = outer_ne = &style->dark[state_type];
2331       break;
2332
2333     case GTK_SHADOW_ETCHED_OUT:
2334       inner_sw = inner_se = &style->bg[state_type];
2335       middle_sw = middle_se = &style->light[state_type];
2336       outer_sw = outer_se = &style->dark[state_type];
2337       inner_nw = inner_ne = &style->bg[state_type];
2338       middle_nw = middle_ne = &style->dark[state_type];
2339       outer_nw = outer_ne = &style->light[state_type];
2340       break;
2341       
2342     default:
2343
2344       break;
2345     }
2346
2347   if (inner_sw)
2348     {
2349       _cairo_draw_line (cr, inner_sw,
2350                         x + 2, y + half_height,
2351                         x + half_width, y + height - 2);
2352       _cairo_draw_line (cr, inner_se,
2353                         x + half_width, y + height - 2,
2354                         x + width - 2, y + half_height);
2355       _cairo_draw_line (cr, middle_sw,
2356                         x + 1, y + half_height,
2357                         x + half_width, y + height - 1);
2358       _cairo_draw_line (cr, middle_se,
2359                         x + half_width, y + height - 1,
2360                         x + width - 1, y + half_height);
2361       _cairo_draw_line (cr, outer_sw,
2362                         x, y + half_height,
2363                         x + half_width, y + height);
2364       _cairo_draw_line (cr, outer_se,
2365                         x + half_width, y + height,
2366                         x + width, y + half_height);
2367   
2368       _cairo_draw_line (cr, inner_nw,
2369                         x + 2, y + half_height,
2370                         x + half_width, y + 2);
2371       _cairo_draw_line (cr, inner_ne,
2372                         x + half_width, y + 2,
2373                         x + width - 2, y + half_height);
2374       _cairo_draw_line (cr, middle_nw,
2375                         x + 1, y + half_height,
2376                         x + half_width, y + 1);
2377       _cairo_draw_line (cr, middle_ne,
2378                         x + half_width, y + 1,
2379                         x + width - 1, y + half_height);
2380       _cairo_draw_line (cr, outer_nw,
2381                         x, y + half_height,
2382                         x + half_width, y);
2383       _cairo_draw_line (cr, outer_ne,
2384                         x + half_width, y,
2385                         x + width, y + half_height);
2386     }
2387 }
2388
2389 static void
2390 option_menu_get_props (GtkWidget      *widget,
2391                        GtkRequisition *indicator_size,
2392                        GtkBorder      *indicator_spacing)
2393 {
2394   GtkRequisition *tmp_size = NULL;
2395   GtkBorder *tmp_spacing = NULL;
2396
2397   if (tmp_size)
2398     {
2399       *indicator_size = *tmp_size;
2400       gtk_requisition_free (tmp_size);
2401     }
2402   else
2403     *indicator_size = default_option_indicator_size;
2404
2405   if (tmp_spacing)
2406     {
2407       *indicator_spacing = *tmp_spacing;
2408       gtk_border_free (tmp_spacing);
2409     }
2410   else
2411     *indicator_spacing = default_option_indicator_spacing;
2412 }
2413
2414 static gboolean
2415 background_is_solid (GtkStyle     *style,
2416                      GtkStateType  type)
2417 {
2418   if (style->background[type] == NULL)
2419     return FALSE;
2420
2421   return cairo_pattern_get_type (style->background[type]) == CAIRO_PATTERN_TYPE_SOLID;
2422 }
2423
2424 static void 
2425 gtk_default_draw_box (GtkStyle      *style,
2426                       cairo_t       *cr,
2427                       GtkStateType   state_type,
2428                       GtkShadowType  shadow_type,
2429                       GtkWidget     *widget,
2430                       const gchar   *detail,
2431                       gint           x,
2432                       gint           y,
2433                       gint           width,
2434                       gint           height)
2435 {
2436   gboolean is_spinbutton_box = FALSE;
2437   
2438   if (GTK_IS_SPIN_BUTTON (widget) && detail)
2439     {
2440       if (strcmp (detail, "spinbutton_up") == 0)
2441         {
2442           y += 2;
2443           width -= 3;
2444           height -= 2;
2445
2446           if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2447             x += 2;
2448           else
2449             x += 1;
2450
2451           is_spinbutton_box = TRUE;
2452         }
2453       else if (strcmp (detail, "spinbutton_down") == 0)
2454         {
2455           width -= 3;
2456           height -= 2;
2457
2458           if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2459             x += 2;
2460           else
2461             x += 1;
2462
2463           is_spinbutton_box = TRUE;
2464         }
2465     }
2466   
2467   if (background_is_solid (style, state_type))
2468     {
2469       GdkColor *gc = &style->bg[state_type];
2470
2471       if (state_type == GTK_STATE_SELECTED && detail && strcmp (detail, "paned") == 0)
2472         {
2473           if (widget && !gtk_widget_has_focus (widget))
2474             gc = &style->base[GTK_STATE_ACTIVE];
2475         }
2476
2477       _cairo_draw_rectangle (cr, gc, TRUE,
2478                              x, y, width, height);
2479     }
2480   else
2481     gtk_style_apply_default_background (style, cr, gtk_widget_get_window (widget),
2482                                         state_type, x, y, width, height);
2483
2484
2485   if (is_spinbutton_box)
2486     {
2487       GdkColor *upper;
2488       GdkColor *lower;
2489
2490       lower = &style->dark[state_type];
2491       if (shadow_type == GTK_SHADOW_OUT)
2492         upper = &style->light[state_type];
2493       else
2494         upper = &style->dark[state_type];
2495
2496       _cairo_draw_line (cr, upper, x, y, x + width - 1, y);
2497       _cairo_draw_line (cr, lower, x, y + height - 1, x + width - 1, y + height - 1);
2498
2499       return;
2500     }
2501
2502   gtk_paint_shadow (style, cr, state_type, shadow_type, widget, detail,
2503                           x, y, width, height);
2504
2505   if (detail && strcmp (detail, "optionmenu") == 0)
2506     {
2507       GtkRequisition indicator_size;
2508       GtkBorder indicator_spacing;
2509       gint vline_x;
2510
2511       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2512
2513       if (get_direction (widget) == GTK_TEXT_DIR_RTL)
2514         vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
2515       else 
2516         vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
2517
2518       gtk_paint_vline (style, cr, state_type, widget,
2519                              detail,
2520                              y + style->ythickness + 1,
2521                              y + height - style->ythickness - 3,
2522                              vline_x);
2523     }
2524 }
2525
2526 static GdkColor *
2527 get_darkened (const GdkColor *color,
2528                  gint            darken_count)
2529 {
2530   GdkColor src = *color;
2531   GdkColor shaded = *color;
2532   
2533   while (darken_count)
2534     {
2535       _gtk_style_shade (&src, &shaded, 0.93);
2536       src = shaded;
2537       --darken_count;
2538     }
2539    
2540   return gdk_color_copy (&shaded);
2541 }
2542
2543 static void 
2544 gtk_default_draw_flat_box (GtkStyle      *style,
2545                            cairo_t       *cr,
2546                            GtkStateType   state_type,
2547                            GtkShadowType  shadow_type,
2548                            GtkWidget     *widget,
2549                            const gchar   *detail,
2550                            gint           x,
2551                            gint           y,
2552                            gint           width,
2553                            gint           height)
2554 {
2555   GdkColor *gc1;
2556   GdkColor *freeme = NULL;
2557   
2558   cairo_set_line_width (cr, 1.0);
2559
2560   if (detail)
2561     {
2562       int trimmed_len = strlen (detail);
2563
2564       if (g_str_has_prefix (detail, "cell_"))
2565         {
2566           if (g_str_has_suffix (detail, "_start"))
2567             trimmed_len -= 6;
2568           else if (g_str_has_suffix (detail, "_middle"))
2569             trimmed_len -= 7;
2570           else if (g_str_has_suffix (detail, "_end"))
2571             trimmed_len -= 4;
2572         }
2573
2574       if (state_type == GTK_STATE_SELECTED)
2575         {
2576           if (!strcmp ("text", detail))
2577             gc1 = &style->bg[GTK_STATE_SELECTED];
2578           else if (!strncmp ("cell_even", detail, trimmed_len) ||
2579                    !strncmp ("cell_odd", detail, trimmed_len) ||
2580                    !strncmp ("cell_even_ruled", detail, trimmed_len) ||
2581                    !strncmp ("cell_even_ruled_sorted", detail, trimmed_len))
2582             {
2583               /* This has to be really broken; alex made me do it. -jrb */
2584               if (widget && gtk_widget_has_focus (widget))
2585                 gc1 = &style->base[state_type];
2586               else
2587                 gc1 = &style->base[GTK_STATE_ACTIVE];
2588             }
2589           else if (!strncmp ("cell_odd_ruled", detail, trimmed_len) ||
2590                    !strncmp ("cell_odd_ruled_sorted", detail, trimmed_len))
2591             {
2592               if (widget && gtk_widget_has_focus (widget))
2593                 freeme = get_darkened (&style->base[state_type], 1);
2594               else
2595                 freeme = get_darkened (&style->base[GTK_STATE_ACTIVE], 1);
2596               gc1 = freeme;
2597             }
2598           else
2599             {
2600               gc1 = &style->bg[state_type];
2601             }
2602         }
2603       else
2604         {
2605           if (!strcmp ("viewportbin", detail))
2606             gc1 = &style->bg[GTK_STATE_NORMAL];
2607           else if (!strcmp ("entry_bg", detail))
2608             gc1 = &style->base[gtk_widget_get_state (widget)];
2609
2610           /* For trees: even rows are base color, odd rows are a shade of
2611            * the base color, the sort column is a shade of the original color
2612            * for that row.
2613            */
2614
2615           else if (!strncmp ("cell_even", detail, trimmed_len) ||
2616                    !strncmp ("cell_odd", detail, trimmed_len) ||
2617                    !strncmp ("cell_even_ruled", detail, trimmed_len))
2618             {
2619               GdkColor *color = NULL;
2620
2621               gtk_widget_style_get (widget,
2622                                     "even-row-color", &color,
2623                                     NULL);
2624
2625               if (color)
2626                 {
2627                   freeme = get_darkened (color, 0);
2628                   gc1 = freeme;
2629
2630                   gdk_color_free (color);
2631                 }
2632               else
2633                 gc1 = &style->base[state_type];
2634             }
2635           else if (!strncmp ("cell_odd_ruled", detail, trimmed_len))
2636             {
2637               GdkColor *color = NULL;
2638
2639               gtk_widget_style_get (widget,
2640                                     "odd-row-color", &color,
2641                                     NULL);
2642
2643               if (color)
2644                 {
2645                   freeme = get_darkened (color, 0);
2646                   gc1 = freeme;
2647
2648                   gdk_color_free (color);
2649                 }
2650               else
2651                 {
2652                   gtk_widget_style_get (widget,
2653                                         "even-row-color", &color,
2654                                         NULL);
2655
2656                   if (color)
2657                     {
2658                       freeme = get_darkened (color, 1);
2659                       gdk_color_free (color);
2660                     }
2661                   else
2662                     freeme = get_darkened (&style->base[state_type], 1);
2663                   gc1 = freeme;
2664                 }
2665             }
2666           else if (!strncmp ("cell_even_sorted", detail, trimmed_len) ||
2667                    !strncmp ("cell_odd_sorted", detail, trimmed_len) ||
2668                    !strncmp ("cell_even_ruled_sorted", detail, trimmed_len))
2669             {
2670               GdkColor *color = NULL;
2671
2672               if (!strncmp ("cell_odd_sorted", detail, trimmed_len))
2673                 gtk_widget_style_get (widget,
2674                                       "odd-row-color", &color,
2675                                       NULL);
2676               else
2677                 gtk_widget_style_get (widget,
2678                                       "even-row-color", &color,
2679                                       NULL);
2680
2681               if (color)
2682                 {
2683                   freeme = get_darkened (color, 1);
2684                   gc1 = freeme;
2685
2686                   gdk_color_free (color);
2687                 }
2688               else
2689                 {
2690                   freeme = get_darkened (&style->base[state_type], 1);
2691                   gc1 = freeme;
2692                 }
2693             }
2694           else if (!strncmp ("cell_odd_ruled_sorted", detail, trimmed_len))
2695             {
2696               GdkColor *color = NULL;
2697
2698               gtk_widget_style_get (widget,
2699                                     "odd-row-color", &color,
2700                                     NULL);
2701
2702               if (color)
2703                 {
2704                   freeme = get_darkened (color, 1);
2705                   gc1 = freeme;
2706
2707                   gdk_color_free (color);
2708                 }
2709               else
2710                 {
2711                   gtk_widget_style_get (widget,
2712                                         "even-row-color", &color,
2713                                         NULL);
2714
2715                   if (color)
2716                     {
2717                       freeme = get_darkened (color, 2);
2718                       gdk_color_free (color);
2719                     }
2720                   else
2721                     freeme = get_darkened (&style->base[state_type], 2);
2722                   gc1 = freeme;
2723                 }
2724             }
2725           else
2726             gc1 = &style->bg[state_type];
2727         }
2728     }
2729   else
2730     gc1 = &style->bg[state_type];
2731   
2732   if (background_is_solid (style, state_type) || gc1 != &style->bg[state_type])
2733     {
2734       _cairo_draw_rectangle (cr, gc1, TRUE,
2735                              x, y, width, height);
2736
2737       if (detail && !strcmp ("tooltip", detail))
2738         _cairo_draw_rectangle (cr, &style->black, FALSE,
2739                                x, y, width - 1, height - 1);
2740     }
2741   else
2742     gtk_style_apply_default_background (style, cr, gtk_widget_get_window (widget),
2743                                         state_type, x, y, width, height);
2744
2745   if (freeme)
2746     gdk_color_free (freeme);
2747 }
2748
2749 static void 
2750 gtk_default_draw_check (GtkStyle      *style,
2751                         cairo_t       *cr,
2752                         GtkStateType   state_type,
2753                         GtkShadowType  shadow_type,
2754                         GtkWidget     *widget,
2755                         const gchar   *detail,
2756                         gint           x,
2757                         gint           y,
2758                         gint           width,
2759                         gint           height)
2760 {
2761   enum { BUTTON, MENU, CELL } type = BUTTON;
2762   int exterior_size;
2763   int interior_size;
2764   int pad;
2765   
2766   if (detail)
2767     {
2768       if (strcmp (detail, "cellcheck") == 0)
2769         type = CELL;
2770       else if (strcmp (detail, "check") == 0)
2771         type = MENU;
2772     }
2773       
2774   exterior_size = MIN (width, height);
2775   if (exterior_size % 2 == 0) /* Ensure odd */
2776     exterior_size -= 1;
2777
2778   pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
2779   interior_size = MAX (1, exterior_size - 2 * pad);
2780
2781   if (interior_size < 7)
2782     {
2783       interior_size = 7;
2784       pad = MAX (0, (exterior_size - interior_size) / 2);
2785     }
2786
2787   x -= (1 + exterior_size - width) / 2;
2788   y -= (1 + exterior_size - height) / 2;
2789
2790   switch (type)
2791     {
2792     case BUTTON:
2793     case CELL:
2794       if (type == BUTTON)
2795         gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2796       else
2797         gdk_cairo_set_source_color (cr, &style->text[state_type]);
2798         
2799       cairo_set_line_width (cr, 1.0);
2800       cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1);
2801       cairo_stroke (cr);
2802
2803       gdk_cairo_set_source_color (cr, &style->base[state_type]);
2804       cairo_rectangle (cr, x + 1, y + 1, exterior_size - 2, exterior_size - 2);
2805       cairo_fill (cr);
2806       break;
2807
2808     case MENU:
2809       break;
2810     }
2811       
2812   switch (type)
2813     {
2814     case BUTTON:
2815     case CELL:
2816       gdk_cairo_set_source_color (cr, &style->text[state_type]);
2817       break;
2818     case MENU:
2819       gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2820       break;
2821     }
2822
2823   if (shadow_type == GTK_SHADOW_IN)
2824     {
2825       cairo_translate (cr,
2826                        x + pad, y + pad);
2827       
2828       cairo_scale (cr, interior_size / 7., interior_size / 7.);
2829       
2830       cairo_move_to  (cr, 7.0, 0.0);
2831       cairo_line_to  (cr, 7.5, 1.0);
2832       cairo_curve_to (cr, 5.3, 2.0,
2833                       4.3, 4.0,
2834                       3.5, 7.0);
2835       cairo_curve_to (cr, 3.0, 5.7,
2836                       1.3, 4.7,
2837                       0.0, 4.7);
2838       cairo_line_to  (cr, 0.2, 3.5);
2839       cairo_curve_to (cr, 1.1, 3.5,
2840                       2.3, 4.3,
2841                       3.0, 5.0);
2842       cairo_curve_to (cr, 1.0, 3.9,
2843                       2.4, 4.1,
2844                       3.2, 4.9);
2845       cairo_curve_to (cr, 3.5, 3.1,
2846                       5.2, 2.0,
2847                       7.0, 0.0);
2848       
2849       cairo_fill (cr);
2850     }
2851   else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
2852     {
2853       int line_thickness = MAX (1, (3 + interior_size * 2) / 7);
2854
2855       cairo_rectangle (cr,
2856                        x + pad,
2857                        y + pad + (1 + interior_size - line_thickness) / 2,
2858                        interior_size,
2859                        line_thickness);
2860       cairo_fill (cr);
2861     }
2862 }
2863
2864 static void 
2865 gtk_default_draw_option (GtkStyle      *style,
2866                          cairo_t       *cr,
2867                          GtkStateType   state_type,
2868                          GtkShadowType  shadow_type,
2869                          GtkWidget     *widget,
2870                          const gchar   *detail,
2871                          gint           x,
2872                          gint           y,
2873                          gint           width,
2874                          gint           height)
2875 {
2876   enum { BUTTON, MENU, CELL } type = BUTTON;
2877   int exterior_size;
2878   
2879   if (detail)
2880     {
2881       if (strcmp (detail, "radio") == 0)
2882         type = CELL;
2883       else if (strcmp (detail, "option") == 0)
2884         type = MENU;
2885     }
2886       
2887   exterior_size = MIN (width, height);
2888   if (exterior_size % 2 == 0) /* Ensure odd */
2889     exterior_size -= 1;
2890   
2891   x -= (1 + exterior_size - width) / 2;
2892   y -= (1 + exterior_size - height) / 2;
2893
2894   switch (type)
2895     {
2896     case BUTTON:
2897     case CELL:
2898       gdk_cairo_set_source_color (cr, &style->base[state_type]);
2899       
2900       cairo_arc (cr,
2901                  x + exterior_size / 2.,
2902                  y + exterior_size / 2.,
2903                  (exterior_size - 1) / 2.,
2904                  0, 2 * G_PI);
2905
2906       cairo_fill_preserve (cr);
2907
2908       if (type == BUTTON)
2909         gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2910       else
2911         gdk_cairo_set_source_color (cr, &style->text[state_type]);
2912         
2913       cairo_set_line_width (cr, 1.);
2914       cairo_stroke (cr);
2915       break;
2916
2917     case MENU:
2918       break;
2919     }
2920       
2921   switch (type)
2922     {
2923     case BUTTON:
2924       gdk_cairo_set_source_color (cr, &style->text[state_type]);
2925       break;
2926     case CELL:
2927       break;
2928     case MENU:
2929       gdk_cairo_set_source_color (cr, &style->fg[state_type]);
2930       break;
2931     }
2932
2933   if (shadow_type == GTK_SHADOW_IN)
2934     {
2935       int pad = style->xthickness + MAX (1, 2 * (exterior_size - 2 * style->xthickness) / 9);
2936       int interior_size = MAX (1, exterior_size - 2 * pad);
2937
2938       if (interior_size < 5)
2939         {
2940           interior_size = 7;
2941           pad = MAX (0, (exterior_size - interior_size) / 2);
2942         }
2943
2944       cairo_arc (cr,
2945                  x + pad + interior_size / 2.,
2946                  y + pad + interior_size / 2.,
2947                  interior_size / 2.,
2948                  0, 2 * G_PI);
2949       cairo_fill (cr);
2950     }
2951   else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
2952     {
2953       int pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
2954       int interior_size = MAX (1, exterior_size - 2 * pad);
2955       int line_thickness;
2956
2957       if (interior_size < 7)
2958         {
2959           interior_size = 7;
2960           pad = MAX (0, (exterior_size - interior_size) / 2);
2961         }
2962
2963       line_thickness = MAX (1, (3 + interior_size * 2) / 7);
2964
2965       cairo_rectangle (cr,
2966                        x + pad,
2967                        y + pad + (interior_size - line_thickness) / 2.,
2968                        interior_size,
2969                        line_thickness);
2970       cairo_fill (cr);
2971     }
2972 }
2973
2974 static void
2975 gtk_default_draw_tab (GtkStyle      *style,
2976                       cairo_t       *cr,
2977                       GtkStateType   state_type,
2978                       GtkShadowType  shadow_type,
2979                       GtkWidget     *widget,
2980                       const gchar   *detail,
2981                       gint           x,
2982                       gint           y,
2983                       gint           width,
2984                       gint           height)
2985 {
2986 #define ARROW_SPACE 4
2987
2988   GtkRequisition indicator_size;
2989   GtkBorder indicator_spacing;
2990   gint arrow_height;
2991
2992   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2993
2994   indicator_size.width += (indicator_size.width % 2) - 1;
2995   arrow_height = indicator_size.width / 2 + 1;
2996
2997   x += (width - indicator_size.width) / 2;
2998   y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
2999
3000   if (state_type == GTK_STATE_INSENSITIVE)
3001     {
3002       draw_arrow (cr, &style->white,
3003                   GTK_ARROW_UP, x + 1, y + 1,
3004                   indicator_size.width, arrow_height);
3005       
3006       draw_arrow (cr, &style->white,
3007                   GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3008                   indicator_size.width, arrow_height);
3009     }
3010   
3011   draw_arrow (cr, &style->fg[state_type],
3012               GTK_ARROW_UP, x, y,
3013               indicator_size.width, arrow_height);
3014   
3015   
3016   draw_arrow (cr, &style->fg[state_type],
3017               GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3018               indicator_size.width, arrow_height);
3019 }
3020
3021 static void 
3022 gtk_default_draw_shadow_gap (GtkStyle       *style,
3023                              cairo_t        *cr,
3024                              GtkStateType    state_type,
3025                              GtkShadowType   shadow_type,
3026                              GtkWidget      *widget,
3027                              const gchar    *detail,
3028                              gint            x,
3029                              gint            y,
3030                              gint            width,
3031                              gint            height,
3032                              GtkPositionType gap_side,
3033                              gint            gap_x,
3034                              gint            gap_width)
3035 {
3036   GdkColor *color1 = NULL;
3037   GdkColor *color2 = NULL;
3038   GdkColor *color3 = NULL;
3039   GdkColor *color4 = NULL;
3040   
3041   switch (shadow_type)
3042     {
3043     case GTK_SHADOW_NONE:
3044     default:
3045       return;
3046     case GTK_SHADOW_IN:
3047       color1 = &style->dark[state_type];
3048       color2 = &style->black;
3049       color3 = &style->bg[state_type];
3050       color4 = &style->light[state_type];
3051       break;
3052     case GTK_SHADOW_ETCHED_IN:
3053       color1 = &style->dark[state_type];
3054       color2 = &style->light[state_type];
3055       color3 = &style->dark[state_type];
3056       color4 = &style->light[state_type];
3057       break;
3058     case GTK_SHADOW_OUT:
3059       color1 = &style->light[state_type];
3060       color2 = &style->bg[state_type];
3061       color3 = &style->dark[state_type];
3062       color4 = &style->black;
3063       break;
3064     case GTK_SHADOW_ETCHED_OUT:
3065       color1 = &style->light[state_type];
3066       color2 = &style->dark[state_type];
3067       color3 = &style->light[state_type];
3068       color4 = &style->dark[state_type];
3069       break;
3070     }
3071
3072   switch (shadow_type)
3073     {
3074     case GTK_SHADOW_NONE:
3075     case GTK_SHADOW_IN:
3076     case GTK_SHADOW_OUT:
3077     case GTK_SHADOW_ETCHED_IN:
3078     case GTK_SHADOW_ETCHED_OUT:
3079       switch (gap_side)
3080         {
3081         case GTK_POS_TOP:
3082           _cairo_draw_line (cr, color1,
3083                             x, y, x, y + height - 1);
3084           _cairo_draw_line (cr, color2,
3085                             x + 1, y, x + 1, y + height - 2);
3086           
3087           _cairo_draw_line (cr, color3,
3088                             x + 1, y + height - 2, x + width - 2, y + height - 2);
3089           _cairo_draw_line (cr, color3,
3090                             x + width - 2, y, x + width - 2, y + height - 2);
3091           _cairo_draw_line (cr, color4,
3092                             x, y + height - 1, x + width - 1, y + height - 1);
3093           _cairo_draw_line (cr, color4,
3094                             x + width - 1, y, x + width - 1, y + height - 1);
3095           if (gap_x > 0)
3096             {
3097               _cairo_draw_line (cr, color1,
3098                                 x, y, x + gap_x - 1, y);
3099               _cairo_draw_line (cr, color2,
3100                                 x + 1, y + 1, x + gap_x - 1, y + 1);
3101               _cairo_draw_line (cr, color2,
3102                                 x + gap_x, y, x + gap_x, y);
3103             }
3104           if ((width - (gap_x + gap_width)) > 0)
3105             {
3106               _cairo_draw_line (cr, color1,
3107                                 x + gap_x + gap_width, y, x + width - 2, y);
3108               _cairo_draw_line (cr, color2,
3109                                 x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
3110               _cairo_draw_line (cr, color2,
3111                                 x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3112             }
3113           break;
3114         case GTK_POS_BOTTOM:
3115           _cairo_draw_line (cr, color1,
3116                             x, y, x + width - 1, y);
3117           _cairo_draw_line (cr, color1,
3118                             x, y, x, y + height - 1);
3119           _cairo_draw_line (cr, color2,
3120                             x + 1, y + 1, x + width - 2, y + 1);
3121           _cairo_draw_line (cr, color2,
3122                             x + 1, y + 1, x + 1, y + height - 1);
3123           
3124           _cairo_draw_line (cr, color3,
3125                             x + width - 2, y + 1, x + width - 2, y + height - 1);
3126           _cairo_draw_line (cr, color4,
3127                             x + width - 1, y, x + width - 1, y + height - 1);
3128           if (gap_x > 0)
3129             {
3130               _cairo_draw_line (cr, color4,
3131                                 x, y + height - 1, x + gap_x - 1, y + height - 1);
3132               _cairo_draw_line (cr, color3,
3133                                 x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3134               _cairo_draw_line (cr, color3,
3135                                 x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3136             }
3137           if ((width - (gap_x + gap_width)) > 0)
3138             {
3139               _cairo_draw_line (cr, color4,
3140                                 x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3141               _cairo_draw_line (cr, color3,
3142                                 x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3143               _cairo_draw_line (cr, color3,
3144                                 x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3145             }
3146           break;
3147         case GTK_POS_LEFT:
3148           _cairo_draw_line (cr, color1,
3149                             x, y, x + width - 1, y);
3150           _cairo_draw_line (cr, color2,
3151                             x, y + 1, x + width - 2, y + 1);
3152           
3153           _cairo_draw_line (cr, color3,
3154                             x, y + height - 2, x + width - 2, y + height - 2);
3155           _cairo_draw_line (cr, color3,
3156                             x + width - 2, y + 1, x + width - 2, y + height - 2);
3157           _cairo_draw_line (cr, color4,
3158                             x, y + height - 1, x + width - 1, y + height - 1);
3159           _cairo_draw_line (cr, color4,
3160                             x + width - 1, y, x + width - 1, y + height - 1);
3161           if (gap_x > 0)
3162             {
3163               _cairo_draw_line (cr, color1,
3164                                 x, y, x, y + gap_x - 1);
3165               _cairo_draw_line (cr, color2,
3166                                 x + 1, y + 1, x + 1, y + gap_x - 1);
3167               _cairo_draw_line (cr, color2,
3168                                 x, y + gap_x, x, y + gap_x);
3169             }
3170           if ((width - (gap_x + gap_width)) > 0)
3171             {
3172               _cairo_draw_line (cr, color1,
3173                                 x, y + gap_x + gap_width, x, y + height - 2);
3174               _cairo_draw_line (cr, color2,
3175                                 x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3176               _cairo_draw_line (cr, color2,
3177                                 x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3178             }
3179           break;
3180         case GTK_POS_RIGHT:
3181           _cairo_draw_line (cr, color1,
3182                             x, y, x + width - 1, y);
3183           _cairo_draw_line (cr, color1,
3184                             x, y, x, y + height - 1);
3185           _cairo_draw_line (cr, color2,
3186                             x + 1, y + 1, x + width - 1, y + 1);
3187           _cairo_draw_line (cr, color2,
3188                             x + 1, y + 1, x + 1, y + height - 2);
3189           
3190           _cairo_draw_line (cr, color3,
3191                             x + 1, y + height - 2, x + width - 1, y + height - 2);
3192           _cairo_draw_line (cr, color4,
3193                             x, y + height - 1, x + width - 1, y + height - 1);
3194           if (gap_x > 0)
3195             {
3196               _cairo_draw_line (cr, color4,
3197                                 x + width - 1, y, x + width - 1, y + gap_x - 1);
3198               _cairo_draw_line (cr, color3,
3199                                 x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3200               _cairo_draw_line (cr, color3,
3201                                 x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3202             }
3203           if ((width - (gap_x + gap_width)) > 0)
3204             {
3205               _cairo_draw_line (cr, color4,
3206                                 x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3207               _cairo_draw_line (cr, color3,
3208                                 x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3209               _cairo_draw_line (cr, color3,
3210                                 x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3211             }
3212           break;
3213         }
3214     }
3215 }
3216
3217 static void 
3218 gtk_default_draw_box_gap (GtkStyle       *style,
3219                           cairo_t        *cr,
3220                           GtkStateType    state_type,
3221                           GtkShadowType   shadow_type,
3222                           GtkWidget      *widget,
3223                           const gchar    *detail,
3224                           gint            x,
3225                           gint            y,
3226                           gint            width,
3227                           gint            height,
3228                           GtkPositionType gap_side,
3229                           gint            gap_x,
3230                           gint            gap_width)
3231 {
3232   GdkColor color1;
3233   GdkColor color2;
3234   GdkColor color3;
3235   GdkColor color4;
3236   
3237   gtk_style_apply_default_background (style, cr, gtk_widget_get_window (widget),
3238                                       state_type, x, y, width, height);
3239
3240   switch (shadow_type)
3241     {
3242     case GTK_SHADOW_NONE:
3243       return;
3244     case GTK_SHADOW_IN:
3245       color1 = style->dark[state_type];
3246       color2 = style->black;
3247       color3 = style->bg[state_type];
3248       color4 = style->light[state_type];
3249       break;
3250     case GTK_SHADOW_ETCHED_IN:
3251       color1 = style->dark[state_type];
3252       color2 = style->light[state_type];
3253       color3 = style->dark[state_type];
3254       color4 = style->light[state_type];
3255       break;
3256     case GTK_SHADOW_OUT:
3257       color1 = style->light[state_type];
3258       color2 = style->bg[state_type];
3259       color3 = style->dark[state_type];
3260       color4 = style->black;
3261       break;
3262     case GTK_SHADOW_ETCHED_OUT:
3263       color1 = style->light[state_type];
3264       color2 = style->dark[state_type];
3265       color3 = style->light[state_type];
3266       color4 = style->dark[state_type];
3267       break;
3268     }
3269   
3270   cairo_set_line_width (cr, 1.0);
3271
3272   switch (shadow_type)
3273     {
3274     case GTK_SHADOW_NONE:
3275     case GTK_SHADOW_IN:
3276     case GTK_SHADOW_OUT:
3277     case GTK_SHADOW_ETCHED_IN:
3278     case GTK_SHADOW_ETCHED_OUT:
3279       switch (gap_side)
3280         {
3281         case GTK_POS_TOP:
3282           _cairo_draw_line (cr, &color1,
3283                             x, y, x, y + height - 1);
3284           _cairo_draw_line (cr, &color2,
3285                             x + 1, y, x + 1, y + height - 2);
3286           
3287           _cairo_draw_line (cr, &color3,
3288                             x + 1, y + height - 2, x + width - 2, y + height - 2);
3289           _cairo_draw_line (cr, &color3,
3290                             x + width - 2, y, x + width - 2, y + height - 2);
3291           _cairo_draw_line (cr, &color4,
3292                             x, y + height - 1, x + width - 1, y + height - 1);
3293           _cairo_draw_line (cr, &color4,
3294                             x + width - 1, y, x + width - 1, y + height - 1);
3295           if (gap_x > 0)
3296             {
3297               _cairo_draw_line (cr, &color1,
3298                                 x, y, x + gap_x - 1, y);
3299               _cairo_draw_line (cr, &color2,
3300                                 x + 1, y + 1, x + gap_x - 1, y + 1);
3301               _cairo_draw_line (cr, &color2,
3302                                 x + gap_x, y, x + gap_x, y);
3303             }
3304           if ((width - (gap_x + gap_width)) > 0)
3305             {
3306               _cairo_draw_line (cr, &color1,
3307                                 x + gap_x + gap_width, y, x + width - 2, y);
3308               _cairo_draw_line (cr, &color2,
3309                                 x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
3310               _cairo_draw_line (cr, &color2,
3311                                 x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3312             }
3313           break;
3314         case  GTK_POS_BOTTOM:
3315           _cairo_draw_line (cr, &color1,
3316                             x, y, x + width - 1, y);
3317           _cairo_draw_line (cr, &color1,
3318                             x, y, x, y + height - 1);
3319           _cairo_draw_line (cr, &color2,
3320                             x + 1, y + 1, x + width - 2, y + 1);
3321           _cairo_draw_line (cr, &color2,
3322                             x + 1, y + 1, x + 1, y + height - 1);
3323           
3324           _cairo_draw_line (cr, &color3,
3325                             x + width - 2, y + 1, x + width - 2, y + height - 1);
3326           _cairo_draw_line (cr, &color4,
3327                             x + width - 1, y, x + width - 1, y + height - 1);
3328           if (gap_x > 0)
3329             {
3330               _cairo_draw_line (cr, &color4,
3331                                 x, y + height - 1, x + gap_x - 1, y + height - 1);
3332               _cairo_draw_line (cr, &color3,
3333                                 x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3334               _cairo_draw_line (cr, &color3,
3335                                 x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3336             }
3337           if ((width - (gap_x + gap_width)) > 0)
3338             {
3339               _cairo_draw_line (cr, &color4,
3340                                 x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3341               _cairo_draw_line (cr, &color3,
3342                                 x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3343               _cairo_draw_line (cr, &color3,
3344                                 x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3345             }
3346           break;
3347         case GTK_POS_LEFT:
3348           _cairo_draw_line (cr, &color1,
3349                             x, y, x + width - 1, y);
3350           _cairo_draw_line (cr, &color2,
3351                             x, y + 1, x + width - 2, y + 1);
3352           
3353           _cairo_draw_line (cr, &color3,
3354                             x, y + height - 2, x + width - 2, y + height - 2);
3355           _cairo_draw_line (cr, &color3,
3356                             x + width - 2, y + 1, x + width - 2, y + height - 2);
3357           _cairo_draw_line (cr, &color4,
3358                             x, y + height - 1, x + width - 1, y + height - 1);
3359           _cairo_draw_line (cr, &color4,
3360                             x + width - 1, y, x + width - 1, y + height - 1);
3361           if (gap_x > 0)
3362             {
3363               _cairo_draw_line (cr, &color1,
3364                                 x, y, x, y + gap_x - 1);
3365               _cairo_draw_line (cr, &color2,
3366                                 x + 1, y + 1, x + 1, y + gap_x - 1);
3367               _cairo_draw_line (cr, &color2,
3368                                 x, y + gap_x, x, y + gap_x);
3369             }
3370           if ((height - (gap_x + gap_width)) > 0)
3371             {
3372               _cairo_draw_line (cr, &color1,
3373                                 x, y + gap_x + gap_width, x, y + height - 2);
3374               _cairo_draw_line (cr, &color2,
3375                                 x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3376               _cairo_draw_line (cr, &color2,
3377                                 x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3378             }
3379           break;
3380         case GTK_POS_RIGHT:
3381           _cairo_draw_line (cr, &color1,
3382                             x, y, x + width - 1, y);
3383           _cairo_draw_line (cr, &color1,
3384                             x, y, x, y + height - 1);
3385           _cairo_draw_line (cr, &color2,
3386                             x + 1, y + 1, x + width - 1, y + 1);
3387           _cairo_draw_line (cr, &color2,
3388                             x + 1, y + 1, x + 1, y + height - 2);
3389           
3390           _cairo_draw_line (cr, &color3,
3391                             x + 1, y + height - 2, x + width - 1, y + height - 2);
3392           _cairo_draw_line (cr, &color4,
3393                             x, y + height - 1, x + width - 1, y + height - 1);
3394           if (gap_x > 0)
3395             {
3396               _cairo_draw_line (cr, &color4,
3397                                 x + width - 1, y, x + width - 1, y + gap_x - 1);
3398               _cairo_draw_line (cr, &color3,
3399                                 x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3400               _cairo_draw_line (cr, &color3,
3401                                 x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3402             }
3403           if ((height - (gap_x + gap_width)) > 0)
3404             {
3405               _cairo_draw_line (cr, &color4,
3406                                 x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3407               _cairo_draw_line (cr, &color3,
3408                                 x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3409               _cairo_draw_line (cr, &color3,
3410                                 x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3411             }
3412           break;
3413         }
3414     }
3415 }
3416
3417 static void 
3418 gtk_default_draw_extension (GtkStyle       *style,
3419                             cairo_t        *cr,
3420                             GtkStateType    state_type,
3421                             GtkShadowType   shadow_type,
3422                             GtkWidget      *widget,
3423                             const gchar    *detail,
3424                             gint            x,
3425                             gint            y,
3426                             gint            width,
3427                             gint            height,
3428                             GtkPositionType gap_side)
3429 {
3430   GdkWindow *window = gtk_widget_get_window (widget);
3431   GdkColor color1;
3432   GdkColor color2;
3433   GdkColor color3;
3434   GdkColor color4;
3435   
3436   switch (gap_side)
3437     {
3438     case GTK_POS_TOP:
3439       gtk_style_apply_default_background (style, cr, window,
3440                                           state_type,
3441                                           x + 1,
3442                                           y,
3443                                           width - 2,
3444                                           height - 1);
3445       break;
3446     case GTK_POS_BOTTOM:
3447       gtk_style_apply_default_background (style, cr, window,
3448                                           state_type,
3449                                           x + 1,
3450                                           y + 1,
3451                                           width - 2,
3452                                           height - 1);
3453       break;
3454     case GTK_POS_LEFT:
3455       gtk_style_apply_default_background (style, cr, window,
3456                                           state_type,
3457                                           x,
3458                                           y + 1,
3459                                           width - 1,
3460                                           height - 2);
3461       break;
3462     case GTK_POS_RIGHT:
3463       gtk_style_apply_default_background (style, cr, window,
3464                                           state_type,
3465                                           x + 1,
3466                                           y + 1,
3467                                           width - 1,
3468                                           height - 2);
3469       break;
3470     }
3471
3472   switch (shadow_type)
3473     {
3474     case GTK_SHADOW_NONE:
3475       return;
3476     case GTK_SHADOW_IN:
3477       color1 = style->dark[state_type];
3478       color2 = style->black;
3479       color3 = style->bg[state_type];
3480       color4 = style->light[state_type];
3481       break;
3482     case GTK_SHADOW_ETCHED_IN:
3483       color1 = style->dark[state_type];
3484       color2 = style->light[state_type];
3485       color3 = style->dark[state_type];
3486       color4 = style->light[state_type];
3487       break;
3488     case GTK_SHADOW_OUT:
3489       color1 = style->light[state_type];
3490       color2 = style->bg[state_type];
3491       color3 = style->dark[state_type];
3492       color4 = style->black;
3493       break;
3494     case GTK_SHADOW_ETCHED_OUT:
3495       color1 = style->light[state_type];
3496       color2 = style->dark[state_type];
3497       color3 = style->light[state_type];
3498       color4 = style->dark[state_type];
3499       break;
3500     }
3501
3502   cairo_set_line_width (cr, 1.0);
3503
3504   switch (shadow_type)
3505     {
3506     case GTK_SHADOW_NONE:
3507     case GTK_SHADOW_IN:
3508     case GTK_SHADOW_OUT:
3509     case GTK_SHADOW_ETCHED_IN:
3510     case GTK_SHADOW_ETCHED_OUT:
3511       switch (gap_side)
3512         {
3513         case GTK_POS_TOP:
3514           _cairo_draw_line (cr, &color1,
3515                             x, y, x, y + height - 2);
3516           _cairo_draw_line (cr, &color2,
3517                             x + 1, y, x + 1, y + height - 2);
3518           
3519           _cairo_draw_line (cr, &color3,
3520                             x + 2, y + height - 2, x + width - 2, y + height - 2);
3521           _cairo_draw_line (cr, &color3,
3522                             x + width - 2, y, x + width - 2, y + height - 2);
3523           _cairo_draw_line (cr, &color4,
3524                             x + 1, y + height - 1, x + width - 2, y + height - 1);
3525           _cairo_draw_line (cr, &color4,
3526                             x + width - 1, y, x + width - 1, y + height - 2);
3527           break;
3528         case GTK_POS_BOTTOM:
3529           _cairo_draw_line (cr, &color1,
3530                             x + 1, y, x + width - 2, y);
3531           _cairo_draw_line (cr, &color1,
3532                             x, y + 1, x, y + height - 1);
3533           _cairo_draw_line (cr, &color2,
3534                             x + 1, y + 1, x + width - 2, y + 1);
3535           _cairo_draw_line (cr, &color2,
3536                             x + 1, y + 1, x + 1, y + height - 1);
3537           
3538           _cairo_draw_line (cr, &color3,
3539                             x + width - 2, y + 2, x + width - 2, y + height - 1);
3540           _cairo_draw_line (cr, &color4,
3541                             x + width - 1, y + 1, x + width - 1, y + height - 1);
3542           break;
3543         case GTK_POS_LEFT:
3544           _cairo_draw_line (cr, &color1,
3545                             x, y, x + width - 2, y);
3546           _cairo_draw_line (cr, &color2,
3547                             x + 1, y + 1, x + width - 2, y + 1);
3548           
3549           _cairo_draw_line (cr, &color3,
3550                             x, y + height - 2, x + width - 2, y + height - 2);
3551           _cairo_draw_line (cr, &color3,
3552                             x + width - 2, y + 2, x + width - 2, y + height - 2);
3553           _cairo_draw_line (cr, &color4,
3554                             x, y + height - 1, x + width - 2, y + height - 1);
3555           _cairo_draw_line (cr, &color4,
3556                             x + width - 1, y + 1, x + width - 1, y + height - 2);
3557           break;
3558         case GTK_POS_RIGHT:
3559           _cairo_draw_line (cr, &color1,
3560                             x + 1, y, x + width - 1, y);
3561           _cairo_draw_line (cr, &color1,
3562                             x, y + 1, x, y + height - 2);
3563           _cairo_draw_line (cr, &color2,
3564                             x + 1, y + 1, x + width - 1, y + 1);
3565           _cairo_draw_line (cr, &color2,
3566                             x + 1, y + 1, x + 1, y + height - 2);
3567           
3568           _cairo_draw_line (cr, &color3,
3569                             x + 2, y + height - 2, x + width - 1, y + height - 2);
3570           _cairo_draw_line (cr, &color4,
3571                             x + 1, y + height - 1, x + width - 1, y + height - 1);
3572           break;
3573         }
3574     }
3575 }
3576
3577 static void 
3578 gtk_default_draw_focus (GtkStyle      *style,
3579                         cairo_t       *cr,
3580                         GtkStateType   state_type,
3581                         GtkWidget     *widget,
3582                         const gchar   *detail,
3583                         gint           x,
3584                         gint           y,
3585                         gint           width,
3586                         gint           height)
3587 {
3588   gboolean free_dash_list = FALSE;
3589   gint line_width = 1;
3590   gint8 *dash_list = (gint8 *) "\1\1";
3591
3592   if (widget)
3593     {
3594       gtk_widget_style_get (widget,
3595                             "focus-line-width", &line_width,
3596                             "focus-line-pattern", (gchar *)&dash_list,
3597                             NULL);
3598
3599       free_dash_list = TRUE;
3600   }
3601
3602   if (detail && !strcmp (detail, "add-mode"))
3603     {
3604       if (free_dash_list)
3605         g_free (dash_list);
3606
3607       dash_list = (gint8 *) "\4\4";
3608       free_dash_list = FALSE;
3609     }
3610
3611   if (detail && !strcmp (detail, "colorwheel_light"))
3612     cairo_set_source_rgb (cr, 0., 0., 0.);
3613   else if (detail && !strcmp (detail, "colorwheel_dark"))
3614     cairo_set_source_rgb (cr, 1., 1., 1.);
3615   else
3616     gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3617
3618   cairo_set_line_width (cr, line_width);
3619
3620   if (dash_list[0])
3621     {
3622       gint n_dashes = strlen ((const gchar *) dash_list);
3623       gdouble *dashes = g_new (gdouble, n_dashes);
3624       gdouble total_length = 0;
3625       gdouble dash_offset;
3626       gint i;
3627
3628       for (i = 0; i < n_dashes; i++)
3629         {
3630           dashes[i] = dash_list[i];
3631           total_length += dash_list[i];
3632         }
3633
3634       /* The dash offset here aligns the pattern to integer pixels
3635        * by starting the dash at the right side of the left border
3636        * Negative dash offsets in cairo don't work
3637        * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
3638        */
3639       dash_offset = - line_width / 2.;
3640       while (dash_offset < 0)
3641         dash_offset += total_length;
3642       
3643       cairo_set_dash (cr, dashes, n_dashes, dash_offset);
3644       g_free (dashes);
3645     }
3646
3647   cairo_rectangle (cr,
3648                    x + line_width / 2.,
3649                    y + line_width / 2.,
3650                    width - line_width,
3651                    height - line_width);
3652   cairo_stroke (cr);
3653
3654   if (free_dash_list)
3655     g_free (dash_list);
3656 }
3657
3658 static void 
3659 gtk_default_draw_slider (GtkStyle      *style,
3660                          cairo_t       *cr,
3661                          GtkStateType   state_type,
3662                          GtkShadowType  shadow_type,
3663                          GtkWidget     *widget,
3664                          const gchar   *detail,
3665                          gint           x,
3666                          gint           y,
3667                          gint           width,
3668                          gint           height,
3669                          GtkOrientation orientation)
3670 {
3671   gtk_paint_box (style, cr, state_type, shadow_type,
3672                        widget, detail, x, y, width, height);
3673
3674   if (detail &&
3675       (strcmp ("hscale", detail) == 0 ||
3676        strcmp ("vscale", detail) == 0))
3677     {
3678       if (orientation == GTK_ORIENTATION_HORIZONTAL)
3679         gtk_paint_vline (style, cr, state_type, widget, detail, 
3680                                y + style->ythickness, 
3681                                y + height - style->ythickness - 1, x + width / 2);
3682       else
3683         gtk_paint_hline (style, cr, state_type, widget, detail, 
3684                                x + style->xthickness, 
3685                                x + width - style->xthickness - 1, y + height / 2);
3686     }
3687 }
3688
3689 static void
3690 draw_dot (cairo_t    *cr,
3691           GdkColor   *light,
3692           GdkColor   *dark,
3693           gint        x,
3694           gint        y,
3695           gushort     size)
3696 {
3697   size = CLAMP (size, 2, 3);
3698
3699   if (size == 2)
3700     {
3701       _cairo_draw_point (cr, light, x, y);
3702       _cairo_draw_point (cr, light, x+1, y+1);
3703     }
3704   else if (size == 3)
3705     {
3706       _cairo_draw_point (cr, light, x, y);
3707       _cairo_draw_point (cr, light, x+1, y);
3708       _cairo_draw_point (cr, light, x, y+1);
3709       _cairo_draw_point (cr, dark, x+1, y+2);
3710       _cairo_draw_point (cr, dark, x+2, y+1);
3711       _cairo_draw_point (cr, dark, x+2, y+2);
3712     }
3713 }
3714
3715 static void 
3716 gtk_default_draw_handle (GtkStyle      *style,
3717                          cairo_t       *cr,
3718                          GtkStateType   state_type,
3719                          GtkShadowType  shadow_type,
3720                          GtkWidget     *widget,
3721                          const gchar   *detail,
3722                          gint           x,
3723                          gint           y,
3724                          gint           width,
3725                          gint           height,
3726                          GtkOrientation orientation)
3727 {
3728   gint xx, yy;
3729   gint xthick, ythick;
3730   GdkColor light, dark;
3731   
3732   gtk_paint_box (style, cr, state_type, shadow_type, widget, 
3733                        detail, x, y, width, height);
3734   
3735   if (detail && !strcmp (detail, "paned"))
3736     {
3737       /* we want to ignore the shadow border in paned widgets */
3738       xthick = 0;
3739       ythick = 0;
3740
3741       if (state_type == GTK_STATE_SELECTED && widget && !gtk_widget_has_focus (widget))
3742           _gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &light,
3743                             LIGHTNESS_MULT);
3744       else
3745         light = style->light[state_type];
3746
3747       dark = style->black;
3748     }
3749   else
3750     {
3751       xthick = style->xthickness;
3752       ythick = style->ythickness;
3753
3754       light = style->light[state_type];
3755       dark = style->dark[state_type];
3756     }
3757   
3758   cairo_rectangle(cr, x + xthick, y + ythick,
3759                   width - (xthick * 2), height - (ythick * 2));
3760   cairo_clip (cr);
3761
3762   if (detail && !strcmp (detail, "paned"))
3763     {
3764       if (orientation == GTK_ORIENTATION_HORIZONTAL)
3765         for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
3766           draw_dot (cr, &light, &dark, xx, y + height/2 - 1, 3);
3767       else
3768         for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
3769           draw_dot (cr, &light, &dark, x + width/2 - 1, yy, 3);
3770     }
3771   else
3772     {
3773       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
3774         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
3775           {
3776             draw_dot (cr, &light, &dark, xx, yy, 2);
3777             draw_dot (cr, &light, &dark, xx + 3, yy + 1, 2);
3778           }
3779     }
3780 }
3781
3782 static void
3783 gtk_default_draw_expander (GtkStyle        *style,
3784                            cairo_t         *cr,
3785                            GtkStateType     state_type,
3786                            GtkWidget       *widget,
3787                            const gchar     *detail,
3788                            gint             x,
3789                            gint             y,
3790                            GtkExpanderStyle expander_style)
3791 {
3792 #define DEFAULT_EXPANDER_SIZE 12
3793
3794   gint expander_size;
3795   gint line_width;
3796   double vertical_overshoot;
3797   int diameter;
3798   double radius;
3799   double interp;                /* interpolation factor for center position */
3800   double x_double_horz, y_double_horz;
3801   double x_double_vert, y_double_vert;
3802   double x_double, y_double;
3803   gint degrees = 0;
3804
3805   if (widget &&
3806       gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
3807                                             "expander-size"))
3808     {
3809       gtk_widget_style_get (widget,
3810                             "expander-size", &expander_size,
3811                             NULL);
3812     }
3813   else
3814     expander_size = DEFAULT_EXPANDER_SIZE;
3815     
3816   line_width = MAX (1, expander_size/9);
3817
3818   switch (expander_style)
3819     {
3820     case GTK_EXPANDER_COLLAPSED:
3821       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
3822       interp = 0.0;
3823       break;
3824     case GTK_EXPANDER_SEMI_COLLAPSED:
3825       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
3826       interp = 0.25;
3827       break;
3828     case GTK_EXPANDER_SEMI_EXPANDED:
3829       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
3830       interp = 0.75;
3831       break;
3832     case GTK_EXPANDER_EXPANDED:
3833       degrees = 90;
3834       interp = 1.0;
3835       break;
3836     default:
3837       g_assert_not_reached ();
3838     }
3839
3840   /* Compute distance that the stroke extends beyonds the end
3841    * of the triangle we draw.
3842    */
3843   vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
3844
3845   /* For odd line widths, we end the vertical line of the triangle
3846    * at a half pixel, so we round differently.
3847    */
3848   if (line_width % 2 == 1)
3849     vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
3850   else
3851     vertical_overshoot = ceil (vertical_overshoot);
3852
3853   /* Adjust the size of the triangle we draw so that the entire stroke fits
3854    */
3855   diameter = MAX (3, expander_size - 2 * vertical_overshoot);
3856
3857   /* If the line width is odd, we want the diameter to be even,
3858    * and vice versa, so force the sum to be odd. This relationship
3859    * makes the point of the triangle look right.
3860    */
3861   diameter -= (1 - (diameter + line_width) % 2);
3862   
3863   radius = diameter / 2.;
3864
3865   /* Adjust the center so that the stroke is properly aligned with
3866    * the pixel grid. The center adjustment is different for the
3867    * horizontal and vertical orientations. For intermediate positions
3868    * we interpolate between the two.
3869    */
3870   x_double_vert = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.;
3871   y_double_vert = y - 0.5;
3872
3873   x_double_horz = x - 0.5;
3874   y_double_horz = floor (y - (radius + line_width) / 2.) + (radius + line_width) / 2.;
3875
3876   x_double = x_double_vert * (1 - interp) + x_double_horz * interp;
3877   y_double = y_double_vert * (1 - interp) + y_double_horz * interp;
3878   
3879   cairo_translate (cr, x_double, y_double);
3880   cairo_rotate (cr, degrees * G_PI / 180);
3881
3882   cairo_move_to (cr, - radius / 2., - radius);
3883   cairo_line_to (cr,   radius / 2.,   0);
3884   cairo_line_to (cr, - radius / 2.,   radius);
3885   cairo_close_path (cr);
3886   
3887   cairo_set_line_width (cr, line_width);
3888
3889   if (state_type == GTK_STATE_PRELIGHT)
3890     gdk_cairo_set_source_color (cr,
3891                                 &style->fg[GTK_STATE_PRELIGHT]);
3892   else if (state_type == GTK_STATE_ACTIVE)
3893     gdk_cairo_set_source_color (cr,
3894                                 &style->light[GTK_STATE_ACTIVE]);
3895   else
3896     gdk_cairo_set_source_color (cr,
3897                                 &style->base[GTK_STATE_NORMAL]);
3898   
3899   cairo_fill_preserve (cr);
3900   
3901   gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3902   cairo_stroke (cr);
3903 }
3904
3905 static void
3906 gtk_default_draw_layout (GtkStyle        *style,
3907                          cairo_t         *cr,
3908                          GtkStateType     state_type,
3909                          gboolean         use_text,
3910                          GtkWidget       *widget,
3911                          const gchar     *detail,
3912                          gint             x,
3913                          gint             y,
3914                          PangoLayout     *layout)
3915 {
3916   GdkColor *gc;
3917   const PangoMatrix *matrix;
3918
3919   matrix = pango_context_get_matrix (pango_layout_get_context (layout));
3920   if (matrix)
3921     {
3922       cairo_matrix_t cairo_matrix;
3923       PangoMatrix tmp_matrix;
3924       PangoRectangle rect;
3925       
3926       cairo_matrix_init (&cairo_matrix,
3927                          matrix->xx, matrix->yx,
3928                          matrix->xy, matrix->yy,
3929                          matrix->x0, matrix->y0);
3930
3931       pango_layout_get_extents (layout, NULL, &rect);
3932       pango_matrix_transform_rectangle (matrix, &rect);
3933       pango_extents_to_pixels (&rect, NULL);
3934                                           
3935       tmp_matrix = *matrix;
3936       cairo_matrix.x0 += x - rect.x;
3937       cairo_matrix.y0 += y - rect.y;
3938
3939       cairo_set_matrix (cr, &cairo_matrix);
3940     }
3941   else
3942     cairo_translate (cr, x, y);
3943
3944   cairo_new_path (cr);
3945
3946   if (state_type == GTK_STATE_INSENSITIVE)
3947     {
3948       gdk_cairo_set_source_color (cr, &style->white);
3949       cairo_move_to (cr, 1, 1);
3950       _gtk_pango_fill_layout (cr, layout);
3951       cairo_new_path (cr);
3952     }
3953
3954   gc = use_text ? &style->text[state_type] : &style->fg[state_type];
3955
3956   gdk_cairo_set_source_color (cr, gc);
3957
3958   pango_cairo_show_layout (cr, layout);
3959 }
3960
3961 static void
3962 gtk_default_draw_resize_grip (GtkStyle       *style,
3963                               cairo_t        *cr,
3964                               GtkStateType    state_type,
3965                               GtkWidget      *widget,
3966                               const gchar    *detail,
3967                               GdkWindowEdge   edge,
3968                               gint            x,
3969                               gint            y,
3970                               gint            width,
3971                               gint            height)
3972 {
3973   gint skip;
3974
3975   cairo_rectangle (cr, x, y, width, height);
3976   cairo_clip (cr);
3977
3978   cairo_set_line_width (cr, 1.0);
3979
3980   skip = -1;
3981   switch (edge)
3982     {
3983     case GDK_WINDOW_EDGE_NORTH_WEST:
3984       /* make it square */
3985       if (width < height)
3986         height = width;
3987       else if (height < width)
3988         width = height;
3989       skip = 2;
3990       break;
3991     case GDK_WINDOW_EDGE_NORTH:
3992       if (width < height)
3993         height = width;
3994       break;
3995     case GDK_WINDOW_EDGE_NORTH_EAST:
3996       /* make it square, aligning to top right */
3997       if (width < height)
3998         height = width;
3999       else if (height < width)
4000         {
4001           x += (width - height);
4002           width = height;
4003         }
4004       skip = 3;
4005       break;
4006     case GDK_WINDOW_EDGE_WEST:
4007       if (height < width)
4008         width = height;
4009       break;
4010     case GDK_WINDOW_EDGE_EAST:
4011       /* aligning to right */
4012       if (height < width)
4013         {
4014           x += (width - height);
4015           width = height;
4016         }
4017       break;
4018     case GDK_WINDOW_EDGE_SOUTH_WEST:
4019       /* make it square, aligning to bottom left */
4020       if (width < height)
4021         {
4022           y += (height - width);
4023           height = width;
4024         }
4025       else if (height < width)
4026         width = height;
4027       skip = 1;
4028       break;
4029     case GDK_WINDOW_EDGE_SOUTH:
4030       /* align to bottom */
4031       if (width < height)
4032         {
4033           y += (height - width);
4034           height = width;
4035         }
4036       break;
4037     case GDK_WINDOW_EDGE_SOUTH_EAST:
4038       /* make it square, aligning to bottom right */
4039       if (width < height)
4040         {
4041           y += (height - width);
4042           height = width;
4043         }
4044       else if (height < width)
4045         {
4046           x += (width - height);
4047           width = height;
4048         }
4049       skip = 0;
4050       break;
4051     default:
4052       g_assert_not_reached ();
4053     }
4054   
4055   switch (edge)
4056     {
4057     case GDK_WINDOW_EDGE_WEST:
4058     case GDK_WINDOW_EDGE_EAST:
4059       {
4060         gint xi;
4061
4062         xi = x;
4063
4064         while (xi < x + width)
4065           {
4066             _cairo_draw_line (cr,
4067                               &style->light[state_type],
4068                               xi, y,
4069                               xi, y + height);
4070
4071             xi++;
4072             _cairo_draw_line (cr,
4073                               &style->dark[state_type],
4074                               xi, y,
4075                               xi, y + height);
4076
4077             xi += 2;
4078           }
4079       }
4080       break;
4081     case GDK_WINDOW_EDGE_NORTH:
4082     case GDK_WINDOW_EDGE_SOUTH:
4083       {
4084         gint yi;
4085
4086         yi = y;
4087
4088         while (yi < y + height)
4089           {
4090             _cairo_draw_line (cr,
4091                               &style->light[state_type],
4092                               x, yi,
4093                               x + width, yi);
4094
4095             yi++;
4096             _cairo_draw_line (cr,
4097                               &style->dark[state_type],
4098                               x, yi,
4099                               x + width, yi);
4100
4101             yi+= 2;
4102           }
4103       }
4104       break;
4105     case GDK_WINDOW_EDGE_NORTH_WEST:
4106       {
4107         gint xi, yi;
4108
4109         xi = x + width;
4110         yi = y + height;
4111
4112         while (xi > x + 3)
4113           {
4114             _cairo_draw_line (cr,
4115                               &style->dark[state_type],
4116                               xi, y,
4117                               x, yi);
4118
4119             --xi;
4120             --yi;
4121
4122             _cairo_draw_line (cr,
4123                               &style->dark[state_type],
4124                               xi, y,
4125                               x, yi);
4126
4127             --xi;
4128             --yi;
4129
4130             _cairo_draw_line (cr,
4131                               &style->light[state_type],
4132                               xi, y,
4133                               x, yi);
4134
4135             xi -= 3;
4136             yi -= 3;
4137             
4138           }
4139       }
4140       break;
4141     case GDK_WINDOW_EDGE_NORTH_EAST:
4142       {
4143         gint xi, yi;
4144
4145         xi = x;
4146         yi = y + height;
4147
4148         while (xi < (x + width - 3))
4149           {
4150             _cairo_draw_line (cr,
4151                               &style->light[state_type],
4152                               xi, y,
4153                               x + width, yi);                           
4154
4155             ++xi;
4156             --yi;
4157             
4158             _cairo_draw_line (cr,
4159                               &style->dark[state_type],
4160                               xi, y,
4161                               x + width, yi);                           
4162
4163             ++xi;
4164             --yi;
4165             
4166             _cairo_draw_line (cr,
4167                               &style->dark[state_type],
4168                               xi, y,
4169                               x + width, yi);
4170
4171             xi += 3;
4172             yi -= 3;
4173           }
4174       }
4175       break;
4176     case GDK_WINDOW_EDGE_SOUTH_WEST:
4177       {
4178         gint xi, yi;
4179
4180         xi = x + width;
4181         yi = y;
4182
4183         while (xi > x + 3)
4184           {
4185             _cairo_draw_line (cr,
4186                               &style->dark[state_type],
4187                               x, yi,
4188                               xi, y + height);
4189
4190             --xi;
4191             ++yi;
4192
4193             _cairo_draw_line (cr,
4194                               &style->dark[state_type],
4195                               x, yi,
4196                               xi, y + height);
4197
4198             --xi;
4199             ++yi;
4200
4201             _cairo_draw_line (cr,
4202                               &style->light[state_type],
4203                               x, yi,
4204                               xi, y + height);
4205
4206             xi -= 3;
4207             yi += 3;
4208             
4209           }
4210       }
4211       break;
4212     case GDK_WINDOW_EDGE_SOUTH_EAST:
4213       {
4214         gint xi, yi;
4215
4216         xi = x;
4217         yi = y;
4218
4219         while (xi < (x + width - 3))
4220           {
4221             _cairo_draw_line (cr,
4222                               &style->light[state_type],
4223                               xi, y + height,
4224                               x + width, yi);                           
4225
4226             ++xi;
4227             ++yi;
4228             
4229             _cairo_draw_line (cr,
4230                               &style->dark[state_type],
4231                               xi, y + height,
4232                               x + width, yi);                           
4233
4234             ++xi;
4235             ++yi;
4236             
4237             _cairo_draw_line (cr,
4238                               &style->dark[state_type],
4239                               xi, y + height,
4240                               x + width, yi);
4241
4242             xi += 3;
4243             yi += 3;
4244           }
4245       }
4246       break;
4247     default:
4248       g_assert_not_reached ();
4249       break;
4250     }
4251 }
4252
4253 static void
4254 gtk_default_draw_spinner (GtkStyle     *style,
4255                           cairo_t      *cr,
4256                           GtkStateType  state_type,
4257                           GtkWidget    *widget,
4258                           const gchar  *detail,
4259                           guint         step,
4260                           gint          x,
4261                           gint          y,
4262                           gint          width,
4263                           gint          height)
4264 {
4265   GdkColor *color;
4266   guint num_steps;
4267   gdouble dx, dy;
4268   gdouble radius;
4269   gdouble half;
4270   gint i;
4271   guint real_step;
4272
4273   gtk_style_get (style, GTK_TYPE_SPINNER,
4274                  "num-steps", &num_steps,
4275                  NULL);
4276   real_step = step % num_steps;
4277
4278   /* set a clip region for the expose event */
4279   cairo_rectangle (cr, x, y, width, height);
4280   cairo_clip (cr);
4281
4282   cairo_translate (cr, x, y);
4283
4284   /* draw clip region */
4285   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
4286
4287   color = &style->fg[state_type];
4288   dx = width / 2;
4289   dy = height / 2;
4290   radius = MIN (width / 2, height / 2);
4291   half = num_steps / 2;
4292
4293   for (i = 0; i < num_steps; i++)
4294     {
4295       gint inset = 0.7 * radius;
4296
4297       /* transparency is a function of time and intial value */
4298       gdouble t = (gdouble) ((i + num_steps - real_step)
4299                              % num_steps) / num_steps;
4300
4301       cairo_save (cr);
4302
4303       cairo_set_source_rgba (cr,
4304                              color->red / 65535.,
4305                              color->green / 65535.,
4306                              color->blue / 65535.,
4307                              t);
4308
4309       cairo_set_line_width (cr, 2.0);
4310       cairo_move_to (cr,
4311                      dx + (radius - inset) * cos (i * G_PI / half),
4312                      dy + (radius - inset) * sin (i * G_PI / half));
4313       cairo_line_to (cr,
4314                      dx + radius * cos (i * G_PI / half),
4315                      dy + radius * sin (i * G_PI / half));
4316       cairo_stroke (cr);
4317
4318       cairo_restore (cr);
4319     }
4320 }
4321
4322 void
4323 _gtk_style_shade (const GdkColor *a,
4324                   GdkColor       *b,
4325                   gdouble         k)
4326 {
4327   gdouble red;
4328   gdouble green;
4329   gdouble blue;
4330   
4331   red = (gdouble) a->red / 65535.0;
4332   green = (gdouble) a->green / 65535.0;
4333   blue = (gdouble) a->blue / 65535.0;
4334   
4335   rgb_to_hls (&red, &green, &blue);
4336   
4337   green *= k;
4338   if (green > 1.0)
4339     green = 1.0;
4340   else if (green < 0.0)
4341     green = 0.0;
4342   
4343   blue *= k;
4344   if (blue > 1.0)
4345     blue = 1.0;
4346   else if (blue < 0.0)
4347     blue = 0.0;
4348   
4349   hls_to_rgb (&red, &green, &blue);
4350   
4351   b->red = red * 65535.0;
4352   b->green = green * 65535.0;
4353   b->blue = blue * 65535.0;
4354 }
4355
4356 static void
4357 rgb_to_hls (gdouble *r,
4358             gdouble *g,
4359             gdouble *b)
4360 {
4361   gdouble min;
4362   gdouble max;
4363   gdouble red;
4364   gdouble green;
4365   gdouble blue;
4366   gdouble h, l, s;
4367   gdouble delta;
4368   
4369   red = *r;
4370   green = *g;
4371   blue = *b;
4372   
4373   if (red > green)
4374     {
4375       if (red > blue)
4376         max = red;
4377       else
4378         max = blue;
4379       
4380       if (green < blue)
4381         min = green;
4382       else
4383         min = blue;
4384     }
4385   else
4386     {
4387       if (green > blue)
4388         max = green;
4389       else
4390         max = blue;
4391       
4392       if (red < blue)
4393         min = red;
4394       else
4395         min = blue;
4396     }
4397   
4398   l = (max + min) / 2;
4399   s = 0;
4400   h = 0;
4401   
4402   if (max != min)
4403     {
4404       if (l <= 0.5)
4405         s = (max - min) / (max + min);
4406       else
4407         s = (max - min) / (2 - max - min);
4408       
4409       delta = max -min;
4410       if (red == max)
4411         h = (green - blue) / delta;
4412       else if (green == max)
4413         h = 2 + (blue - red) / delta;
4414       else if (blue == max)
4415         h = 4 + (red - green) / delta;
4416       
4417       h *= 60;
4418       if (h < 0.0)
4419         h += 360;
4420     }
4421   
4422   *r = h;
4423   *g = l;
4424   *b = s;
4425 }
4426
4427 static void
4428 hls_to_rgb (gdouble *h,
4429             gdouble *l,
4430             gdouble *s)
4431 {
4432   gdouble hue;
4433   gdouble lightness;
4434   gdouble saturation;
4435   gdouble m1, m2;
4436   gdouble r, g, b;
4437   
4438   lightness = *l;
4439   saturation = *s;
4440   
4441   if (lightness <= 0.5)
4442     m2 = lightness * (1 + saturation);
4443   else
4444     m2 = lightness + saturation - lightness * saturation;
4445   m1 = 2 * lightness - m2;
4446   
4447   if (saturation == 0)
4448     {
4449       *h = lightness;
4450       *l = lightness;
4451       *s = lightness;
4452     }
4453   else
4454     {
4455       hue = *h + 120;
4456       while (hue > 360)
4457         hue -= 360;
4458       while (hue < 0)
4459         hue += 360;
4460       
4461       if (hue < 60)
4462         r = m1 + (m2 - m1) * hue / 60;
4463       else if (hue < 180)
4464         r = m2;
4465       else if (hue < 240)
4466         r = m1 + (m2 - m1) * (240 - hue) / 60;
4467       else
4468         r = m1;
4469       
4470       hue = *h;
4471       while (hue > 360)
4472         hue -= 360;
4473       while (hue < 0)
4474         hue += 360;
4475       
4476       if (hue < 60)
4477         g = m1 + (m2 - m1) * hue / 60;
4478       else if (hue < 180)
4479         g = m2;
4480       else if (hue < 240)
4481         g = m1 + (m2 - m1) * (240 - hue) / 60;
4482       else
4483         g = m1;
4484       
4485       hue = *h - 120;
4486       while (hue > 360)
4487         hue -= 360;
4488       while (hue < 0)
4489         hue += 360;
4490       
4491       if (hue < 60)
4492         b = m1 + (m2 - m1) * hue / 60;
4493       else if (hue < 180)
4494         b = m2;
4495       else if (hue < 240)
4496         b = m1 + (m2 - m1) * (240 - hue) / 60;
4497       else
4498         b = m1;
4499       
4500       *h = r;
4501       *l = g;
4502       *s = b;
4503     }
4504 }
4505
4506
4507 /**
4508  * gtk_paint_hline:
4509  * @style: a #GtkStyle
4510  * @cr: a #caio_t
4511  * @state_type: a state
4512  * @widget: (allow-none): the widget
4513  * @detail: (allow-none): a style detail
4514  * @x1: the starting x coordinate
4515  * @x2: the ending x coordinate
4516  * @y: the y coordinate
4517  *
4518  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @cr
4519  * using the given style and state.
4520  **/ 
4521 void 
4522 gtk_paint_hline (GtkStyle           *style,
4523                  cairo_t            *cr,
4524                  GtkStateType        state_type,
4525                  GtkWidget          *widget,
4526                  const gchar        *detail,
4527                  gint                x1,
4528                  gint                x2,
4529                  gint                y)
4530 {
4531   g_return_if_fail (GTK_IS_STYLE (style));
4532   g_return_if_fail (cr != NULL);
4533   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
4534
4535   cairo_save (cr);
4536
4537   GTK_STYLE_GET_CLASS (style)->draw_hline (style, cr, state_type,
4538                                            widget, detail,
4539                                            x1, x2, y);
4540
4541   cairo_restore (cr);
4542 }
4543
4544 /**
4545  * gtk_paint_vline:
4546  * @style: a #GtkStyle
4547  * @cr: a #cairo_t
4548  * @state_type: a state
4549  * @widget: (allow-none): the widget
4550  * @detail: (allow-none): a style detail
4551  * @y1_: the starting y coordinate
4552  * @y2_: the ending y coordinate
4553  * @x: the x coordinate
4554  *
4555  * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @cr
4556  * using the given style and state.
4557  */
4558 void
4559 gtk_paint_vline (GtkStyle           *style,
4560                  cairo_t            *cr,
4561                  GtkStateType        state_type,
4562                  GtkWidget          *widget,
4563                  const gchar        *detail,
4564                  gint                y1_,
4565                  gint                y2_,
4566                  gint                x)
4567 {
4568   g_return_if_fail (GTK_IS_STYLE (style));
4569   g_return_if_fail (cr != NULL);
4570   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
4571
4572   cairo_save (cr);
4573
4574   GTK_STYLE_GET_CLASS (style)->draw_vline (style, cr, state_type,
4575                                            widget, detail,
4576                                            y1_, y2_, x);
4577
4578   cairo_restore (cr);
4579 }
4580
4581 /**
4582  * gtk_paint_shadow:
4583  * @style: a #GtkStyle
4584  * @cr: a #cairo_t
4585  * @state_type: a state
4586  * @shadow_type: type of shadow to draw
4587  * @widget: (allow-none): the widget
4588  * @detail: (allow-none): a style detail
4589  * @x: x origin of the rectangle
4590  * @y: y origin of the rectangle
4591  * @width: width of the rectangle
4592  * @height: width of the rectangle
4593  *
4594  * Draws a shadow around the given rectangle in @cr 
4595  * using the given style and state and shadow type.
4596  */
4597 void
4598 gtk_paint_shadow (GtkStyle           *style,
4599                   cairo_t            *cr,
4600                   GtkStateType        state_type,
4601                   GtkShadowType       shadow_type,
4602                   GtkWidget          *widget,
4603                   const gchar        *detail,
4604                   gint                x,
4605                   gint                y,
4606                   gint                width,
4607                   gint                height)
4608 {
4609   g_return_if_fail (GTK_IS_STYLE (style));
4610   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4611   g_return_if_fail (cr != NULL);
4612   g_return_if_fail (width >= 0);
4613   g_return_if_fail (height >= 0);
4614
4615   cairo_save (cr);
4616
4617   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, cr, state_type, shadow_type,
4618                                             widget, detail,
4619                                             x, y, width, height);
4620
4621   cairo_restore (cr);
4622 }
4623
4624 /**
4625  * gtk_paint_arrow:
4626  * @style: a #GtkStyle
4627  * @cr: a #cairo_t
4628  * @state_type: a state
4629  * @shadow_type: the type of shadow to draw
4630  * @widget: (allow-none): the widget
4631  * @detail: (allow-none): a style detail
4632  * @arrow_type: the type of arrow to draw
4633  * @fill: %TRUE if the arrow tip should be filled
4634  * @x: x origin of the rectangle to draw the arrow in
4635  * @y: y origin of the rectangle to draw the arrow in
4636  * @width: width of the rectangle to draw the arrow in
4637  * @height: height of the rectangle to draw the arrow in
4638  * 
4639  * Draws an arrow in the given rectangle on @cr using the given 
4640  * parameters. @arrow_type determines the direction of the arrow.
4641  */
4642 void
4643 gtk_paint_arrow (GtkStyle           *style,
4644                  cairo_t            *cr,
4645                  GtkStateType        state_type,
4646                  GtkShadowType       shadow_type,
4647                  GtkWidget          *widget,
4648                  const gchar        *detail,
4649                  GtkArrowType        arrow_type,
4650                  gboolean            fill,
4651                  gint                x,
4652                  gint                y,
4653                  gint                width,
4654                  gint                height)
4655 {
4656   g_return_if_fail (GTK_IS_STYLE (style));
4657   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
4658   g_return_if_fail (cr != NULL);
4659   g_return_if_fail (width >= 0);
4660   g_return_if_fail (height >= 0);
4661
4662   cairo_save (cr);
4663
4664   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, cr, state_type, shadow_type,
4665                                            widget, detail,
4666                                            arrow_type, fill, x, y, width, height);
4667
4668   cairo_restore (cr);
4669 }
4670
4671 /**
4672  * gtk_paint_diamond:
4673  * @style: a #GtkStyle
4674  * @cr: a #cairo_t
4675  * @state_type: a state
4676  * @shadow_type: the type of shadow to draw
4677  * @widget: (allow-none): the widget
4678  * @detail: (allow-none): a style detail
4679  * @x: x origin of the rectangle to draw the diamond in
4680  * @y: y origin of the rectangle to draw the diamond in
4681  * @width: width of the rectangle to draw the diamond in
4682  * @height: height of the rectangle to draw the diamond in
4683  *
4684  * Draws a diamond in the given rectangle on @window using the given
4685  * parameters.
4686  */
4687 void
4688 gtk_paint_diamond (GtkStyle           *style,
4689                    cairo_t            *cr,
4690                    GtkStateType        state_type,
4691                    GtkShadowType       shadow_type,
4692                    GtkWidget          *widget,
4693                    const gchar        *detail,
4694                    gint                x,
4695                    gint                y,
4696                    gint                width,
4697                    gint                height)
4698 {
4699   g_return_if_fail (GTK_IS_STYLE (style));
4700   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
4701   g_return_if_fail (cr != NULL);
4702   g_return_if_fail (width >= 0);
4703   g_return_if_fail (height >= 0);
4704
4705   cairo_save (cr);
4706
4707   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, cr, state_type, shadow_type,
4708                                              widget, detail,
4709                                              x, y, width, height);
4710
4711   cairo_restore (cr);
4712 }
4713
4714 /**
4715  * gtk_paint_box:
4716  * @style: a #GtkStyle
4717  * @cr: a #cairo_t
4718  * @state_type: a state
4719  * @shadow_type: the type of shadow to draw
4720  * @widget: (allow-none): the widget
4721  * @detail: (allow-none): a style detail
4722  * @x: x origin of the box
4723  * @y: y origin of the box
4724  * @width: the width of the box
4725  * @height: the height of the box
4726  * 
4727  * Draws a box on @cr with the given parameters.
4728  */
4729 void
4730 gtk_paint_box (GtkStyle           *style,
4731                cairo_t            *cr,
4732                GtkStateType        state_type,
4733                GtkShadowType       shadow_type,
4734                GtkWidget          *widget,
4735                const gchar        *detail,
4736                gint                x,
4737                gint                y,
4738                gint                width,
4739                gint                height)
4740 {
4741   g_return_if_fail (GTK_IS_STYLE (style));
4742   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
4743   g_return_if_fail (cr != NULL);
4744
4745   cairo_save (cr);
4746
4747   GTK_STYLE_GET_CLASS (style)->draw_box (style, cr, state_type, shadow_type,
4748                                          widget, detail,
4749                                          x, y, width, height);
4750
4751   cairo_restore (cr);
4752 }
4753
4754 /**
4755  * gtk_paint_flat_box:
4756  * @style: a #GtkStyle
4757  * @cr: a #cairo_t
4758  * @state_type: a state
4759  * @shadow_type: the type of shadow to draw
4760  * @area: (allow-none): clip rectangle, or %NULL if the
4761  *        output should not be clipped
4762  * @widget: (allow-none): the widget
4763  * @detail: (allow-none): a style detail
4764  * @x: x origin of the box
4765  * @y: y origin of the box
4766  * @width: the width of the box
4767  * @height: the height of the box
4768  * 
4769  * Draws a flat box on @cr with the given parameters.
4770  */
4771 void
4772 gtk_paint_flat_box (GtkStyle           *style,
4773                     cairo_t            *cr,
4774                     GtkStateType        state_type,
4775                     GtkShadowType       shadow_type,
4776                     GtkWidget          *widget,
4777                     const gchar        *detail,
4778                     gint                x,
4779                     gint                y,
4780                     gint                width,
4781                     gint                height)
4782 {
4783   g_return_if_fail (GTK_IS_STYLE (style));
4784   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
4785   g_return_if_fail (cr != NULL);
4786   g_return_if_fail (width >= 0);
4787   g_return_if_fail (height >= 0);
4788
4789   cairo_save (cr);
4790
4791   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, cr, state_type, shadow_type,
4792                                               widget, detail,
4793                                               x, y, width, height);
4794
4795   cairo_restore (cr);
4796 }
4797
4798 /**
4799  * gtk_paint_check:
4800  * @style: a #GtkStyle
4801  * @cr: a #cairo_t
4802  * @state_type: a state
4803  * @shadow_type: the type of shadow to draw
4804  * @widget: (allow-none): the widget
4805  * @detail: (allow-none): a style detail
4806  * @x: x origin of the rectangle to draw the check in
4807  * @y: y origin of the rectangle to draw the check in
4808  * @width: the width of the rectangle to draw the check in
4809  * @height: the height of the rectangle to draw the check in
4810  * 
4811  * Draws a check button indicator in the given rectangle on @cr with 
4812  * the given parameters.
4813  */
4814 void
4815 gtk_paint_check (GtkStyle           *style,
4816                  cairo_t            *cr,
4817                  GtkStateType        state_type,
4818                  GtkShadowType       shadow_type,
4819                  GtkWidget          *widget,
4820                  const gchar        *detail,
4821                  gint                x,
4822                  gint                y,
4823                  gint                width,
4824                  gint                height)
4825 {
4826   g_return_if_fail (GTK_IS_STYLE (style));
4827   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
4828   g_return_if_fail (cr != NULL);
4829
4830   cairo_save (cr);
4831
4832   GTK_STYLE_GET_CLASS (style)->draw_check (style, cr, state_type, shadow_type,
4833                                            widget, detail,
4834                                            x, y, width, height);
4835
4836   cairo_restore (cr);
4837 }
4838
4839 /**
4840  * gtk_paint_option:
4841  * @style: a #GtkStyle
4842  * @cr: a #cairo_t
4843  * @state_type: a state
4844  * @shadow_type: the type of shadow to draw
4845  * @widget: (allow-none): the widget
4846  * @detail: (allow-none): a style detail
4847  * @x: x origin of the rectangle to draw the option in
4848  * @y: y origin of the rectangle to draw the option in
4849  * @width: the width of the rectangle to draw the option in
4850  * @height: the height of the rectangle to draw the option in
4851  *
4852  * Draws a radio button indicator in the given rectangle on @cr with 
4853  * the given parameters.
4854  */
4855 void
4856 gtk_paint_option (GtkStyle           *style,
4857                   cairo_t            *cr,
4858                   GtkStateType        state_type,
4859                   GtkShadowType       shadow_type,
4860                   GtkWidget          *widget,
4861                   const gchar        *detail,
4862                   gint                x,
4863                   gint                y,
4864                   gint                width,
4865                   gint                height)
4866 {
4867   g_return_if_fail (GTK_IS_STYLE (style));
4868   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
4869   g_return_if_fail (cr != NULL);
4870
4871   cairo_save (cr);
4872
4873   GTK_STYLE_GET_CLASS (style)->draw_option (style, cr, state_type, shadow_type,
4874                                             widget, detail,
4875                                             x, y, width, height);
4876
4877   cairo_restore (cr);
4878 }
4879
4880 /**
4881  * gtk_paint_tab:
4882  * @style: a #GtkStyle
4883  * @cr: a #cairo_t
4884  * @state_type: a state
4885  * @shadow_type: the type of shadow to draw
4886  * @widget: (allow-none): the widget
4887  * @detail: (allow-none): a style detail
4888  * @x: x origin of the rectangle to draw the tab in
4889  * @y: y origin of the rectangle to draw the tab in
4890  * @width: the width of the rectangle to draw the tab in
4891  * @height: the height of the rectangle to draw the tab in
4892  *
4893  * Draws an option menu tab (i.e. the up and down pointing arrows)
4894  * in the given rectangle on @cr using the given parameters.
4895  */ 
4896 void
4897 gtk_paint_tab (GtkStyle           *style,
4898                cairo_t            *cr,
4899                GtkStateType        state_type,
4900                GtkShadowType       shadow_type,
4901                GtkWidget          *widget,
4902                const gchar        *detail,
4903                gint                x,
4904                gint                y,
4905                gint                width,
4906                gint                height)
4907 {
4908   g_return_if_fail (GTK_IS_STYLE (style));
4909   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
4910   g_return_if_fail (cr != NULL);
4911
4912   cairo_save (cr);
4913
4914   GTK_STYLE_GET_CLASS (style)->draw_tab (style, cr, state_type, shadow_type,
4915                                          widget, detail,
4916                                          x, y, width, height);
4917
4918   cairo_restore (cr);
4919 }
4920
4921 /**
4922  * gtk_paint_shadow_gap:
4923  * @style: a #GtkStyle
4924  * @cr: a #cairo_t
4925  * @state_type: a state
4926  * @shadow_type: type of shadow to draw
4927  * @widget: (allow-none): the widget
4928  * @detail: (allow-none): a style detail
4929  * @x: x origin of the rectangle
4930  * @y: y origin of the rectangle
4931  * @width: width of the rectangle
4932  * @height: width of the rectangle
4933  * @gap_side: side in which to leave the gap
4934  * @gap_x: starting position of the gap
4935  * @gap_width: width of the gap
4936  *
4937  * Draws a shadow around the given rectangle in @cr
4938  * using the given style and state and shadow type, leaving a 
4939  * gap in one side.
4940 */
4941 void
4942 gtk_paint_shadow_gap (GtkStyle           *style,
4943                       cairo_t            *cr,
4944                       GtkStateType        state_type,
4945                       GtkShadowType       shadow_type,
4946                       GtkWidget          *widget,
4947                       const gchar        *detail,
4948                       gint                x,
4949                       gint                y,
4950                       gint                width,
4951                       gint                height,
4952                       GtkPositionType     gap_side,
4953                       gint                gap_x,
4954                       gint                gap_width)
4955 {
4956   g_return_if_fail (GTK_IS_STYLE (style));
4957   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
4958   g_return_if_fail (cr != NULL);
4959   g_return_if_fail (width >= 0);
4960   g_return_if_fail (height >= 0);
4961
4962   cairo_save (cr);
4963
4964   GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, cr, state_type, shadow_type,
4965                                                 widget, detail,
4966                                                 x, y, width, height, gap_side, gap_x, gap_width);
4967
4968   cairo_restore (cr);
4969 }
4970
4971 /**
4972  * gtk_paint_box_gap:
4973  * @style: a #GtkStyle
4974  * @cr: a #cairo_t
4975  * @state_type: a state
4976  * @shadow_type: type of shadow to draw
4977  * @widget: (allow-none): the widget
4978  * @detail: (allow-none): a style detail
4979  * @x: x origin of the rectangle
4980  * @y: y origin of the rectangle
4981  * @width: width of the rectangle
4982  * @height: width of the rectangle
4983  * @gap_side: side in which to leave the gap
4984  * @gap_x: starting position of the gap
4985  * @gap_width: width of the gap
4986  *
4987  * Draws a box in @cr using the given style and state and shadow type, 
4988  * leaving a gap in one side.
4989  */
4990 void
4991 gtk_paint_box_gap (GtkStyle           *style,
4992                    cairo_t            *cr,
4993                    GtkStateType        state_type,
4994                    GtkShadowType       shadow_type,
4995                    GtkWidget          *widget,
4996                    const gchar        *detail,
4997                    gint                x,
4998                    gint                y,
4999                    gint                width,
5000                    gint                height,
5001                    GtkPositionType     gap_side,
5002                    gint                gap_x,
5003                    gint                gap_width)
5004 {
5005   g_return_if_fail (GTK_IS_STYLE (style));
5006   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
5007   g_return_if_fail (cr != NULL);
5008   g_return_if_fail (width >= 0);
5009   g_return_if_fail (height >= 0);
5010
5011   cairo_save (cr);
5012
5013   GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, cr, state_type, shadow_type,
5014                                              widget, detail,
5015                                              x, y, width, height, gap_side, gap_x, gap_width);
5016
5017   cairo_restore (cr);
5018 }
5019
5020 /**
5021  * gtk_paint_extension: 
5022  * @style: a #GtkStyle
5023  * @cr: a #cairo_t
5024  * @state_type: a state
5025  * @shadow_type: type of shadow to draw
5026  * @widget: (allow-none): the widget
5027  * @detail: (allow-none): a style detail
5028  * @x: x origin of the extension
5029  * @y: y origin of the extension
5030  * @width: width of the extension
5031  * @height: width of the extension
5032  * @gap_side: the side on to which the extension is attached
5033  * 
5034  * Draws an extension, i.e. a notebook tab.
5035  **/
5036 void
5037 gtk_paint_extension (GtkStyle           *style,
5038                      cairo_t            *cr,
5039                      GtkStateType        state_type,
5040                      GtkShadowType       shadow_type,
5041                      GtkWidget          *widget,
5042                      const gchar        *detail,
5043                      gint                x,
5044                      gint                y,
5045                      gint                width,
5046                      gint                height,
5047                      GtkPositionType     gap_side)
5048 {
5049   g_return_if_fail (GTK_IS_STYLE (style));
5050   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
5051   g_return_if_fail (cr != NULL);
5052   g_return_if_fail (width >= 0);
5053   g_return_if_fail (height >= 0);
5054
5055   cairo_save (cr);
5056
5057   GTK_STYLE_GET_CLASS (style)->draw_extension (style, cr, state_type, shadow_type,
5058                                                widget, detail,
5059                                                x, y, width, height, gap_side);
5060
5061   cairo_restore (cr);
5062 }
5063
5064 /**
5065  * gtk_paint_focus:
5066  * @style: a #GtkStyle
5067  * @cr: a #cairo_t
5068  * @state_type: a state
5069  * @widget: (allow-none): the widget
5070  * @detail: (allow-none): a style detail
5071  * @x: the x origin of the rectangle around which to draw a focus indicator
5072  * @y: the y origin of the rectangle around which to draw a focus indicator
5073  * @width: the width of the rectangle around which to draw a focus indicator
5074  * @height: the height of the rectangle around which to draw a focus indicator
5075  *
5076  * Draws a focus indicator around the given rectangle on @cr using the
5077  * given style.
5078  */
5079 void
5080 gtk_paint_focus (GtkStyle           *style,
5081                  cairo_t            *cr,
5082                  GtkStateType        state_type,
5083                  GtkWidget          *widget,
5084                  const gchar        *detail,
5085                  gint                x,
5086                  gint                y,
5087                  gint                width,
5088                  gint                height)
5089 {
5090   g_return_if_fail (GTK_IS_STYLE (style));
5091   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
5092   g_return_if_fail (cr != NULL);
5093   g_return_if_fail (width >= 0);
5094   g_return_if_fail (height >= 0);
5095
5096   cairo_save (cr);
5097
5098   GTK_STYLE_GET_CLASS (style)->draw_focus (style, cr, state_type,
5099                                            widget, detail,
5100                                            x, y, width, height);
5101
5102   cairo_restore (cr);
5103 }
5104
5105 /**
5106  * gtk_paint_slider:
5107  * @style: a #GtkStyle
5108  * @cr: a #cairo_t
5109  * @state_type: a state
5110  * @shadow_type: a shadow
5111  * @widget: (allow-none): the widget
5112  * @detail: (allow-none): a style detail
5113  * @x: the x origin of the rectangle in which to draw a slider
5114  * @y: the y origin of the rectangle in which to draw a slider
5115  * @width: the width of the rectangle in which to draw a slider
5116  * @height: the height of the rectangle in which to draw a slider
5117  * @orientation: the orientation to be used
5118  *
5119  * Draws a slider in the given rectangle on @cr using the
5120  * given style and orientation.
5121  **/
5122 void
5123 gtk_paint_slider (GtkStyle           *style,
5124                   cairo_t            *cr,
5125                   GtkStateType        state_type,
5126                   GtkShadowType       shadow_type,
5127                   GtkWidget          *widget,
5128                   const gchar        *detail,
5129                   gint                x,
5130                   gint                y,
5131                   gint                width,
5132                   gint                height,
5133                   GtkOrientation      orientation)
5134 {
5135   g_return_if_fail (GTK_IS_STYLE (style));
5136   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
5137   g_return_if_fail (cr != NULL);
5138   g_return_if_fail (width >= 0);
5139   g_return_if_fail (height >= 0);
5140
5141   cairo_save (cr);
5142
5143   GTK_STYLE_GET_CLASS (style)->draw_slider (style, cr, state_type, shadow_type,
5144                                             widget, detail,
5145                                             x, y, width, height, orientation);
5146
5147   cairo_restore (cr);
5148 }
5149
5150 /**
5151  * gtk_paint_handle:
5152  * @style: a #GtkStyle
5153  * @cr: a #cairo_t
5154  * @state_type: a state
5155  * @shadow_type: type of shadow to draw
5156  * @widget: (allow-none): the widget
5157  * @detail: (allow-none): a style detail
5158  * @x: x origin of the handle
5159  * @y: y origin of the handle
5160  * @width: with of the handle
5161  * @height: height of the handle
5162  * @orientation: the orientation of the handle
5163  * 
5164  * Draws a handle as used in #GtkHandleBox and #GtkPaned.
5165  **/
5166 void
5167 gtk_paint_handle (GtkStyle           *style,
5168                   cairo_t            *cr,
5169                   GtkStateType        state_type,
5170                   GtkShadowType       shadow_type,
5171                   GtkWidget          *widget,
5172                   const gchar        *detail,
5173                   gint                x,
5174                   gint                y,
5175                   gint                width,
5176                   gint                height,
5177                   GtkOrientation      orientation)
5178 {
5179   g_return_if_fail (GTK_IS_STYLE (style));
5180   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
5181   g_return_if_fail (cr != NULL);
5182   g_return_if_fail (width >= 0);
5183   g_return_if_fail (height >= 0);
5184
5185   cairo_save (cr);
5186
5187   GTK_STYLE_GET_CLASS (style)->draw_handle (style, cr, state_type, shadow_type,
5188                                             widget, detail,
5189                                             x, y, width, height, orientation);
5190
5191   cairo_restore (cr);
5192 }
5193
5194 /**
5195  * gtk_paint_expander:
5196  * @style: a #GtkStyle
5197  * @cr: a #cairo_t
5198  * @state_type: a state
5199  * @widget: (allow-none): the widget
5200  * @detail: (allow-none): a style detail
5201  * @x: the x position to draw the expander at
5202  * @y: the y position to draw the expander at
5203  * @expander_style: the style to draw the expander in; determines
5204  *   whether the expander is collapsed, expanded, or in an
5205  *   intermediate state.
5206  * 
5207  * Draws an expander as used in #GtkTreeView. @x and @y specify the
5208  * center the expander. The size of the expander is determined by the
5209  * "expander-size" style property of @widget.  (If widget is not
5210  * specified or doesn't have an "expander-size" property, an
5211  * unspecified default size will be used, since the caller doesn't
5212  * have sufficient information to position the expander, this is
5213  * likely not useful.) The expander is expander_size pixels tall
5214  * in the collapsed position and expander_size pixels wide in the
5215  * expanded position.
5216  **/
5217 void
5218 gtk_paint_expander (GtkStyle           *style,
5219                     cairo_t            *cr,
5220                     GtkStateType        state_type,
5221                     GtkWidget          *widget,
5222                     const gchar        *detail,
5223                     gint                x,
5224                     gint                y,
5225                     GtkExpanderStyle    expander_style)
5226 {
5227   g_return_if_fail (GTK_IS_STYLE (style));
5228   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
5229   g_return_if_fail (cr != NULL);
5230
5231   cairo_save (cr);
5232
5233   GTK_STYLE_GET_CLASS (style)->draw_expander (style, cr, state_type,
5234                                               widget, detail,
5235                                               x, y, expander_style);
5236
5237   cairo_restore (cr);
5238 }
5239
5240 /**
5241  * gtk_paint_layout:
5242  * @style: a #GtkStyle
5243  * @cr: a #cairo_t
5244  * @state_type: a state
5245  * @use_text: whether to use the text or foreground
5246  *            graphics context of @style
5247  * @widget: (allow-none): the widget
5248  * @detail: (allow-none): a style detail
5249  * @x: x origin
5250  * @y: y origin
5251  * @layout: the layout to draw
5252  *
5253  * Draws a layout on @cr using the given parameters.
5254  **/
5255 void
5256 gtk_paint_layout (GtkStyle           *style,
5257                   cairo_t            *cr,
5258                   GtkStateType        state_type,
5259                   gboolean            use_text,
5260                   GtkWidget          *widget,
5261                   const gchar        *detail,
5262                   gint                x,
5263                   gint                y,
5264                   PangoLayout        *layout)
5265 {
5266   g_return_if_fail (GTK_IS_STYLE (style));
5267   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
5268   g_return_if_fail (cr != NULL);
5269
5270   cairo_save (cr);
5271
5272   GTK_STYLE_GET_CLASS (style)->draw_layout (style, cr, state_type, use_text,
5273                                             widget, detail,
5274                                             x, y, layout);
5275
5276   cairo_restore (cr);
5277 }
5278
5279 /**
5280  * gtk_paint_resize_grip:
5281  * @style: a #GtkStyle
5282  * @cr: a #cairo_t
5283  * @state_type: a state
5284  * @widget: (allow-none): the widget
5285  * @detail: (allow-none): a style detail
5286  * @edge: the edge in which to draw the resize grip
5287  * @x: the x origin of the rectangle in which to draw the resize grip
5288  * @y: the y origin of the rectangle in which to draw the resize grip
5289  * @width: the width of the rectangle in which to draw the resize grip
5290  * @height: the height of the rectangle in which to draw the resize grip
5291  *
5292  * Draws a resize grip in the given rectangle on @cr using the given
5293  * parameters. 
5294  */
5295 void
5296 gtk_paint_resize_grip (GtkStyle           *style,
5297                        cairo_t            *cr,
5298                        GtkStateType        state_type,
5299                        GtkWidget          *widget,
5300                        const gchar        *detail,
5301                        GdkWindowEdge       edge,
5302                        gint                x,
5303                        gint                y,
5304                        gint                width,
5305                        gint                height)
5306 {
5307   g_return_if_fail (GTK_IS_STYLE (style));
5308   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
5309   g_return_if_fail (cr != NULL);
5310
5311   cairo_save (cr);
5312
5313   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, cr, state_type,
5314                                                  widget, detail,
5315                                                  edge, x, y, width, height);
5316   cairo_restore (cr);
5317 }
5318
5319 /**
5320  * gtk_paint_spinner:
5321  * @style: a #GtkStyle
5322  * @cr: a #cairo_t
5323  * @state_type: a state
5324  * @widget: (allow-none): the widget (may be %NULL)
5325  * @detail: (allow-none): a style detail (may be %NULL)
5326  * @step: the nth step, a value between 0 and #GtkSpinner:num-steps
5327  * @x: the x origin of the rectangle in which to draw the spinner
5328  * @y: the y origin of the rectangle in which to draw the spinner
5329  * @width: the width of the rectangle in which to draw the spinner
5330  * @height: the height of the rectangle in which to draw the spinner
5331  *
5332  * Draws a spinner on @window using the given parameters.
5333  */
5334 void
5335 gtk_paint_spinner (GtkStyle           *style,
5336                    cairo_t            *cr,
5337                    GtkStateType        state_type,
5338                    GtkWidget          *widget,
5339                    const gchar        *detail,
5340                    guint               step,
5341                    gint                x,
5342                    gint                y,
5343                    gint                width,
5344                    gint                height)
5345 {
5346   g_return_if_fail (GTK_IS_STYLE (style));
5347   g_return_if_fail (cr != NULL);
5348   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_spinner != NULL);
5349
5350   cairo_save (cr);
5351
5352   GTK_STYLE_GET_CLASS (style)->draw_spinner (style, cr, state_type,
5353                                              widget, detail,
5354                                              step, x, y, width, height);
5355
5356   cairo_restore (cr);
5357 }
5358
5359 /**
5360  * gtk_border_new:
5361  *
5362  * Allocates a new #GtkBorder structure and initializes its elements to zero.
5363  * 
5364  * Returns: a new empty #GtkBorder. The newly allocated #GtkBorder should be 
5365  *     freed with gtk_border_free()
5366  *
5367  * Since: 2.14
5368  **/
5369 GtkBorder *
5370 gtk_border_new (void)
5371 {
5372   return g_slice_new0 (GtkBorder);
5373 }
5374
5375 /**
5376  * gtk_border_copy:
5377  * @border_: a #GtkBorder.
5378  * @returns: a copy of @border_.
5379  *
5380  * Copies a #GtkBorder structure.
5381  **/
5382 GtkBorder *
5383 gtk_border_copy (const GtkBorder *border)
5384 {
5385   g_return_val_if_fail (border != NULL, NULL);
5386
5387   return g_slice_dup (GtkBorder, border);
5388 }
5389
5390 /**
5391  * gtk_border_free:
5392  * @border_: a #GtkBorder.
5393  * 
5394  * Frees a #GtkBorder structure.
5395  **/
5396 void
5397 gtk_border_free (GtkBorder *border)
5398 {
5399   g_slice_free (GtkBorder, border);
5400 }
5401
5402 G_DEFINE_BOXED_TYPE (GtkBorder, gtk_border,
5403                      gtk_border_copy,
5404                      gtk_border_free)
5405
5406 typedef struct _CursorInfo CursorInfo;
5407
5408 struct _CursorInfo
5409 {
5410   GType for_type;
5411   GdkColor primary;
5412   GdkColor secondary;
5413 };
5414
5415 static void
5416 style_unrealize_cursors (GtkStyle *style)
5417 {
5418   CursorInfo *
5419   
5420   cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
5421   if (cursor_info)
5422     {
5423       g_free (cursor_info);
5424       g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), NULL);
5425     }
5426 }
5427
5428 static const GdkColor *
5429 get_insertion_cursor_color (GtkWidget *widget,
5430                             gboolean   is_primary)
5431 {
5432   CursorInfo *cursor_info;
5433   GtkStyle *style;
5434   GdkColor *cursor_color;
5435
5436   style = gtk_widget_get_style (widget);
5437
5438   cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
5439   if (!cursor_info)
5440     {
5441       cursor_info = g_new0 (CursorInfo, 1);
5442       g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), cursor_info);
5443       cursor_info->for_type = G_TYPE_INVALID;
5444     }
5445
5446   /* We have to keep track of the type because gtk_widget_style_get()
5447    * can return different results when called on the same property and
5448    * same style but for different widgets. :-(. That is,
5449    * GtkEntry::cursor-color = "red" in a style will modify the cursor
5450    * color for entries but not for text view.
5451    */
5452   if (cursor_info->for_type != G_OBJECT_TYPE (widget))
5453     {
5454       cursor_info->for_type = G_OBJECT_TYPE (widget);
5455
5456       /* Cursors in text widgets are drawn only in NORMAL state,
5457        * so we can use text[GTK_STATE_NORMAL] as text color here */
5458       gtk_widget_style_get (widget, "cursor-color", &cursor_color, NULL);
5459       if (cursor_color)
5460         {
5461           cursor_info->primary = *cursor_color;
5462           gdk_color_free (cursor_color);
5463         }
5464       else
5465         {
5466           cursor_info->primary = style->text[GTK_STATE_NORMAL];
5467         }
5468
5469       gtk_widget_style_get (widget, "secondary-cursor-color", &cursor_color, NULL);
5470       if (cursor_color)
5471         {
5472           cursor_info->secondary = *cursor_color;
5473           gdk_color_free (cursor_color);
5474         }
5475       else
5476         {
5477           /* text_aa is the average of text and base colors,
5478            * in usual black-on-white case it's grey. */
5479           cursor_info->secondary = style->text_aa[GTK_STATE_NORMAL];
5480         }
5481     }
5482
5483   if (is_primary)
5484     return &cursor_info->primary;
5485   else
5486     return &cursor_info->secondary;
5487 }
5488
5489 void
5490 _gtk_widget_get_cursor_color (GtkWidget *widget,
5491                               GdkColor  *color)
5492 {
5493   GdkColor *style_color;
5494
5495   g_return_if_fail (GTK_IS_WIDGET (widget));
5496   g_return_if_fail (color != NULL);
5497
5498   gtk_widget_style_get (widget, "cursor-color", &style_color, NULL);
5499
5500   if (style_color)
5501     {
5502       *color = *style_color;
5503       gdk_color_free (style_color);
5504     }
5505   else
5506     *color = gtk_widget_get_style (widget)->text[GTK_STATE_NORMAL];
5507 }
5508
5509 /**
5510  * gtk_draw_insertion_cursor:
5511  * @widget:  a #GtkWidget
5512  * @cr: cairo context to draw to
5513  * @location: location where to draw the cursor (@location->width is ignored)
5514  * @is_primary: if the cursor should be the primary cursor color.
5515  * @direction: whether the cursor is left-to-right or
5516  *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
5517  * @draw_arrow: %TRUE to draw a directional arrow on the
5518  *        cursor. Should be %FALSE unless the cursor is split.
5519  * 
5520  * Draws a text caret on @cr at @location. This is not a style function
5521  * but merely a convenience function for drawing the standard cursor shape.
5522  *
5523  * Since: 3.0
5524  **/
5525 void
5526 gtk_draw_insertion_cursor (GtkWidget          *widget,
5527                            cairo_t            *cr,
5528                            const GdkRectangle *location,
5529                            gboolean            is_primary,
5530                            GtkTextDirection    direction,
5531                            gboolean            draw_arrow)
5532 {
5533   gint stem_width;
5534   gint arrow_width;
5535   gint x, y;
5536   gfloat cursor_aspect_ratio;
5537   gint offset;
5538   
5539   g_return_if_fail (GTK_IS_WIDGET (widget));
5540   g_return_if_fail (cr != NULL);
5541   g_return_if_fail (location != NULL);
5542   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
5543
5544   gdk_cairo_set_source_color (cr, get_insertion_cursor_color (widget, is_primary));
5545
5546   /* When changing the shape or size of the cursor here,
5547    * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
5548    */
5549
5550   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
5551   
5552   stem_width = location->height * cursor_aspect_ratio + 1;
5553   arrow_width = stem_width + 1;
5554
5555   /* put (stem_width % 2) on the proper side of the cursor */
5556   if (direction == GTK_TEXT_DIR_LTR)
5557     offset = stem_width / 2;
5558   else
5559     offset = stem_width - stem_width / 2;
5560   
5561   cairo_rectangle (cr, 
5562                    location->x - offset, location->y,
5563                    stem_width, location->height);
5564   cairo_fill (cr);
5565
5566   if (draw_arrow)
5567     {
5568       if (direction == GTK_TEXT_DIR_RTL)
5569         {
5570           x = location->x - offset - 1;
5571           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5572   
5573           cairo_move_to (cr, x, y + 1);
5574           cairo_line_to (cr, x - arrow_width, y + arrow_width);
5575           cairo_line_to (cr, x, y + 2 * arrow_width);
5576           cairo_fill (cr);
5577         }
5578       else if (direction == GTK_TEXT_DIR_LTR)
5579         {
5580           x = location->x + stem_width - offset;
5581           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5582   
5583           cairo_move_to (cr, x, y + 1);
5584           cairo_line_to (cr, x + arrow_width, y + arrow_width);
5585           cairo_line_to (cr, x, y + 2 * arrow_width);
5586           cairo_fill (cr);
5587         }
5588     }
5589 }