Commit 3d1407a0 authored by Cosimo Cecchi's avatar Cosimo Cecchi

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.
parent 5fcf9ae0
......@@ -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,
......
......@@ -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);
......
......@@ -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
......
......@@ -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",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment