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.
This commit is contained in:
@@ -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 (¶meter[2].value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
|
||||
|
||||
parameter[3].name = "border-image-width";
|
||||
g_value_init (¶meter[3].value, GTK_TYPE_BORDER);
|
||||
|
||||
if (image != NULL)
|
||||
{
|
||||
g_value_set_boxed (¶meter[0].value, image->source);
|
||||
g_value_set_boxed (¶meter[1].value, &image->slice);
|
||||
g_value_set_boxed (¶meter[2].value, &image->repeat);
|
||||
g_value_set_boxed (¶meter[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",
|
||||
|
||||
Reference in New Issue
Block a user