[gtk+/wip/baedert/gl: 213/216] snapshot: Add & use API for linear gradient nodes



commit c4f946c3989fc3a25a044a76bad1dde67b330ee2
Author: Timm Bäder <mail baedert org>
Date:   Wed Dec 13 09:05:49 2017 +0100

    snapshot: Add & use API for linear gradient nodes
    
    This way, we can also clip the created node bounds to the current clip
    of the GtkSnapshot. This works as long as we don't modify the start and
    end points, and happens all the time while rendering.

 gtk/gtkcssimagelinear.c |   40 ++++--------
 gtk/gtksnapshot.c       |  160 +++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtksnapshot.h       |   19 ++++++
 3 files changed, 193 insertions(+), 26 deletions(-)
---
diff --git a/gtk/gtkcssimagelinear.c b/gtk/gtkcssimagelinear.c
index 97ce80a..87cc64a 100644
--- a/gtk/gtkcssimagelinear.c
+++ b/gtk/gtkcssimagelinear.c
@@ -135,15 +135,12 @@ gtk_css_image_linear_snapshot (GtkCssImage        *image,
 {
   GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
   GskColorStop *stops;
-  GskRenderNode *node;
-  int off_x, off_y; /* snapshot offset */
   double angle; /* actual angle of the gradiant line in degrees */
   double x, y; /* coordinates of start point */
   double length; /* distance in pixels for 100% */
   double start, end; /* position of first/last point on gradient line - with gradient line being [0, 1] */
   double offset;
   int i, last;
-  char *name;
 
   if (linear->side)
     {
@@ -233,37 +230,28 @@ gtk_css_image_linear_snapshot (GtkCssImage        *image,
       last = i;
     }
 
-  gtk_snapshot_get_offset (snapshot, &off_x, &off_y);
-
   if (linear->repeating)
     {
-      node = gsk_repeating_linear_gradient_node_new (
-          &GRAPHENE_RECT_INIT (off_x, off_y, width, height),
-          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 
0.5)),
-          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5),   off_y + height / 2 + y * (end - 0.5)),
+      gtk_snapshot_append_repeating_linear_gradient (
+          snapshot,
+          &GRAPHENE_RECT_INIT (0, 0, width, height),
+          &GRAPHENE_POINT_INIT (width / 2 + x * (start - 0.5), height / 2 + y * (start - 0.5)),
+          &GRAPHENE_POINT_INIT (width / 2 + x * (end - 0.5),   height / 2 + y * (end - 0.5)),
           stops,
-          linear->stops->len);
+          linear->stops->len,
+          "RepeatingLinearGradient<%ustops>", linear->stops->len);
     }
   else
     {
-      node = gsk_linear_gradient_node_new (
-          &GRAPHENE_RECT_INIT (off_x, off_y, width, height),
-          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 
0.5)),
-          &GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5),   off_y + height / 2 + y * (end - 0.5)),
+      gtk_snapshot_append_linear_gradient (
+          snapshot,
+          &GRAPHENE_RECT_INIT (0, 0, width, height),
+          &GRAPHENE_POINT_INIT (width / 2 + x * (start - 0.5), height / 2 + y * (start - 0.5)),
+          &GRAPHENE_POINT_INIT (width / 2 + x * (end - 0.5),   height / 2 + y * (end - 0.5)),
           stops,
-          linear->stops->len);
-    }
-
-  if (snapshot->record_names)
-    {
-      name = g_strdup_printf ("%sLinearGradient<%ustops>", linear->repeating ? "Repeating" : "", 
linear->stops->len);
-      gsk_render_node_set_name (node, name);
-      g_free (name);
+          linear->stops->len,
+          "LinearGradient<%ustops>", linear->stops->len);
     }
-
-  gtk_snapshot_append_node (snapshot, node);
-
-  gsk_render_node_unref (node);
 }
 
 
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index c3f9295..e16e0d3 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -1553,3 +1553,163 @@ gtk_snapshot_render_layout (GtkSnapshot     *snapshot,
 
   gtk_snapshot_offset (snapshot, -x, -y);
 }
+
+/*
+ * gtk_snapshot_append_linear_gradient:
+ * @snapshot: a #GtkSnapshot
+ * @bounds: the rectangle to render the linear gradient into
+ * @start: the point at which the linear gradient will begin
+ * @end: the point at which the linear gradient will finish
+ * @stops: (array length=n_stops): a pointer to an array of #GskColorStop defining the gradient
+ * @n_stops: the number of elements in @color_stops
+ *
+ * Appends a linear gradient node with the given stops to @snapshot.
+ *
+ * Since: 3.94
+ */
+void
+gtk_snapshot_append_linear_gradient (GtkSnapshot            *snapshot,
+                                     const graphene_rect_t  *bounds,
+                                     const graphene_point_t *start_point,
+                                     const graphene_point_t *end_point,
+                                     const GskColorStop     *stops,
+                                     gsize                   n_stops,
+                                     const char             *name,
+                                     ...)
+{
+  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
+  GskRenderNode *node;
+  graphene_rect_t real_bounds;
+  graphene_point_t real_start_point;
+  graphene_point_t real_end_point;
+
+  g_return_if_fail (snapshot != NULL);
+  g_return_if_fail (start_point != NULL);
+  g_return_if_fail (end_point != NULL);
+  g_return_if_fail (stops != NULL);
+  g_return_if_fail (n_stops > 1);
+
+  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
+  real_start_point.x = start_point->x + current_state->translate_x;
+  real_start_point.y = start_point->y + current_state->translate_y;
+  real_end_point.x = end_point->x + current_state->translate_x;
+  real_end_point.y = end_point->y + current_state->translate_y;
+
+  /* Linear gradients can be trivially clipped if we don't change the start/end points. */
+  if (current_state->clip_region)
+    {
+      cairo_rectangle_int_t clip_extents;
+
+      cairo_region_get_extents (current_state->clip_region, &clip_extents);
+      graphene_rect_intersection (&GRAPHENE_RECT_INIT (
+                                    clip_extents.x,
+                                    clip_extents.y,
+                                    clip_extents.width,
+                                    clip_extents.height
+                                  ),
+                                  &real_bounds, &real_bounds);
+    }
+
+  node = gsk_linear_gradient_node_new (&real_bounds,
+                                       &real_start_point,
+                                       &real_end_point,
+                                       stops,
+                                       n_stops);
+
+  if (name && snapshot->record_names)
+    {
+      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 (snapshot, node);
+  gsk_render_node_unref (node);
+}
+
+/*
+ * gtk_snapshot_append_repeating_linear_gradient:
+ * @snapshot: a #GtkSnapshot
+ * @bounds: the rectangle to render the linear gradient into
+ * @start: the point at which the linear gradient will begin
+ * @end: the point at which the linear gradient will finish
+ * @stops: (array length=n_stops): a pointer to an array of #GskColorStop defining the gradient
+ * @n_stops: the number of elements in @color_stops
+ *
+ * Appends a repeating linear gradient node with the given stops to @snapshot.
+ *
+ * Since: 3.94
+ */
+void
+gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot            *snapshot,
+                                               const graphene_rect_t  *bounds,
+                                               const graphene_point_t *start_point,
+                                               const graphene_point_t *end_point,
+                                               const GskColorStop     *stops,
+                                               gsize                   n_stops,
+                                               const char             *name,
+                                               ...)
+{
+  const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
+  GskRenderNode *node;
+  graphene_rect_t real_bounds;
+  graphene_point_t real_start_point;
+  graphene_point_t real_end_point;
+
+  g_return_if_fail (snapshot != NULL);
+  g_return_if_fail (start_point != NULL);
+  g_return_if_fail (end_point != NULL);
+  g_return_if_fail (stops != NULL);
+  g_return_if_fail (n_stops > 1);
+
+  graphene_rect_offset_r (bounds, current_state->translate_x, current_state->translate_y, &real_bounds);
+  real_start_point.x = start_point->x + current_state->translate_x;
+  real_start_point.y = start_point->y + current_state->translate_y;
+  real_end_point.x = end_point->x + current_state->translate_x;
+  real_end_point.y = end_point->y + current_state->translate_y;
+
+  /* Repeating Linear gradients can be trivially clipped if we don't change the start/end points. */
+  if (current_state->clip_region)
+    {
+      cairo_rectangle_int_t clip_extents;
+
+      cairo_region_get_extents (current_state->clip_region, &clip_extents);
+      graphene_rect_intersection (&GRAPHENE_RECT_INIT (
+                                    clip_extents.x,
+                                    clip_extents.y,
+                                    clip_extents.width,
+                                    clip_extents.height
+                                  ),
+                                  &real_bounds, &real_bounds);
+    }
+
+  node = gsk_repeating_linear_gradient_node_new (&real_bounds,
+                                                 &real_start_point,
+                                                 &real_end_point,
+                                                 stops,
+                                                 n_stops);
+
+  if (name && snapshot->record_names)
+    {
+      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 (snapshot, node);
+  gsk_render_node_unref (node);
+}
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index e1a1e2a..5d9657d 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -166,6 +166,25 @@ void            gtk_snapshot_render_insertion_cursor    (GtkSnapshot
                                                          PangoLayout            *layout,
                                                          int                     index,
                                                          PangoDirection          direction);
+GDK_AVAILABLE_IN_3_94
+void            gtk_snapshot_append_linear_gradient     (GtkSnapshot            *snapshot,
+                                                         const graphene_rect_t  *bounds,
+                                                         const graphene_point_t *start_point,
+                                                         const graphene_point_t *end_point,
+                                                         const GskColorStop     *stops,
+                                                         gsize                   n_stops,
+                                                         const char             *name,
+                                                         ...) G_GNUC_PRINTF (7, 8);
+GDK_AVAILABLE_IN_3_94
+void            gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot            *snapshot,
+                                                               const graphene_rect_t  *bounds,
+                                                               const graphene_point_t *start_point,
+                                                               const graphene_point_t *end_point,
+                                                               const GskColorStop     *stops,
+                                                               gsize                   n_stops,
+                                                                const char             *name,
+                                                               ...) G_GNUC_PRINTF (7, 8);
+
 
 G_END_DECLS
 


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