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