forked from AuroraMiddleware/gtk
css: start background-repeat
By default, a background image is stretched. Instead, it is worth to have a tiled background. This patch allows background surfaces to be repeated or not, and should be compatible with future extensions and CSS. https://bugzilla.gnome.org/show_bug.cgi?id=663522
This commit is contained in:
parent
ee7ac4fa44
commit
3b436eec6d
@ -840,6 +840,16 @@
|
||||
* </entry>
|
||||
* </row>
|
||||
* <row>
|
||||
* <entry>background-repeat</entry>
|
||||
* <entry>[repeat|no-repeat]</entry>
|
||||
* <entry>internal</entry>
|
||||
* <entry><literallayout>background-repeat: no-repeat;</literallayout>
|
||||
* If not specified, the style doesn't respect the CSS3
|
||||
* specification, since the background will be
|
||||
* stretched to fill the area.
|
||||
* </entry>
|
||||
* </row>
|
||||
* <row>
|
||||
* <entry>border-top-width</entry>
|
||||
* <entry>integer</entry>
|
||||
* <entry>#gint</entry>
|
||||
|
@ -31,6 +31,8 @@ type_name ## _copy (const TypeName *foo) \
|
||||
\
|
||||
G_DEFINE_BOXED_TYPE (TypeName, type_name, type_name ## _copy, g_free)
|
||||
|
||||
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBackgroundRepeat, _gtk_css_background_repeat)
|
||||
|
||||
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderCornerRadius, _gtk_css_border_corner_radius)
|
||||
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderRadius, _gtk_css_border_radius)
|
||||
DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderImageRepeat, _gtk_css_border_image_repeat)
|
||||
|
@ -24,6 +24,12 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GTK_CSS_BACKGROUND_REPEAT_STYLE_NONE,
|
||||
GTK_CSS_BACKGROUND_REPEAT_STYLE_REPEAT,
|
||||
GTK_CSS_BACKGROUND_REPEAT_STYLE_NO_REPEAT,
|
||||
} GtkCssBackgroundRepeatStyle;
|
||||
|
||||
typedef enum {
|
||||
GTK_CSS_REPEAT_STYLE_NONE,
|
||||
GTK_CSS_REPEAT_STYLE_REPEAT,
|
||||
@ -31,10 +37,17 @@ typedef enum {
|
||||
GTK_CSS_REPEAT_STYLE_SPACE
|
||||
} GtkCssBorderRepeatStyle;
|
||||
|
||||
typedef struct _GtkCssBackgroundRepeat GtkCssBackgroundRepeat;
|
||||
|
||||
typedef struct _GtkCssBorderCornerRadius GtkCssBorderCornerRadius;
|
||||
typedef struct _GtkCssBorderRadius GtkCssBorderRadius;
|
||||
typedef struct _GtkCssBorderImageRepeat GtkCssBorderImageRepeat;
|
||||
|
||||
struct _GtkCssBackgroundRepeat {
|
||||
/* FIXME: will have vrepeat and hrepeat instead */
|
||||
GtkCssBackgroundRepeatStyle repeat;
|
||||
};
|
||||
|
||||
struct _GtkCssBorderCornerRadius {
|
||||
double horizontal;
|
||||
double vertical;
|
||||
@ -52,10 +65,14 @@ struct _GtkCssBorderImageRepeat {
|
||||
GtkCssBorderRepeatStyle hrepeat;
|
||||
};
|
||||
|
||||
#define GTK_TYPE_CSS_BACKGROUND_REPEAT _gtk_css_background_repeat_get_type ()
|
||||
|
||||
#define GTK_TYPE_CSS_BORDER_CORNER_RADIUS _gtk_css_border_corner_radius_get_type ()
|
||||
#define GTK_TYPE_CSS_BORDER_RADIUS _gtk_css_border_radius_get_type ()
|
||||
#define GTK_TYPE_CSS_BORDER_IMAGE_REPEAT _gtk_css_border_image_repeat_get_type ()
|
||||
|
||||
GType _gtk_css_background_repeat_get_type (void);
|
||||
|
||||
GType _gtk_css_border_corner_radius_get_type (void);
|
||||
GType _gtk_css_border_radius_get_type (void);
|
||||
GType _gtk_css_border_image_repeat_get_type (void);
|
||||
|
@ -148,7 +148,6 @@ struct _GtkStyleContextClass
|
||||
*/
|
||||
#define GTK_STYLE_PROPERTY_BACKGROUND_IMAGE "background-image"
|
||||
|
||||
|
||||
/* Predefined set of CSS classes */
|
||||
|
||||
/**
|
||||
|
@ -1126,6 +1126,53 @@ shadow_value_print (const GValue *value,
|
||||
_gtk_shadow_print (shadow, string);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
background_repeat_value_parse (GtkCssParser *parser,
|
||||
GFile *file,
|
||||
GValue *value)
|
||||
{
|
||||
GtkCssBackgroundRepeat repeat;
|
||||
GtkCssBackgroundRepeatStyle style;
|
||||
|
||||
if (_gtk_css_parser_try (parser, "repeat", TRUE))
|
||||
style = GTK_CSS_BACKGROUND_REPEAT_STYLE_REPEAT;
|
||||
else if (_gtk_css_parser_try (parser, "no-repeat", TRUE))
|
||||
style = GTK_CSS_BACKGROUND_REPEAT_STYLE_NO_REPEAT;
|
||||
else
|
||||
style = GTK_CSS_BACKGROUND_REPEAT_STYLE_NONE;
|
||||
|
||||
repeat.repeat = style;
|
||||
|
||||
g_value_set_boxed (value, &repeat);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
background_repeat_style_to_string (GtkCssBackgroundRepeatStyle repeat)
|
||||
{
|
||||
switch (repeat)
|
||||
{
|
||||
case GTK_CSS_BACKGROUND_REPEAT_STYLE_REPEAT:
|
||||
return "repeat";
|
||||
case GTK_CSS_BACKGROUND_REPEAT_STYLE_NO_REPEAT:
|
||||
return "no-repeat";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
background_repeat_value_print (const GValue *value,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssBackgroundRepeat *repeat;
|
||||
|
||||
repeat = g_value_get_boxed (value);
|
||||
|
||||
g_string_append (string, background_repeat_style_to_string (repeat->repeat));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
border_image_repeat_value_parse (GtkCssParser *parser,
|
||||
GFile *file,
|
||||
@ -2246,6 +2293,9 @@ css_string_funcs_init (void)
|
||||
register_conversion_function (G_TYPE_FLAGS,
|
||||
flags_value_parse,
|
||||
flags_value_print);
|
||||
register_conversion_function (GTK_TYPE_CSS_BACKGROUND_REPEAT,
|
||||
background_repeat_value_parse,
|
||||
background_repeat_value_print);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -2912,6 +2962,12 @@ gtk_style_property_init (void)
|
||||
"Background Image",
|
||||
"Background Image",
|
||||
CAIRO_GOBJECT_TYPE_PATTERN, 0));
|
||||
gtk_style_properties_register_property (NULL,
|
||||
g_param_spec_boxed ("background-repeat",
|
||||
"Background repeat",
|
||||
"Background repeat",
|
||||
GTK_TYPE_CSS_BACKGROUND_REPEAT, 0));
|
||||
|
||||
gtk_style_properties_register_property (NULL,
|
||||
g_param_spec_boxed ("border-image-source",
|
||||
"Border image source",
|
||||
|
@ -1381,6 +1381,7 @@ render_background_internal (GtkThemingEngine *engine,
|
||||
{
|
||||
GdkRGBA bg_color;
|
||||
cairo_pattern_t *pattern;
|
||||
GtkCssBackgroundRepeat *repeat;
|
||||
GtkStateFlags flags;
|
||||
gboolean running;
|
||||
gdouble progress;
|
||||
@ -1394,6 +1395,7 @@ render_background_internal (GtkThemingEngine *engine,
|
||||
|
||||
gtk_theming_engine_get (engine, flags,
|
||||
"background-image", &pattern,
|
||||
"background-repeat", &repeat,
|
||||
"box-shadow", &box_shadow,
|
||||
NULL);
|
||||
|
||||
@ -1602,9 +1604,31 @@ render_background_internal (GtkThemingEngine *engine,
|
||||
|
||||
if (pattern)
|
||||
{
|
||||
cairo_scale (cr, width, height);
|
||||
cairo_surface_t *surface;
|
||||
int scale_width, scale_height;
|
||||
|
||||
if (cairo_pattern_get_surface (pattern, &surface) != CAIRO_STATUS_SUCCESS)
|
||||
surface = NULL;
|
||||
|
||||
if (surface && repeat &&
|
||||
repeat->repeat != GTK_CSS_BACKGROUND_REPEAT_STYLE_NONE)
|
||||
{
|
||||
scale_width = cairo_image_surface_get_width (surface);
|
||||
scale_height = cairo_image_surface_get_height (surface);
|
||||
if (repeat->repeat == GTK_CSS_BACKGROUND_REPEAT_STYLE_REPEAT)
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
else if (repeat->repeat == GTK_CSS_BACKGROUND_REPEAT_STYLE_NO_REPEAT)
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
scale_width = width;
|
||||
scale_height = height;
|
||||
}
|
||||
|
||||
cairo_scale (cr, scale_width, scale_height);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_scale (cr, 1.0 / width, 1.0 / height);
|
||||
cairo_scale (cr, 1.0 / scale_width, 1.0 / scale_height);
|
||||
}
|
||||
else
|
||||
gdk_cairo_set_source_rgba (cr, &bg_color);
|
||||
@ -1614,6 +1638,9 @@ render_background_internal (GtkThemingEngine *engine,
|
||||
if (pattern)
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
if (repeat)
|
||||
g_free (repeat);
|
||||
|
||||
if (box_shadow != NULL)
|
||||
{
|
||||
_gtk_box_shadow_render (box_shadow, cr, &border_box);
|
||||
|
Loading…
Reference in New Issue
Block a user