[gtk+/wip/otte/snapshot: 7/30] snapshot: Add gtk_snapshot_render_background()



commit ee84f14c07b2fb3aba03ea5662d96d04b74dfa6c
Author: Benjamin Otte <otte redhat com>
Date:   Sun Nov 13 16:16:39 2016 +0100

    snapshot: Add gtk_snapshot_render_background()
    
    and gtk_snapshot_render_frame() to be direct replacements for the
    old gtk_render_*() functions.
    
    Use them to replace Cairo usage completely in gtk_window_snapshot().

 gtk/gtkrenderbackground.c        |   43 ++++++++++++++++
 gtk/gtkrenderbackgroundprivate.h |    7 ++-
 gtk/gtkrenderborder.c            |  103 ++++++++++++++++++++++++++++++++++++++
 gtk/gtkrenderborderprivate.h     |   10 ++++
 gtk/gtksnapshot.c                |   77 +++++++++++++++++++++++++++-
 gtk/gtksnapshot.h                |   22 ++++++++
 gtk/gtkwindow.c                  |   74 ++++++++++++---------------
 7 files changed, 291 insertions(+), 45 deletions(-)
---
diff --git a/gtk/gtkrenderbackground.c b/gtk/gtkrenderbackground.c
index f3e09e4..2e850ca 100644
--- a/gtk/gtkrenderbackground.c
+++ b/gtk/gtkrenderbackground.c
@@ -593,3 +593,46 @@ gtk_css_style_render_background_is_opaque (GtkCssStyle *style)
       && corner_value_is_right_angle (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS))
       && corner_value_is_right_angle (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS));
 }
+
+void
+gtk_css_style_snapshot_background (GtkCssStyle      *style,
+                                   GtkSnapshot      *snapshot,
+                                   gdouble           width,
+                                   gdouble           height,
+                                   GtkJunctionSides  junction)
+{
+  GtkCssValue *background_image;
+  GtkCssValue *box_shadow;
+  const GdkRGBA *bg_color;
+  GtkBorder shadow;
+  graphene_rect_t bounds;
+  cairo_t *cr;
+
+  background_image = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_IMAGE);
+  bg_color = _gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BACKGROUND_COLOR));
+  box_shadow = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BOX_SHADOW);
+
+  /* This is the common default case of no background */
+  if (gtk_rgba_is_clear (bg_color) &&
+      _gtk_css_array_value_get_n_values (background_image) == 1 &&
+      _gtk_css_image_value_get_image (_gtk_css_array_value_get_nth (background_image, 0)) == NULL &&
+      _gtk_css_shadows_value_is_none (box_shadow))
+    return;
+
+  _gtk_css_shadows_value_get_extents (box_shadow, &shadow);
+
+  graphene_rect_init (&bounds,
+                      - shadow.left,
+                      - shadow.top,
+                      ceil (width) + shadow.left + shadow.right,
+                      ceil (height) + shadow.top + shadow.bottom);
+
+  cr = gtk_snapshot_append_cairo_node (snapshot,
+                                       &bounds,
+                                       "Background");
+
+  gtk_css_style_render_background (style, cr, 0, 0, width, height, junction);
+
+  cairo_destroy (cr);
+}
+
diff --git a/gtk/gtkrenderbackgroundprivate.h b/gtk/gtkrenderbackgroundprivate.h
index a3927f0..cb6ab5b 100644
--- a/gtk/gtkrenderbackgroundprivate.h
+++ b/gtk/gtkrenderbackgroundprivate.h
@@ -24,8 +24,8 @@
 #include <cairo.h>
 
 #include "gtkcsstypesprivate.h"
+#include "gtksnapshot.h"
 #include "gtktypes.h"
-#include "gsk/gsk.h"
 
 G_BEGIN_DECLS
 
@@ -47,6 +47,11 @@ void            gtk_css_style_add_background_render_nodes       (GtkCssStyle
                                                                  gdouble           width,
                                                                  gdouble           height,
                                                                  GtkJunctionSides  junction);
+void            gtk_css_style_snapshot_background               (GtkCssStyle          *style,
+                                                                 GtkSnapshot          *snapshot,
+                                                                 gdouble               width,
+                                                                 gdouble               height,
+                                                                 GtkJunctionSides      junction);
 
 
 
diff --git a/gtk/gtkrenderborder.c b/gtk/gtkrenderborder.c
index f755f9f..2672dec 100644
--- a/gtk/gtkrenderborder.c
+++ b/gtk/gtkrenderborder.c
@@ -757,6 +757,71 @@ gtk_css_style_render_border (GtkCssStyle      *style,
     }
 }
 
+void
+gtk_css_style_snapshot_border (GtkCssStyle      *style,
+                               GtkSnapshot      *state,
+                               gdouble           width,
+                               gdouble           height,
+                               GtkJunctionSides  junction)
+{
+  GtkBorderImage border_image;
+  double border_width[4];
+  graphene_rect_t bounds;
+  cairo_t *cr;
+
+  border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100);
+  border_width[1] = _gtk_css_number_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100);
+  border_width[2] = _gtk_css_number_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100);
+  border_width[3] = _gtk_css_number_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100);
+
+  graphene_rect_init (&bounds, 0, 0, width, height);
+
+  if (gtk_border_image_init (&border_image, style))
+    {
+      cr = gtk_snapshot_append_cairo_node (state,
+                                           &bounds,
+                                           "Border Image");
+      gtk_border_image_render (&border_image, border_width, cr, 0, 0, width, height);
+      cairo_destroy (cr);
+    }
+  else
+    {
+      GtkBorderStyle border_style[4];
+      GtkRoundedBox border_box;
+      GdkRGBA colors[4];
+
+      /* Optimize the most common case of "This widget has no border" */
+      if (border_width[0] == 0 &&
+          border_width[1] == 0 &&
+          border_width[2] == 0 &&
+          border_width[3] == 0)
+        return;
+
+      cr = gtk_snapshot_append_cairo_node (state,
+                                           &bounds,
+                                           "Border");
+
+      border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_TOP_STYLE));
+      border_style[1] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE));
+      border_style[2] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE));
+      border_style[3] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_LEFT_STYLE));
+
+      hide_border_sides (border_width, border_style, 0);
+
+      colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_TOP_COLOR));
+      colors[1] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR));
+      colors[2] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR));
+      colors[3] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_BORDER_LEFT_COLOR));
+
+      _gtk_rounded_box_init_rect (&border_box, 0, 0, width, height);
+      _gtk_rounded_box_apply_border_radius_for_style (&border_box, style, junction);
+
+      render_border (cr, &border_box, border_width, 0, colors, border_style);
+
+      cairo_destroy (cr);
+    }
+}
+
 gboolean
 gtk_css_style_render_border_get_clip (GtkCssStyle  *style,
                                       gdouble       x,
@@ -854,6 +919,44 @@ gtk_css_style_render_outline (GtkCssStyle *style,
     }
 }
 
+void
+gtk_css_style_snapshot_outline (GtkCssStyle *style,
+                                GtkSnapshot *state,
+                                gdouble      width,
+                                gdouble      height)
+{
+  GtkBorderStyle border_style[4];
+  GtkRoundedBox border_box;
+  double border_width[4];
+  GdkRGBA colors[4];
+
+  border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_OUTLINE_STYLE));
+  if (border_style[0] != GTK_BORDER_STYLE_NONE)
+    {
+      cairo_rectangle_t rect;
+      cairo_t *cr;
+
+      compute_outline_rect (style, 0, 0, width, height, &rect);
+
+      border_style[1] = border_style[2] = border_style[3] = border_style[0];
+      border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
+      border_width[3] = border_width[2] = border_width[1] = border_width[0];
+      colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_OUTLINE_COLOR));
+      colors[3] = colors[2] = colors[1] = colors[0];
+
+      _gtk_rounded_box_init_rect (&border_box, rect.x, rect.y, rect.width, rect.height);
+      _gtk_rounded_box_apply_outline_radius_for_style (&border_box, style, GTK_JUNCTION_NONE);
+
+      cr = gtk_snapshot_append_cairo_node (state,
+                                           &(graphene_rect_t) GRAPHENE_RECT_INIT (rect.x, rect.y, 
rect.width, rect.height),
+                                           "Outline");
+
+      render_border (cr, &border_box, border_width, 0, colors, border_style);
+
+      cairo_destroy (cr);
+    }
+}
+
 gboolean
 gtk_css_style_render_outline_get_clip (GtkCssStyle  *style,
                                        gdouble       x,
diff --git a/gtk/gtkrenderborderprivate.h b/gtk/gtkrenderborderprivate.h
index b72010e..e05a664 100644
--- a/gtk/gtkrenderborderprivate.h
+++ b/gtk/gtkrenderborderprivate.h
@@ -25,6 +25,7 @@
 #include "gtkborder.h"
 #include "gtkcssimageprivate.h"
 #include "gtkcssvalueprivate.h"
+#include "gtksnapshot.h"
 
 G_BEGIN_DECLS
 
@@ -43,6 +44,11 @@ gboolean        gtk_css_style_render_border_get_clip    (GtkCssStyle
                                                          gdouble                 width,
                                                          gdouble                 height,
                                                          GdkRectangle           *out_clip) 
G_GNUC_WARN_UNUSED_RESULT;
+void            gtk_css_style_snapshot_border           (GtkCssStyle            *style,
+                                                         GtkSnapshot            *state,
+                                                         gdouble                 width,
+                                                         gdouble                 height,
+                                                         GtkJunctionSides        junction);
 
 gboolean        gtk_css_style_render_has_outline        (GtkCssStyle            *style);
 void            gtk_css_style_render_outline            (GtkCssStyle            *style,
@@ -51,6 +57,10 @@ void            gtk_css_style_render_outline            (GtkCssStyle
                                                          gdouble                 y,
                                                          gdouble                 width,
                                                          gdouble                 height);
+void            gtk_css_style_snapshot_outline          (GtkCssStyle            *style,
+                                                         GtkSnapshot            *state,
+                                                         gdouble                 width,
+                                                         gdouble                 height);
 gboolean        gtk_css_style_render_outline_get_clip   (GtkCssStyle            *style,
                                                          gdouble                 x,
                                                          gdouble                 y,
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index c638243..2a0507a 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -20,6 +20,10 @@
 #include "gtksnapshot.h"
 #include "gtksnapshotprivate.h"
 
+#include "gtkrenderbackgroundprivate.h"
+#include "gtkrenderborderprivate.h"
+#include "gtkstylecontextprivate.h"
+
 #include "gsk/gskrendernodeprivate.h"
 
 void
@@ -45,8 +49,8 @@ gtk_snapshot_finish (GtkSnapshot *state)
 }
 
 void
-gtk_snapshot_push (GtkSnapshot   *state,
-                   GskRenderNode *node)
+gtk_snapshot_push_node (GtkSnapshot   *state,
+                        GskRenderNode *node)
 {
   gtk_snapshot_append_node (state, node);
 
@@ -55,6 +59,35 @@ gtk_snapshot_push (GtkSnapshot   *state,
 }
 
 void
+gtk_snapshot_push (GtkSnapshot           *state,
+                   const graphene_rect_t *bounds,
+                   const char            *name,
+                   ...)
+{
+  GskRenderNode *node;
+
+  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_push_node (state, node);
+  gsk_render_node_unref (node);
+}
+
+void
 gtk_snapshot_pop (GtkSnapshot *state)
 {
   if (state->node == NULL)
@@ -212,8 +245,46 @@ gtk_snapshot_push_cairo_node (GtkSnapshot            *state,
       g_free (str);
     }
 
-  gtk_snapshot_push (state, node);
+  gtk_snapshot_push_node (state, node);
   gsk_render_node_unref (node);
 
   return gsk_render_node_get_draw_context (node, state->renderer);
 }
+
+void
+gtk_snapshot_render_background (GtkSnapshot     *state,
+                                GtkStyleContext *context,
+                                gdouble          x,
+                                gdouble          y,
+                                gdouble          width,
+                                gdouble          height)
+{
+  g_return_if_fail (state != NULL);
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+  gtk_snapshot_translate_2d (state, x, y);
+  gtk_css_style_snapshot_background (gtk_style_context_lookup_style (context),
+                                     state,
+                                     width, height,
+                                     gtk_style_context_get_junction_sides (context));
+  gtk_snapshot_translate_2d (state, -x, -y);
+}
+
+void
+gtk_snapshot_render_frame (GtkSnapshot     *state,
+                           GtkStyleContext *context,
+                           gdouble          x,
+                           gdouble          y,
+                           gdouble          width,
+                           gdouble          height)
+{
+  g_return_if_fail (state != NULL);
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+  gtk_snapshot_translate_2d (state, x, y);
+  gtk_css_style_snapshot_border (gtk_style_context_lookup_style (context),
+                                 state,
+                                 width, height,
+                                 gtk_style_context_get_junction_sides (context));
+  gtk_snapshot_translate_2d (state, -x, -y);
+}
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index b5a4b38..90ecef0 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -32,6 +32,8 @@
 
 #include <gsk/gsk.h>
 
+#include <gtk/gtktypes.h>
+
 G_BEGIN_DECLS
 
 typedef struct _GtkSnapshot GtkSnapshot;
@@ -42,6 +44,11 @@ GskRenderer *   gtk_snapshot_get_renderer               (const GtkSnapshot
 
 GDK_AVAILABLE_IN_3_90
 void            gtk_snapshot_push                       (GtkSnapshot            *state,
+                                                         const graphene_rect_t  *bounds,
+                                                         const char             *name,
+                                                         ...) G_GNUC_PRINTF(3, 4);
+GDK_AVAILABLE_IN_3_90
+void            gtk_snapshot_push_node                 (GtkSnapshot            *state,
                                                          GskRenderNode          *node);
 GDK_AVAILABLE_IN_3_90
 cairo_t *       gtk_snapshot_push_cairo_node            (GtkSnapshot            *state,
@@ -71,6 +78,21 @@ cairo_t *       gtk_snapshot_append_cairo_node          (GtkSnapshot
                                                          const char             *name,
                                                          ...) G_GNUC_PRINTF(3, 4);
 
+GDK_AVAILABLE_IN_3_90
+void            gtk_snapshot_render_background          (GtkSnapshot            *state,
+                                                         GtkStyleContext        *context,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height);
+GDK_AVAILABLE_IN_3_90
+void            gtk_snapshot_render_frame               (GtkSnapshot            *state,
+                                                         GtkStyleContext        *context,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height);
+
 G_END_DECLS
 
 #endif /* __GTK_SNAPSHOT_H__ */
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 19136e8..9854f2e 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -9379,9 +9379,6 @@ gtk_window_snapshot (GtkWidget   *widget,
   GtkBorder window_border;
   gint title_height;
   graphene_rect_t bounds;
-  graphene_matrix_t m;
-  graphene_point3d_t p;
-  cairo_t *cr;
   GList *l;
 
   context = gtk_widget_get_style_context (widget);
@@ -9390,11 +9387,8 @@ gtk_window_snapshot (GtkWidget   *widget,
   _gtk_widget_get_allocation (widget, &allocation);
 
   graphene_rect_init (&bounds, allocation.x, allocation.y, allocation.width, allocation.height);
-  graphene_matrix_init_translate (&m, graphene_point3d_init (&p, allocation.x, allocation.y, 0.));
 
-  cr = gtk_snapshot_push_cairo_node (snapshot,
-                                     &bounds, 
-                                     "Window Decoration");
+  gtk_snapshot_push (snapshot, &bounds, "Window Decoration");
 
   if (priv->client_decorated &&
       priv->decorated &&
@@ -9411,28 +9405,28 @@ gtk_window_snapshot (GtkWidget   *widget,
           gtk_style_context_get_border (context, &border);
           sum_borders (&border, &padding);
 
-          gtk_render_background (context, cr,
-                                 window_border.left - border.left, window_border.top - border.top,
-                                 allocation.width -
-                                   (window_border.left + window_border.right - border.left - border.right),
-                                 allocation.height -
-                                   (window_border.top + window_border.bottom - border.top - border.bottom));
-          gtk_render_frame (context, cr,
-                            window_border.left - border.left, window_border.top - border.top,
-                            allocation.width -
-                              (window_border.left + window_border.right - border.left - border.right),
-                            allocation.height -
-                              (window_border.top + window_border.bottom - border.top - border.bottom));
+          gtk_snapshot_render_background (snapshot, context,
+                                          window_border.left - border.left, window_border.top - border.top,
+                                          allocation.width -
+                                            (window_border.left + window_border.right - border.left - 
border.right),
+                                          allocation.height -
+                                            (window_border.top + window_border.bottom - border.top - 
border.bottom));
+          gtk_snapshot_render_frame (snapshot, context,
+                                     window_border.left - border.left, window_border.top - border.top,
+                                     allocation.width -
+                                       (window_border.left + window_border.right - border.left - 
border.right),
+                                     allocation.height -
+                                       (window_border.top + window_border.bottom - border.top - 
border.bottom));
         }
       else
         {
-          gtk_render_background (context, cr, 0, 0,
-                                 allocation.width,
-                                 allocation.height);
+          gtk_snapshot_render_background (snapshot, context, 0, 0,
+                                          allocation.width,
+                                          allocation.height);
 
-          gtk_render_frame (context, cr, 0, 0,
-                            allocation.width,
-                            allocation.height);
+          gtk_snapshot_render_frame (snapshot, context, 0, 0,
+                                     allocation.width,
+                                     allocation.height);
         }
       gtk_style_context_restore (context);
     }
@@ -9444,22 +9438,20 @@ gtk_window_snapshot (GtkWidget   *widget,
   else
     title_height = 0;
 
-  gtk_render_background (context, cr,
-                         window_border.left,
-                         window_border.top + title_height,
-                         allocation.width -
-                           (window_border.left + window_border.right),
-                         allocation.height -
-                           (window_border.top + window_border.bottom + title_height));
-  gtk_render_frame (context, cr,
-                    window_border.left,
-                    window_border.top + title_height,
-                    allocation.width -
-                      (window_border.left + window_border.right),
-                    allocation.height -
-                      (window_border.top + window_border.bottom + title_height));
-
-  cairo_destroy (cr);
+  gtk_snapshot_render_background (snapshot, context,
+                                  window_border.left,
+                                  window_border.top + title_height,
+                                  allocation.width -
+                                    (window_border.left + window_border.right),
+                                  allocation.height -
+                                    (window_border.top + window_border.bottom + title_height));
+  gtk_snapshot_render_frame (snapshot, context,
+                             window_border.left,
+                             window_border.top + title_height,
+                             allocation.width -
+                               (window_border.left + window_border.right),
+                             allocation.height -
+                               (window_border.top + window_border.bottom + title_height));
 
   if (priv->title_box != NULL)
     gtk_container_snapshot_child (GTK_CONTAINER (widget), priv->title_box, snapshot);


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