[gtk+] snapshot: Convert GtkLabel and GtkAccelLabel



commit 349f55f2feb27cce00d32bb89fedcb33990fdd85
Author: Benjamin Otte <otte redhat com>
Date:   Mon Nov 14 22:58:58 2016 +0100

    snapshot: Convert GtkLabel and GtkAccelLabel
    
    Also adds gtk_snapshot_render_insertion_cursor().

 gtk/gtkaccellabel.c   |   46 ++++++---------
 gtk/gtklabel.c        |  104 ++++++++++++++++++----------------
 gtk/gtksnapshot.c     |   18 ++++++
 gtk/gtksnapshot.h     |   15 +++++
 gtk/gtkstylecontext.c |  147 ++++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 252 insertions(+), 78 deletions(-)
---
diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c
index 93b660a..954b1d3 100644
--- a/gtk/gtkaccellabel.c
+++ b/gtk/gtkaccellabel.c
@@ -139,8 +139,8 @@ static void         gtk_accel_label_get_property (GObject            *object,
                                                  GParamSpec         *pspec);
 static void         gtk_accel_label_destroy      (GtkWidget          *widget);
 static void         gtk_accel_label_finalize     (GObject            *object);
-static GskRenderNode *gtk_accel_label_get_render_node (GtkWidget   *widget,
-                                                       GskRenderer *renderer);
+static void         gtk_accel_label_snapshot     (GtkWidget          *widget,
+                                                  GtkSnapshot        *snapshot);
 static const gchar *gtk_accel_label_get_string   (GtkAccelLabel      *accel_label);
 static void gtk_accel_label_measure (GtkWidget      *widget,
                                      GtkOrientation  orientation,
@@ -163,7 +163,7 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
   gobject_class->set_property = gtk_accel_label_set_property;
   gobject_class->get_property = gtk_accel_label_get_property;
 
-  widget_class->get_render_node = gtk_accel_label_get_render_node;
+  widget_class->snapshot = gtk_accel_label_snapshot;
   widget_class->measure = gtk_accel_label_measure;
   widget_class->destroy = gtk_accel_label_destroy;
 
@@ -457,20 +457,26 @@ get_first_baseline (PangoLayout *layout)
   return PANGO_PIXELS (result);
 }
 
-static GskRenderNode *
-gtk_accel_label_get_render_node (GtkWidget   *widget,
-                                 GskRenderer *renderer)
+static void
+gtk_accel_label_snapshot (GtkWidget   *widget,
+                          GtkSnapshot *snapshot)
 {
   GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
   guint ac_width;
-  GtkAllocation allocation;
+  GtkAllocation allocation, clip;
   GtkRequisition requisition;
-  GskRenderNode *res;
+  graphene_rect_t bounds;
+
+  gtk_widget_get_clip (widget, &clip);
+  gtk_widget_get_allocation (widget, &allocation);
+  graphene_rect_init (&bounds,
+                      clip.x - allocation.x, clip.y - allocation.y,
+                      clip.width, clip.height);
+  gtk_snapshot_push (snapshot, &bounds, "AccelLabel");
 
-  res = GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->get_render_node (widget, renderer);
+  GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->snapshot (widget, snapshot);
 
   ac_width = gtk_accel_label_get_accel_width (accel_label);
-  gtk_widget_get_allocation (widget, &allocation);
   gtk_widget_get_preferred_size (widget, NULL, &requisition);
 
   if (allocation.width >= requisition.width + ac_width)
@@ -480,17 +486,6 @@ gtk_accel_label_get_render_node (GtkWidget   *widget,
       PangoLayout *accel_layout;
       gint x;
       gint y;
-      GtkAllocation alloc, clip;
-      GskRenderNode *node;
-      cairo_t *cr;
-
-      node = gtk_widget_create_render_node (widget, renderer, "AccelLabel Content");
-
-      gtk_widget_get_clip (widget, &clip);
-      _gtk_widget_get_allocation (widget, &alloc);
-
-      cr = gsk_render_node_get_draw_context (node, renderer);
-      cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y);
 
       context = gtk_widget_get_style_context (widget);
 
@@ -507,18 +502,13 @@ gtk_accel_label_get_render_node (GtkWidget   *widget,
       y += get_first_baseline (label_layout) - get_first_baseline (accel_layout) - allocation.y;
 
       gtk_style_context_save_to_node (context, accel_label->priv->accel_node);
-      gtk_render_layout (context, cr, x, y, accel_layout);
+      gtk_snapshot_render_layout (snapshot, context, x, y, accel_layout);
       gtk_style_context_restore (context);
 
       g_object_unref (accel_layout);
-
-      cairo_destroy (cr);
-
-      gsk_render_node_append_child (res, node);
-      gsk_render_node_unref (node);
     }
 
-  return res;
+  gtk_snapshot_pop (snapshot);
 }
 
 static void
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 5461d3f..e9e6a69 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -414,12 +414,11 @@ static void gtk_label_size_allocate     (GtkWidget        *widget,
 static void gtk_label_state_flags_changed   (GtkWidget        *widget,
                                              GtkStateFlags     prev_state);
 static void gtk_label_style_updated     (GtkWidget        *widget);
+static void gtk_label_snapshot          (GtkWidget        *widget,
+                                         GtkSnapshot      *snapshot);
 static gboolean gtk_label_focus         (GtkWidget         *widget,
                                          GtkDirectionType   direction);
 
-static GskRenderNode *gtk_label_get_render_node (GtkWidget   *label,
-                                                 GskRenderer *renderer);
-
 static void gtk_label_realize           (GtkWidget        *widget);
 static void gtk_label_unrealize         (GtkWidget        *widget);
 static void gtk_label_map               (GtkWidget        *widget);
@@ -565,6 +564,13 @@ static void     gtk_label_measure (GtkCssGadget   *gadget,
                                    int            *minimum_baseline,
                                    int            *natural_baseline,
                                    gpointer        unused);
+static gboolean gtk_label_render  (GtkCssGadget   *gadget,
+                                   GtkSnapshot    *snapshot,
+                                   int             x,
+                                   int             y,
+                                   int             width,
+                                   int             height,
+                                   gpointer        data);
 
 static GtkBuildableIface *buildable_parent_iface = NULL;
 
@@ -612,7 +618,7 @@ gtk_label_class_init (GtkLabelClass *class)
   widget_class->state_flags_changed = gtk_label_state_flags_changed;
   widget_class->style_updated = gtk_label_style_updated;
   widget_class->query_tooltip = gtk_label_query_tooltip;
-  widget_class->get_render_node = gtk_label_get_render_node;
+  widget_class->snapshot = gtk_label_snapshot;
   widget_class->realize = gtk_label_realize;
   widget_class->unrealize = gtk_label_unrealize;
   widget_class->map = gtk_label_map;
@@ -1371,7 +1377,7 @@ gtk_label_init (GtkLabel *label)
                                                      gtk_label_measure,
                                                      NULL,
                                                      NULL,
-                                                     NULL,
+                                                     gtk_label_render,
                                                      NULL,
                                                      NULL);
 }
@@ -4153,41 +4159,38 @@ gtk_label_get_focus_link (GtkLabel *label)
   return NULL;
 }
 
+static void
+gtk_label_snapshot (GtkWidget   *widget,
+                    GtkSnapshot *snapshot)
+{
+  gtk_css_gadget_snapshot (GTK_LABEL (widget)->priv->gadget, snapshot);
+}
+
 static void layout_to_window_coords (GtkLabel *label,
                                      gint     *x,
                                      gint     *y);
+#define GRAPHENE_RECT_FROM_RECT(_r) ((graphene_rect_t) GRAPHENE_RECT_INIT ((_r)->x, (_r)->y, (_r)->width, 
(_r)->height))
 
-static GskRenderNode *
-gtk_label_get_render_node (GtkWidget   *widget,
-                           GskRenderer *renderer)
+static gboolean
+gtk_label_render (GtkCssGadget *gadget,
+                  GtkSnapshot  *snapshot,
+                  int           x,
+                  int           y,
+                  int           width,
+                  int           height,
+                  gpointer      data)
 {
-  GtkLabel *label = GTK_LABEL (widget);
-  GtkLabelPrivate *priv = label->priv;
-  GtkLabelSelectionInfo *info = priv->select_info;
+  GtkWidget *widget;
+  GtkLabel *label;
+  GtkLabelPrivate *priv;
+  GtkLabelSelectionInfo *info;
   GtkStyleContext *context;
-  gint x, y, width, height;
   gint lx, ly;
-  cairo_t *cr;
-  GtkAllocation alloc, clip;
-  GskRenderNode *node;
-  GskRenderNode *res;
 
-  res = gtk_css_gadget_get_render_node (priv->gadget, renderer, FALSE);
-
-  if (res == NULL)
-    return NULL;
-
-  node = gtk_widget_create_render_node (widget, renderer, "Label Content");
-
-  gtk_widget_get_clip (widget, &clip);
-  _gtk_widget_get_allocation (widget, &alloc);
-
-  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);
+  label = GTK_LABEL (widget);
+  priv = label->priv;
+  info = priv->select_info;
 
   gtk_label_ensure_layout (label);
 
@@ -4206,12 +4209,14 @@ gtk_label_get_render_node (GtkWidget   *widget,
       lx = ly = 0;
       layout_to_window_coords (label, &lx, &ly);
 
-      gtk_render_layout (context, cr, lx, ly, priv->layout);
+      gtk_snapshot_render_layout (snapshot, context, lx, ly, priv->layout);
 
       if (info && (info->selection_anchor != info->selection_end))
         {
           gint range[2];
           cairo_region_t *range_clip;
+          cairo_rectangle_int_t clip_extents;
+          cairo_t *cr;
 
           range[0] = info->selection_anchor;
           range[1] = info->selection_end;
@@ -4224,8 +4229,10 @@ gtk_label_get_render_node (GtkWidget   *widget,
             }
 
           range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
-
-          cairo_save (cr);
+          cairo_region_get_extents (range_clip, &clip_extents);
+          cr = gtk_snapshot_append_cairo_node (snapshot,
+                                               &GRAPHENE_RECT_FROM_RECT(&clip_extents),
+                                               "Selected Text");
           gtk_style_context_save_to_node (context, info->selection_node);
 
           gdk_cairo_region (cr, range_clip);
@@ -4235,7 +4242,7 @@ gtk_label_get_render_node (GtkWidget   *widget,
           gtk_render_layout (context, cr, lx, ly, priv->layout);
 
           gtk_style_context_restore (context);
-          cairo_restore (cr);
+          cairo_destroy (cr);
           cairo_region_destroy (range_clip);
         }
       else if (info)
@@ -4244,7 +4251,9 @@ gtk_label_get_render_node (GtkWidget   *widget,
           GtkLabelLink *active_link;
           gint range[2];
           cairo_region_t *range_clip;
+          cairo_rectangle_int_t clip_extents;
           GdkRectangle rect;
+          cairo_t *cr;
 
           if (info->selectable &&
               gtk_widget_has_focus (widget) &&
@@ -4253,10 +4262,10 @@ gtk_label_get_render_node (GtkWidget   *widget,
               PangoDirection cursor_direction;
 
               cursor_direction = get_cursor_direction (label);
-              gtk_render_insertion_cursor (context, cr,
-                                           lx, ly,
-                                           priv->layout, priv->select_info->selection_end,
-                                           cursor_direction);
+              gtk_snapshot_render_insertion_cursor (snapshot, context,
+                                                    lx, ly,
+                                                    priv->layout, priv->select_info->selection_end,
+                                                    cursor_direction);
             }
 
           focus_link = gtk_label_get_focus_link (label);
@@ -4267,11 +4276,13 @@ gtk_label_get_render_node (GtkWidget   *widget,
               range[0] = active_link->start;
               range[1] = active_link->end;
 
-              cairo_save (cr);
               gtk_style_context_save_to_node (context, active_link->cssnode);
 
               range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
-
+              cairo_region_get_extents (range_clip, &clip_extents);
+              cr = gtk_snapshot_append_cairo_node (snapshot,
+                                                   &GRAPHENE_RECT_FROM_RECT(&clip_extents),
+                                                   "Active Link");
               gdk_cairo_region (cr, range_clip);
               cairo_clip (cr);
               cairo_region_destroy (range_clip);
@@ -4291,19 +4302,14 @@ gtk_label_get_render_node (GtkWidget   *widget,
               range_clip = gdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
               cairo_region_get_extents (range_clip, &rect);
 
-              gtk_render_focus (context, cr, rect.x, rect.y, rect.width, rect.height);
+              gtk_snapshot_render_focus (snapshot, context, rect.x, rect.y, rect.width, rect.height);
 
               cairo_region_destroy (range_clip);
             }
         }
     }
 
-  cairo_destroy (cr);
-
-  gsk_render_node_append_child (res, node);
-  gsk_render_node_unref (node);
-
-  return res;
+  return FALSE;
 }
 
 static gboolean
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 110cdb5..62defef 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -299,6 +299,24 @@ gtk_snapshot_render_frame (GtkSnapshot     *state,
 }
 
 void
+gtk_snapshot_render_focus (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_outline (gtk_style_context_lookup_style (context),
+                                  state,
+                                  width, height);
+  gtk_snapshot_translate_2d (state, -x, -y);
+}
+
+void
 gtk_snapshot_render_layout (GtkSnapshot     *state,
                             GtkStyleContext *context,
                             gdouble          x,
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index 948e22c..74be2c1 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -97,11 +97,26 @@ void            gtk_snapshot_render_frame               (GtkSnapshot
                                                          gdouble                 width,
                                                          gdouble                 height);
 GDK_AVAILABLE_IN_3_90
+void            gtk_snapshot_render_focus               (GtkSnapshot            *state,
+                                                         GtkStyleContext        *context,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height);
+GDK_AVAILABLE_IN_3_90
 void            gtk_snapshot_render_layout              (GtkSnapshot            *state,
                                                          GtkStyleContext        *context,
                                                          gdouble                 x,
                                                          gdouble                 y,
                                                          PangoLayout            *layout);
+GDK_AVAILABLE_IN_3_90 /* in gtkstylecontext.c */
+void            gtk_snapshot_render_insertion_cursor    (GtkSnapshot            *snapshot,
+                                                         GtkStyleContext        *context,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         PangoLayout            *layout,
+                                                         int                     index,
+                                                         PangoDirection          direction);
 
 G_END_DECLS
 
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 64641f8..df934e0 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -2060,7 +2060,6 @@ draw_insertion_cursor (GtkStyleContext *context,
                        gboolean         is_primary,
                        PangoDirection   direction,
                        gboolean         draw_arrow)
-
 {
   GdkRGBA primary_color;
   GdkRGBA secondary_color;
@@ -2122,6 +2121,65 @@ draw_insertion_cursor (GtkStyleContext *context,
   cairo_restore (cr);
 }
 
+static void
+get_insertion_cursor_bounds (gdouble          height,
+                             PangoDirection   direction,
+                             gboolean         draw_arrow,
+                             graphene_rect_t *bounds)
+{
+  gint stem_width;
+  gint offset;
+
+  stem_width = height * CURSOR_ASPECT_RATIO + 1;
+  if (direction == PANGO_DIRECTION_LTR)
+    offset = stem_width / 2;
+  else
+    offset = stem_width - stem_width / 2;
+
+  if (draw_arrow)
+    {
+      if (direction == PANGO_DIRECTION_LTR)
+        {
+          graphene_rect_init (bounds,
+                              - offset, 0,
+                              2 * stem_width + 1, height);
+        }
+      else
+        {
+          graphene_rect_init (bounds,
+                              - offset - stem_width - 2, 0,
+                              2 * stem_width + 2, height);
+        }
+    }
+  else
+    {
+      graphene_rect_init (bounds,
+                          - offset, 0,
+                          stem_width, height);
+    }
+}
+
+static void
+snapshot_insertion_cursor (GtkSnapshot     *snapshot,
+                           GtkStyleContext *context,
+                           gdouble          height,
+                           gboolean         is_primary,
+                           PangoDirection   direction,
+                           gboolean         draw_arrow)
+{
+  graphene_rect_t bounds;
+  cairo_t *cr;
+  
+  get_insertion_cursor_bounds (height, direction, draw_arrow, &bounds);
+  cr = gtk_snapshot_append_cairo_node (snapshot,
+                                       &bounds,
+                                       "%s Cursor", is_primary ? "Primary" : "Secondary");
+
+  draw_insertion_cursor (context, cr, 0, 0, height, is_primary, direction, draw_arrow);
+
+  cairo_destroy (cr);
+}
+
 /**
  * gtk_render_insertion_cursor:
  * @context: a #GtkStyleContext
@@ -2210,6 +2268,93 @@ gtk_render_insertion_cursor (GtkStyleContext *context,
 }
 
 /**
+ * gtk_snapshot_render_insertion_cursor:
+ * @snapshot: snapshot to render to
+ * @context: a #GtkStyleContext
+ * @x: X origin
+ * @y: Y origin
+ * @layout: the #PangoLayout of the text
+ * @index: the index in the #PangoLayout
+ * @direction: the #PangoDirection of the text
+ *
+ * Draws a text caret on @cr at the specified index of @layout.
+ *
+ * Since: 3.90
+ **/
+void
+gtk_snapshot_render_insertion_cursor (GtkSnapshot     *snapshot,
+                                      GtkStyleContext *context,
+                                      gdouble          x,
+                                      gdouble          y,
+                                      PangoLayout     *layout,
+                                      int              index,
+                                      PangoDirection   direction)
+{
+  GtkStyleContextPrivate *priv;
+  gboolean split_cursor;
+  PangoRectangle strong_pos, weak_pos;
+  PangoRectangle *cursor1, *cursor2;
+  PangoDirection keymap_direction;
+  PangoDirection direction2;
+
+  g_return_if_fail (snapshot != NULL);
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+  g_return_if_fail (index >= 0);
+
+  priv = context->priv;
+
+  g_object_get (gtk_settings_get_for_screen (priv->screen),
+                "gtk-split-cursor", &split_cursor,
+                NULL);
+
+  keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display 
(priv->screen)));
+
+  pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
+
+  direction2 = PANGO_DIRECTION_NEUTRAL;
+
+  if (split_cursor)
+    {
+      cursor1 = &strong_pos;
+
+      if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
+        {
+          direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+          cursor2 = &weak_pos;
+        }
+    }
+  else
+    {
+      if (keymap_direction == direction)
+        cursor1 = &strong_pos;
+      else
+        cursor1 = &weak_pos;
+    }
+
+  gtk_snapshot_translate_2d (snapshot, x + PANGO_PIXELS (cursor1->x), y + PANGO_PIXELS (cursor1->y));
+  snapshot_insertion_cursor (snapshot,
+                             context,
+                             PANGO_PIXELS (cursor1->height),
+                             TRUE,
+                             direction,
+                             direction2 != PANGO_DIRECTION_NEUTRAL);
+  gtk_snapshot_translate_2d (snapshot, - x - PANGO_PIXELS (cursor1->x), - y - PANGO_PIXELS (cursor1->y));
+
+  if (direction2 != PANGO_DIRECTION_NEUTRAL)
+    {
+      gtk_snapshot_translate_2d (snapshot, x + PANGO_PIXELS (cursor2->x), y + PANGO_PIXELS (cursor2->y));
+      snapshot_insertion_cursor (snapshot,
+                                 context,
+                                 PANGO_PIXELS (cursor2->height),
+                                 FALSE,
+                                 direction2,
+                                 TRUE);
+      gtk_snapshot_translate_2d (snapshot, - x - PANGO_PIXELS (cursor2->x), - y - PANGO_PIXELS (cursor2->y));
+    }
+}
+
+/**
  * gtk_style_context_get_change:
  * @context: the context to query
  *


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