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