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