diff options
author | Benjamin Otte <otte@redhat.com> | 2015-01-20 05:54:45 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2015-01-20 06:30:20 +0100 |
commit | f7433557abd63c8e6d03ba31c14f004a0d62c173 (patch) | |
tree | c384a480cb30bac93da604b0cba9fd473176f0f4 | |
parent | 8c745088d5376ba399985dad98d82311218ca548 (diff) | |
download | gtk+-f7433557abd63c8e6d03ba31c14f004a0d62c173.tar.gz |
render: Implement -gtk-icon-transform for icon surfaces
Yes, I like playing around. To enjoy, add this CSS to your application
of choice (preferrably glade or something with lots of images):
GtkImage { animation: spin 2s linear infinite; }
You can thank me later.
-rw-r--r-- | gtk/gtkrendericon.c | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/gtk/gtkrendericon.c b/gtk/gtkrendericon.c index 3d3fbb754a..a6aecbcb45 100644 --- a/gtk/gtkrendericon.c +++ b/gtk/gtkrendericon.c @@ -74,6 +74,20 @@ gtk_css_style_render_icon (GtkCssStyle *style, } } +gboolean +get_surface_extents (cairo_surface_t *surface, + GdkRectangle *out_extents) +{ + cairo_t *cr; + gboolean result; + + cr = cairo_create (surface); + result = gdk_cairo_get_clip_rectangle (cr, out_extents); + cairo_destroy (cr); + + return result; +} + void gtk_css_style_render_icon_surface (GtkCssStyle *style, cairo_t *cr, @@ -81,14 +95,48 @@ gtk_css_style_render_icon_surface (GtkCssStyle *style, double x, double y) { + const GtkCssValue *shadows; + cairo_matrix_t matrix, transform_matrix; + GdkRectangle extents; + g_return_if_fail (GTK_IS_CSS_STYLE (style)); g_return_if_fail (cr != NULL); g_return_if_fail (surface != NULL); - cairo_set_source_surface (cr, surface, x, y); + shadows = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW); + + if (!get_surface_extents (surface, &extents)) + { + /* weird infinite surface, no special magic for you */ + cairo_set_source_surface (cr, surface, x, y); + _gtk_css_shadows_value_paint_icon (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW), cr); + cairo_paint (cr); + return; + } + + cairo_translate (cr, x + extents.x, y + extents.y); - _gtk_css_shadows_value_paint_icon (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW), cr); + if (_gtk_css_transform_value_get_matrix (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM), &transform_matrix)) + { + cairo_pattern_t *pattern; - cairo_paint (cr); + /* XXX: Implement -gtk-icon-transform-origin instead of hardcoding "50% 50%" here */ + cairo_matrix_init_translate (&matrix, extents.width / 2, extents.height / 2); + cairo_matrix_multiply (&matrix, &transform_matrix, &matrix); + cairo_matrix_translate (&matrix, - extents.width / 2, - extents.height / 2); + if (cairo_matrix_invert (&matrix) != CAIRO_STATUS_SUCCESS) + { + g_assert_not_reached (); + } + cairo_matrix_translate (&matrix, extents.x, extents.y); + + pattern = cairo_pattern_create_for_surface (surface); + cairo_pattern_set_matrix (pattern, &matrix); + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); + + _gtk_css_shadows_value_paint_icon (shadows, cr); + cairo_paint (cr); + } } |