From f7433557abd63c8e6d03ba31c14f004a0d62c173 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 20 Jan 2015 05:54:45 +0100 Subject: 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. --- gtk/gtkrendericon.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file 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); + } } -- cgit v1.2.1