[gtk+] snapshot: Convert GtkImage and GtkIconHelper



commit c0aa065ac119c3280f0e886caff88258b767bb39
Author: Benjamin Otte <otte redhat com>
Date:   Tue Nov 15 06:19:16 2016 +0100

    snapshot: Convert GtkImage and GtkIconHelper
    
    Adds a bunch of new APIs to render textures with theming.
    
    FIXME: Cannot draw shadows for textures.

 gtk/gtkiconhelper.c        |   17 +++----
 gtk/gtkiconhelperprivate.h |    4 +-
 gtk/gtkimage.c             |   99 ++++++++++++++++++++++----------------------
 gtk/gtkrendericon.c        |   49 ++++++++++++++++++++++
 gtk/gtkrendericonprivate.h |    5 ++
 gtk/gtksnapshot.c          |   52 +++++++++++++++++++++++
 gtk/gtksnapshot.h          |   11 +++++
 7 files changed, 175 insertions(+), 62 deletions(-)
---
diff --git a/gtk/gtkiconhelper.c b/gtk/gtkiconhelper.c
index 278ace3..5bd099d 100644
--- a/gtk/gtkiconhelper.c
+++ b/gtk/gtkiconhelper.c
@@ -857,27 +857,24 @@ _gtk_icon_helper_draw (GtkIconHelper *self,
     }
 }
 
-GskRenderNode *
-gtk_icon_helper_get_render_node (GtkIconHelper *self,
-                                 GskRenderer   *renderer)
+void
+gtk_icon_helper_snapshot (GtkIconHelper *self,
+                          GtkSnapshot   *snapshot)
 {
   GskTexture *texture;
   GskRenderNode *node;
   graphene_rect_t bounds;
 
-  gtk_icon_helper_ensure_texture (self, renderer);
+  gtk_icon_helper_ensure_texture (self, gtk_snapshot_get_renderer (snapshot));
   texture = self->priv->texture;
   if (texture == NULL)
-    return NULL;
+    return;
  
   graphene_rect_init (&bounds, 0, 0, gsk_texture_get_width (texture), gsk_texture_get_height (texture));
 
-  node = gsk_renderer_create_render_node (renderer);
-  gsk_render_node_set_name (node, "Icon Helper");
-  gsk_render_node_set_bounds (node, &bounds);
+  node = gtk_snapshot_append (snapshot, &bounds, "Icon Helper");
   gsk_render_node_set_texture (node, texture);
-
-  return node;
+  gsk_render_node_unref (node);
 }
 
 gboolean
diff --git a/gtk/gtkiconhelperprivate.h b/gtk/gtkiconhelperprivate.h
index 6576e81..0fd3240 100644
--- a/gtk/gtkiconhelperprivate.h
+++ b/gtk/gtkiconhelperprivate.h
@@ -125,8 +125,8 @@ void _gtk_icon_helper_draw (GtkIconHelper *self,
                             cairo_t *cr,
                             gdouble x,
                             gdouble y);
-GskRenderNode * gtk_icon_helper_get_render_node (GtkIconHelper *self,
-                                                 GskRenderer   *renderer);
+void gtk_icon_helper_snapshot (GtkIconHelper *self,
+                               GtkSnapshot *snapshot);
 
 gboolean _gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self);
 void     _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c
index f7abcfc..ffb5f81 100644
--- a/gtk/gtkimage.c
+++ b/gtk/gtkimage.c
@@ -142,8 +142,8 @@ struct _GtkImagePrivate
 
 
 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_BUTTON
-static GskRenderNode *gtk_image_get_render_node (GtkWidget   *widget,
-                                                 GskRenderer *renderer);
+static void gtk_image_snapshot             (GtkWidget    *widget,
+                                            GtkSnapshot  *snapshot);
 static void gtk_image_size_allocate        (GtkWidget    *widget,
                                             GtkAllocation*allocation);
 static void gtk_image_unmap                (GtkWidget    *widget);
@@ -163,6 +163,13 @@ static void gtk_image_get_content_size (GtkCssGadget   *gadget,
                                         gint           *minimum_baseline,
                                         gint           *natural_baseline,
                                         gpointer        unused);
+static gboolean gtk_image_render_contents (GtkCssGadget *gadget,
+                                           GtkSnapshot  *snapshot,
+                                           int           x,
+                                           int           y,
+                                           int           width,
+                                           int           height,
+                                           gpointer      data);
 
 static void gtk_image_style_updated        (GtkWidget    *widget);
 static void gtk_image_finalize             (GObject      *object);
@@ -211,7 +218,7 @@ gtk_image_class_init (GtkImageClass *class)
   gobject_class->finalize = gtk_image_finalize;
 
   widget_class = GTK_WIDGET_CLASS (class);
-  widget_class->get_render_node = gtk_image_get_render_node;
+  widget_class->snapshot = gtk_image_snapshot;
   widget_class->measure = gtk_image_measure;
   widget_class->size_allocate = gtk_image_size_allocate;
   widget_class->unmap = gtk_image_unmap;
@@ -367,8 +374,9 @@ gtk_image_init (GtkImage *image)
                                                      gtk_image_get_content_size,
                                                      NULL,
                                                      NULL,
-                                                     NULL,
+                                                     gtk_image_render_contents,
                                                      NULL, NULL);
+
 }
 
 static void
@@ -1403,69 +1411,60 @@ gtk_image_get_content_size (GtkCssGadget   *gadget,
 
 }
 
-static GskRenderNode *
-gtk_image_get_render_node (GtkWidget   *widget,
-                           GskRenderer *renderer)
+static void
+gtk_image_snapshot (GtkWidget   *widget,
+                    GtkSnapshot *snapshot)
 {
-  GtkImage *image = GTK_IMAGE (widget);
-  GtkImagePrivate *priv = image->priv;
-  gint w, h, baseline;
-  gint x, y, width, height;
-  GskRenderNode *res;
-  GskRenderNode *node;
-  GtkAllocation alloc, clip;
-  cairo_t *cr;
-
-  res = gtk_css_gadget_get_render_node (priv->gadget, renderer, FALSE);
-
-  if (res == NULL)
-    return NULL;
-
-  if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
-    {
-      node = gtk_widget_create_render_node (widget, renderer, "Image Content");
+  gtk_css_gadget_snapshot (GTK_IMAGE (widget)->priv->gadget,
+                           snapshot);
+}
 
-      gtk_widget_get_clip (widget, &clip);
-      _gtk_widget_get_allocation (widget, &alloc);
+static gboolean
+gtk_image_render_contents (GtkCssGadget *gadget,
+                           GtkSnapshot  *snapshot,
+                           int           x,
+                           int           y,
+                           int           width,
+                           int           height,
+                           gpointer      data)
+{
+  GtkWidget *widget;
+  GtkImage *image;
+  GtkImagePrivate *priv;
+  gint w, h, baseline;
 
-      cr = gsk_render_node_get_draw_context (node, renderer);
-      cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
-      x = 0;
-      y = 0;
-      width = alloc.width;
-      height = alloc.height;
+  widget = gtk_css_gadget_get_owner (gadget);
+  image = GTK_IMAGE (widget);
+  priv = image->priv;
 
-      _gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
+  _gtk_icon_helper_get_size (priv->icon_helper, &w, &h);
 
-      baseline = gtk_widget_get_allocated_baseline (widget);
+  baseline = gtk_widget_get_allocated_baseline (widget);
 
-      if (baseline == -1)
-        y += floor(height - h) / 2;
-      else
-        y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
+  if (baseline == -1)
+    y += floor(height - h) / 2;
+  else
+    y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h);
 
-      x += (width - w) / 2;
+  x += (width - w) / 2;
 
+  gtk_snapshot_translate_2d (snapshot, x, y);
+  if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION)
+    {
       GtkStyleContext *context = gtk_widget_get_style_context (widget);
       GdkPixbuf *pixbuf = get_animation_frame (image);
 
-      gtk_render_icon (context, cr, pixbuf, x, y);
+      gtk_snapshot_render_icon (snapshot, context, pixbuf, x, y);
+      
       g_object_unref (pixbuf);
-
-      cairo_destroy (cr);
     }
   else
     {
-      node = gtk_icon_helper_get_render_node (priv->icon_helper, renderer);
-    }
-
-  if (node != NULL)
-    {
-      gsk_render_node_append_child (res, node);
-      gsk_render_node_unref (node);
+      gtk_icon_helper_snapshot (priv->icon_helper, snapshot);
     }
+  gtk_snapshot_translate_2d (snapshot, -x, -y);
 
-  return res;
+  return FALSE;
 }
 
 static void
diff --git a/gtk/gtkrendericon.c b/gtk/gtkrendericon.c
index b2ca78a..cd43ec9 100644
--- a/gtk/gtkrendericon.c
+++ b/gtk/gtkrendericon.c
@@ -26,6 +26,7 @@
 #include "gtkcssshadowsvalueprivate.h"
 #include "gtkcssstyleprivate.h"
 #include "gtkcsstransformvalueprivate.h"
+#include "gtksnapshotprivate.h"
 
 #include <math.h>
 
@@ -222,3 +223,51 @@ gtk_css_style_render_icon_get_extents (GtkCssStyle  *style,
   extents->height += border.top + border.bottom;
 }
 
+void
+gtk_css_style_snapshot_icon (GtkCssStyle *style,
+                             GtkSnapshot *snapshot,
+                             GskTexture  *texture)
+{
+  const GtkCssValue *shadows, *transform;
+  cairo_matrix_t transform_matrix;
+  graphene_matrix_t matrix, other, saved_matrix;
+  graphene_rect_t bounds;
+  GskRenderNode *node;
+  int width, height;
+
+  g_return_if_fail (GTK_IS_CSS_STYLE (style));
+  g_return_if_fail (snapshot != NULL);
+  g_return_if_fail (GSK_IS_TEXTURE (texture));
+
+  shadows = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_SHADOW);
+  transform = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_TRANSFORM);
+  width = gsk_texture_get_width (texture);
+  height = gsk_texture_get_height (texture);
+
+  if (!_gtk_css_transform_value_get_matrix (transform, &transform_matrix))
+    return;
+
+  graphene_matrix_init_from_matrix (&saved_matrix, gtk_snapshot_get_transform (snapshot));
+
+  /* XXX: Implement -gtk-icon-transform-origin instead of hardcoding "50% 50%" here */
+  graphene_matrix_init_translate (&matrix, &(graphene_point3d_t)GRAPHENE_POINT3D_INIT(width / 2.0, height / 
2.0, 0));
+  graphene_matrix_init_from_2d (&other, transform_matrix.xx, transform_matrix.yx,
+                                        transform_matrix.xy, transform_matrix.yy,
+                                        transform_matrix.x0, transform_matrix.y0);
+  graphene_matrix_multiply (&other, &matrix, &matrix);
+  graphene_matrix_init_translate (&other, &(graphene_point3d_t)GRAPHENE_POINT3D_INIT(- width / 2.0, - height 
/ 2.0, 0));
+  graphene_matrix_multiply (&matrix, &other, &matrix);
+  gtk_snapshot_transform (snapshot, &matrix);
+
+  graphene_rect_init (&bounds, 0, 0, width, height);
+
+  node = gtk_snapshot_append (snapshot, &bounds, "Icon");
+  if (!_gtk_css_shadows_value_is_none (shadows))
+    {
+      g_warning ("Painting shadows not implemented for textures yet.");
+    }
+  gsk_render_node_set_texture (node, texture);
+  gsk_render_node_unref (node);
+
+  gtk_snapshot_set_transform (snapshot, &saved_matrix);
+}
diff --git a/gtk/gtkrendericonprivate.h b/gtk/gtkrendericonprivate.h
index f627655..83a3b04 100644
--- a/gtk/gtkrendericonprivate.h
+++ b/gtk/gtkrendericonprivate.h
@@ -22,8 +22,10 @@
 
 #include <glib-object.h>
 #include <cairo.h>
+#include <gsk/gsk.h>
 
 #include "gtkcsstypesprivate.h"
+#include "gtksnapshot.h"
 #include "gtktypes.h"
 
 G_BEGIN_DECLS
@@ -41,6 +43,9 @@ void    gtk_css_style_render_icon_surface       (GtkCssStyle            *style,
                                                  cairo_surface_t        *surface,
                                                  double                  x,
                                                  double                  y);
+void    gtk_css_style_snapshot_icon             (GtkCssStyle            *style,
+                                                 GtkSnapshot            *snapshot,
+                                                 GskTexture             *texture);
 
 void    gtk_css_style_render_icon_get_extents   (GtkCssStyle            *style,
                                                  GdkRectangle           *extents,
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 62defef..aacb24f 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -24,6 +24,7 @@
 #include "gtkcssshadowsvalueprivate.h"
 #include "gtkrenderbackgroundprivate.h"
 #include "gtkrenderborderprivate.h"
+#include "gtkrendericonprivate.h"
 #include "gtkstylecontextprivate.h"
 
 #include "gsk/gskrendernodeprivate.h"
@@ -185,6 +186,39 @@ gtk_snapshot_append_node (GtkSnapshot   *state,
     }
 }
 
+GskRenderNode *
+gtk_snapshot_append (GtkSnapshot           *state,
+                     const graphene_rect_t *bounds,
+                     const char            *name,
+                     ...)
+{
+  GskRenderNode *node;
+
+  g_return_val_if_fail (state != NULL, NULL);
+  g_return_val_if_fail (bounds != NULL, NULL);
+
+  node = gsk_renderer_create_render_node (state->renderer);
+  gsk_render_node_set_bounds (node, bounds);
+
+  if (name)
+    {
+      va_list args;
+      char *str;
+
+      va_start (args, name);
+      str = g_strdup_vprintf (name, args);
+      va_end (args);
+
+      gsk_render_node_set_name (node, str);
+
+      g_free (str);
+    }
+
+  gtk_snapshot_append_node (state, node);
+
+  return node;
+}
+
 cairo_t *
 gtk_snapshot_append_cairo_node (GtkSnapshot           *state,
                                 const graphene_rect_t *bounds,
@@ -357,3 +391,21 @@ gtk_snapshot_render_layout (GtkSnapshot     *state,
   gtk_snapshot_translate_2d (state, -x, -y);
 }
 
+void
+gtk_snapshot_render_icon (GtkSnapshot     *snapshot,
+                          GtkStyleContext *context,
+                          GdkPixbuf       *pixbuf,
+                          gdouble          x,
+                          gdouble          y)
+{
+  GskTexture *texture;
+
+  texture = gsk_texture_new_for_pixbuf (snapshot->renderer, pixbuf);
+  gtk_snapshot_translate_2d (snapshot, x, y);
+  gtk_css_style_snapshot_icon (gtk_style_context_lookup_style (context),
+                               snapshot,
+                               texture);
+  gtk_snapshot_translate_2d (snapshot, -x, -y);
+  gsk_texture_unref (texture);
+}
+
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index 74be2c1..20315b0 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -73,6 +73,11 @@ GDK_AVAILABLE_IN_3_90
 void            gtk_snapshot_append_node                (GtkSnapshot            *state,
                                                          GskRenderNode          *node);
 GDK_AVAILABLE_IN_3_90
+GskRenderNode * gtk_snapshot_append                     (GtkSnapshot            *state,
+                                                         const graphene_rect_t  *bounds,
+                                                         const char             *name,
+                                                         ...) G_GNUC_PRINTF(3, 4);
+GDK_AVAILABLE_IN_3_90
 cairo_t *       gtk_snapshot_append_cairo_node          (GtkSnapshot            *state,
                                                          const graphene_rect_t  *bounds,
                                                          const char             *name,
@@ -117,6 +122,12 @@ void            gtk_snapshot_render_insertion_cursor    (GtkSnapshot
                                                          PangoLayout            *layout,
                                                          int                     index,
                                                          PangoDirection          direction);
+GDK_AVAILABLE_IN_3_90
+void            gtk_snapshot_render_icon                (GtkSnapshot            *snapshot,
+                                                         GtkStyleContext        *context,
+                                                         GdkPixbuf              *pixbuf,
+                                                         gdouble                 x,
+                                                         gdouble                 y);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]