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