[gtk+] border-image: add support for border-image-width too



commit 3d1407a01a1e772f8b042801bbbde95ae1e16f9a
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Thu Jun 9 19:59:14 2011 -0400

    border-image: add support for border-image-width too
    
    It's useful to set a slice size != border-width, as backgrounds are
    clipped to border-width too.
    
    As slices can be half-transparent and overlap the background,
    this would not fill the border box properly if we only use a single
    property for specifying the width.
    
    Also, this brings us even closer to CSS3.

 gtk/gtkborderimage.c        |   40 +++++++++++++++++++++++++++++++---------
 gtk/gtkborderimageprivate.h |    2 ++
 gtk/gtkcssprovider.c        |   10 +++++++++-
 gtk/gtkstyleproperty.c      |   29 ++++++++++++++++++++++++-----
 4 files changed, 66 insertions(+), 15 deletions(-)
---
diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c
index f259310..f5cca50 100644
--- a/gtk/gtkborderimage.c
+++ b/gtk/gtkborderimage.c
@@ -52,14 +52,16 @@ struct _GtkBorderImage {
   GtkGradient *source_gradient;
 
   GtkBorder slice;
+  GtkBorder *width;
   GtkCssBorderImageRepeat repeat;
 
   gint ref_count;
 };
 
 GtkBorderImage *
-_gtk_border_image_new (cairo_pattern_t      *pattern,
-                       GtkBorder            *slice,
+_gtk_border_image_new (cairo_pattern_t         *pattern,
+                       GtkBorder               *slice,
+                       GtkBorder               *width,
                        GtkCssBorderImageRepeat *repeat)
 {
   GtkBorderImage *image;
@@ -73,6 +75,9 @@ _gtk_border_image_new (cairo_pattern_t      *pattern,
   if (slice != NULL)
     image->slice = *slice;
 
+  if (width != NULL)
+    image->width = gtk_border_copy (width);
+
   if (repeat != NULL)
     image->repeat = *repeat;
 
@@ -80,8 +85,9 @@ _gtk_border_image_new (cairo_pattern_t      *pattern,
 }
 
 GtkBorderImage *
-_gtk_border_image_new_for_gradient (GtkGradient          *gradient,
-                                    GtkBorder            *slice,
+_gtk_border_image_new_for_gradient (GtkGradient             *gradient,
+                                    GtkBorder               *slice,
+                                    GtkBorder               *width,
                                     GtkCssBorderImageRepeat *repeat)
 {
   GtkBorderImage *image;
@@ -95,6 +101,9 @@ _gtk_border_image_new_for_gradient (GtkGradient          *gradient,
   if (slice != NULL)
     image->slice = *slice;
 
+  if (width != NULL)
+    image->width = gtk_border_copy (width);
+
   if (repeat != NULL)
     image->repeat = *repeat;
 
@@ -126,6 +135,9 @@ _gtk_border_image_unref (GtkBorderImage *image)
       if (image->source_gradient != NULL)
         gtk_gradient_unref (image->source_gradient);
 
+      if (image->width != NULL)
+        gtk_border_free (image->width);
+
       g_slice_free (GtkBorderImage, image);
     }
 }
@@ -134,7 +146,7 @@ GParameter *
 _gtk_border_image_unpack (const GValue *value,
                           guint        *n_params)
 {
-  GParameter *parameter = g_new0 (GParameter, 3);
+  GParameter *parameter = g_new0 (GParameter, 4);
   GtkBorderImage *image = g_value_get_boxed (value);
 
   parameter[0].name = "border-image-source";
@@ -146,14 +158,18 @@ _gtk_border_image_unpack (const GValue *value,
   parameter[2].name = "border-image-repeat";
   g_value_init (&parameter[2].value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
 
+  parameter[3].name = "border-image-width";
+  g_value_init (&parameter[3].value, GTK_TYPE_BORDER);
+
   if (image != NULL)
     {
       g_value_set_boxed (&parameter[0].value, image->source);
       g_value_set_boxed (&parameter[1].value, &image->slice);
       g_value_set_boxed (&parameter[2].value, &image->repeat);
+      g_value_set_boxed (&parameter[3].value, image->width);
     }
 
-  *n_params = 3;
+  *n_params = 4;
   return parameter;
 }
 
@@ -164,13 +180,14 @@ _gtk_border_image_pack (GValue             *value,
 {
   GtkBorderImage *image;
   cairo_pattern_t *source;
-  GtkBorder *slice;
+  GtkBorder *slice, *width;
   GtkCssBorderImageRepeat *repeat;
 
   gtk_style_properties_get (props, state,
                             "border-image-source", &source,
                             "border-image-slice", &slice,
                             "border-image-repeat", &repeat,
+                            "border-image-width", &width,
                             NULL);
 
   if (source == NULL)
@@ -179,7 +196,7 @@ _gtk_border_image_pack (GValue             *value,
     }
   else
     {
-      image = _gtk_border_image_new (source, slice, repeat);
+      image = _gtk_border_image_new (source, slice, width, repeat);
       g_value_take_boxed (value, image);
 
       cairo_pattern_destroy (source);
@@ -188,6 +205,9 @@ _gtk_border_image_pack (GValue             *value,
   if (slice != NULL)
     gtk_border_free (slice);
 
+  if (width != NULL)
+    gtk_border_free (width);
+
   if (repeat != NULL)
     g_free (repeat);
 }
@@ -370,6 +390,9 @@ _gtk_border_image_render (GtkBorderImage   *image,
   int surface_width, surface_height;
   int h, v;
 
+  if (image->width != NULL)
+    border_width = image->width;
+
   if (cairo_pattern_get_type (image->source) != CAIRO_PATTERN_TYPE_SURFACE)
     {
       cairo_matrix_t matrix;
@@ -437,7 +460,6 @@ _gtk_border_image_render (GtkBorderImage   *image,
                                                       horizontal_slice[h].size,
                                                       vertical_slice[v].size);
 
-          /* xxx: we scale to border-width here, that's wrong, isn't it? */
           gtk_border_image_render_slice (cr,
                                          slice,
                                          horizontal_slice[h].size,
diff --git a/gtk/gtkborderimageprivate.h b/gtk/gtkborderimageprivate.h
index ca2ef01..585be67 100644
--- a/gtk/gtkborderimageprivate.h
+++ b/gtk/gtkborderimageprivate.h
@@ -40,9 +40,11 @@ GType             _gtk_border_image_get_type         (void) G_GNUC_CONST;
 
 GtkBorderImage *  _gtk_border_image_new              (cairo_pattern_t      *source,
                                                       GtkBorder            *slice,
+                                                      GtkBorder            *width,
                                                       GtkCssBorderImageRepeat *repeat);
 GtkBorderImage *  _gtk_border_image_new_for_gradient (GtkGradient          *gradient,
                                                       GtkBorder            *slice,
+                                                      GtkBorder            *width,
                                                       GtkCssBorderImageRepeat *repeat);
 
 GtkBorderImage *  _gtk_border_image_ref              (GtkBorderImage       *image);
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 42a25a9..4258b3e 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -538,7 +538,7 @@
  * <inlinegraphic fileref="slices.png" format="PNG"/>
  * <para>
  * The parameters of the slicing process are controlled by
- * three separate properties. Note that you can use the
+ * four separate properties. Note that you can use the
  * <literallayout>border-image</literallayout> shorthand property
  * to set values for the three properties at the same time.
  * </para>
@@ -556,6 +556,14 @@
  * of the border.
  * </para>
  * <para>
+ * <literallayout>border-image-width: @top @right @bottom @left</literallayout>
+ * The sizes specified by the @top, @right, @bottom and @left parameters
+ * are inward distances from the border box edge, used to specify the
+ * rendered size of each slice determined by border-image-slice.
+ * If this property is not specified, the values of border-width will
+ * be used as a fallback.
+ * </para>
+ * <para>
  * <literallayout>border-image-repeat: [stretch|repeat|round|space] ? 
  * [stretch|repeat|round|space]</literallayout>
  * Specifies how the image slices should be rendered in the area
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index 7a93c6a..ce2f4e1 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -1023,7 +1023,7 @@ border_image_value_parse (GtkCssParser *parser,
   GValue temp = { 0, };
   cairo_pattern_t *pattern = NULL;
   GtkGradient *gradient = NULL;
-  GtkBorder border, *parsed_border;
+  GtkBorder slice, *width = NULL, *parsed_slice;
   GtkCssBorderImageRepeat repeat, *parsed_repeat;
   gboolean retval = FALSE;
   GtkBorderImage *image = NULL;
@@ -1044,8 +1044,19 @@ border_image_value_parse (GtkCssParser *parser,
   if (!border_value_parse (parser, base, &temp))
     goto out;
 
-  parsed_border = g_value_get_boxed (&temp);
-  border = *parsed_border;
+  parsed_slice = g_value_get_boxed (&temp);
+  slice = *parsed_slice;
+
+  if (_gtk_css_parser_try (parser, "/", TRUE))
+    {
+      g_value_unset (&temp);
+      g_value_init (&temp, GTK_TYPE_BORDER);
+
+      if (!border_value_parse (parser, base, &temp))
+        goto out;
+
+      width = g_value_dup_boxed (&temp);
+    }
 
   g_value_unset (&temp);
   g_value_init (&temp, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
@@ -1059,9 +1070,9 @@ border_image_value_parse (GtkCssParser *parser,
   g_value_unset (&temp);
 
   if (gradient != NULL)
-    image = _gtk_border_image_new_for_gradient (gradient, &border, &repeat);
+    image = _gtk_border_image_new_for_gradient (gradient, &slice, width, &repeat);
   else if (pattern != NULL)
-    image = _gtk_border_image_new (pattern, &border, &repeat);
+    image = _gtk_border_image_new (pattern, &slice, width, &repeat);
 
   if (image != NULL)
     {
@@ -1076,6 +1087,9 @@ border_image_value_parse (GtkCssParser *parser,
   if (gradient != NULL)
     gtk_gradient_unref (gradient);
 
+  if (width != NULL)
+    gtk_border_free (width);
+
   return retval;
 }
 
@@ -2231,6 +2245,11 @@ gtk_style_property_init (void)
                                                               "Border image slice",
                                                               "Border image slice",
                                                               GTK_TYPE_BORDER, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("border-image-width",
+                                                              "Border image width",
+                                                              "Border image width",
+                                                              GTK_TYPE_BORDER, 0));  
   _gtk_style_property_register           (g_param_spec_boxed ("border-image",
                                                               "Border Image",
                                                               "Border Image",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]