[gtk/deprecate-render: 39/54] Add gtk_css_style_snapshot_caret




commit 820e063ee02802c9bde7cd25d10531ce2577af68
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Oct 8 16:32:13 2022 -0400

    Add gtk_css_style_snapshot_caret

 gtk/gtkrenderlayout.c        | 248 +++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkrenderlayoutprivate.h |  19 +++-
 2 files changed, 262 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtkrenderlayout.c b/gtk/gtkrenderlayout.c
index 1d38ff097b..454ca2fc78 100644
--- a/gtk/gtkrenderlayout.c
+++ b/gtk/gtkrenderlayout.c
@@ -24,6 +24,7 @@
 #include "gtkpangoprivate.h"
 #include "gtksnapshot.h"
 #include "gtktypebuiltins.h"
+#include "gtksettings.h"
 
 
 void
@@ -60,3 +61,250 @@ gtk_css_style_snapshot_layout (GtkCssBoxes *boxes,
   gtk_snapshot_pop (snapshot);
 }
 
+static void
+draw_insertion_cursor (cairo_t         *cr,
+                       double           x,
+                       double           y,
+                       double           width,
+                       double           height,
+                       double           aspect_ratio,
+                       const GdkRGBA   *color,
+                       PangoDirection   direction,
+                       gboolean         draw_arrow)
+{
+  int stem_width;
+  double angle;
+  double dx, dy;
+  double xx1, yy1, xx2, yy2;
+
+  cairo_save (cr);
+  cairo_new_path (cr);
+
+  gdk_cairo_set_source_rgba (cr, color);
+
+  stem_width = height * aspect_ratio + 1;
+
+  yy1 = y;
+  yy2 = y + height;
+
+  if (width < 0)
+    {
+      xx1 = x;
+      xx2 = x - width;
+    }
+  else
+    {
+      xx1 = x + width;
+      xx2 = x;
+    }
+
+  angle = atan2 (height, width);
+
+  dx = (stem_width/2.0) * cos (M_PI/2 - angle);
+  dy = (stem_width/2.0) * sin (M_PI/2 - angle);
+
+  if (draw_arrow)
+    {
+      if (direction == PANGO_DIRECTION_RTL)
+        {
+          double x0, y0, x1, y1, x2, y2;
+
+          x0 = xx2 - dx + 2 * dy;
+          y0 = yy2 - dy - 2 * dx;
+
+          x1 = x0 + 4 * dy;
+          y1 = y0 - 4 * dx;
+          x2 = x0 + 2 * dy - 3 * dx;
+          y2 = y0 - 2 * dx - 3 * dy;
+
+          cairo_move_to (cr, xx1 + dx, yy1 + dy);
+          cairo_line_to (cr, xx2 + dx, yy2 + dy);
+          cairo_line_to (cr, x2, y2);
+          cairo_line_to (cr, x1, y1);
+          cairo_line_to (cr, xx1 - dx, yy1 - dy);
+        }
+      else if (direction == PANGO_DIRECTION_LTR)
+        {
+          double x0, y0, x1, y1, x2, y2;
+
+          x0 = xx2 + dx + 2 * dy;
+          y0 = yy2 + dy - 2 * dx;
+
+          x1 = x0 + 4 * dy;
+          y1 = y0 - 4 * dx;
+          x2 = x0 + 2 * dy + 3 * dx;
+          y2 = y0 - 2 * dx + 3 * dy;
+
+          cairo_move_to (cr, xx1 - dx, yy1 - dy);
+          cairo_line_to (cr, xx2 - dx, yy2 - dy);
+          cairo_line_to (cr, x2, y2);
+          cairo_line_to (cr, x1, y1);
+          cairo_line_to (cr, xx1 + dx, yy1 + dy);
+        }
+      else
+        g_assert_not_reached();
+    }
+  else
+    {
+      cairo_move_to (cr, xx1 + dx, yy1 + dy);
+      cairo_line_to (cr, xx2 + dx, yy2 + dy);
+      cairo_line_to (cr, xx2 - dx, yy2 - dy);
+      cairo_line_to (cr, xx1 - dx, yy1 - dy);
+    }
+
+  cairo_fill (cr);
+
+  cairo_restore (cr);
+}
+
+static void
+get_insertion_cursor_bounds (double           width,
+                             double           height,
+                             double           aspect_ratio,
+                             PangoDirection   direction,
+                             gboolean         draw_arrow,
+                             graphene_rect_t *bounds)
+{
+  int stem_width;
+
+  if (width < 0)
+    width = - width;
+
+  stem_width = height * aspect_ratio + 1;
+
+  graphene_rect_init (bounds,
+                      - 2 * stem_width, - stem_width,
+                      width + 4 * stem_width, height + 2 * stem_width);
+}
+
+static void
+snapshot_insertion_cursor (GtkSnapshot     *snapshot,
+                           GtkCssStyle     *style,
+                           double           width,
+                           double           height,
+                           double           aspect_ratio,
+                           gboolean         is_primary,
+                           PangoDirection   direction,
+                           gboolean         draw_arrow)
+{
+  GdkRGBA color;
+
+  if (is_primary)
+    color = *gtk_css_color_value_get_rgba (style->font->caret_color ? style->font->caret_color : 
style->core->color);
+  else
+    color = *gtk_css_color_value_get_rgba (style->font->secondary_caret_color ? 
style->font->secondary_caret_color : style->core->color);
+
+  if (width != 0 || draw_arrow)
+    {
+      cairo_t *cr;
+      graphene_rect_t bounds;
+
+      get_insertion_cursor_bounds (width, height, aspect_ratio, direction, draw_arrow, &bounds);
+      cr = gtk_snapshot_append_cairo (snapshot, &bounds);
+
+      draw_insertion_cursor (cr, 0, 0, width, height, aspect_ratio, &color, direction, draw_arrow);
+
+      cairo_destroy (cr);
+    }
+  else
+    {
+      int stem_width;
+      int offset;
+
+      stem_width = height * aspect_ratio + 1;
+
+      /* put (stem_width % 2) on the proper side of the cursor */
+      if (direction == PANGO_DIRECTION_LTR)
+        offset = stem_width / 2;
+      else
+        offset = stem_width - stem_width / 2;
+
+      gtk_snapshot_append_color (snapshot,
+                                 &color,
+                                 &GRAPHENE_RECT_INIT (- offset, 0, stem_width, height));
+    }
+}
+
+void
+gtk_css_style_snapshot_caret (GtkCssBoxes    *boxes,
+                              GdkDisplay     *display,
+                              GtkSnapshot    *snapshot,
+                              int             x,
+                              int             y,
+                              PangoLayout    *layout,
+                              int             index,
+                              PangoDirection  direction)
+{
+  gboolean split_cursor;
+  double aspect_ratio;
+  PangoRectangle strong_pos, weak_pos;
+  PangoRectangle *cursor1, *cursor2;
+  GdkSeat *seat;
+  PangoDirection keyboard_direction;
+  PangoDirection direction2;
+
+  g_object_get (gtk_settings_get_for_display (display),
+                "gtk-split-cursor", &split_cursor,
+                "gtk-cursor-aspect-ratio", &aspect_ratio,
+                NULL);
+
+  keyboard_direction = PANGO_DIRECTION_LTR;
+  seat = gdk_display_get_default_seat (display);
+  if (seat)
+    {
+      GdkDevice *keyboard = gdk_seat_get_keyboard (seat);
+
+      if (keyboard)
+        keyboard_direction = gdk_device_get_direction (keyboard);
+    }
+
+  pango_layout_get_caret_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 (keyboard_direction == direction)
+        cursor1 = &strong_pos;
+      else
+        cursor1 = &weak_pos;
+    }
+
+  gtk_snapshot_save (snapshot);
+  gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + PANGO_PIXELS (MIN (cursor1->x, cursor1->x + 
cursor1->width)), y + PANGO_PIXELS (cursor1->y)));
+  snapshot_insertion_cursor (snapshot,
+                             boxes->style,
+                             PANGO_PIXELS (cursor1->width),
+                             PANGO_PIXELS (cursor1->height),
+                             aspect_ratio,
+                             TRUE,
+                             direction,
+                             direction2 != PANGO_DIRECTION_NEUTRAL);
+  gtk_snapshot_restore (snapshot);
+
+  if (direction2 != PANGO_DIRECTION_NEUTRAL)
+    {
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + PANGO_PIXELS (MIN (cursor2->x, cursor2->x 
+ cursor2->width)), y + PANGO_PIXELS (cursor2->y)));
+      snapshot_insertion_cursor (snapshot,
+                                 boxes->style,
+                                 PANGO_PIXELS (cursor2->width),
+                                 PANGO_PIXELS (cursor2->height),
+                                 aspect_ratio,
+                                 FALSE,
+                                 direction2,
+                                 TRUE);
+      gtk_snapshot_restore (snapshot);
+    }
+}
+
diff --git a/gtk/gtkrenderlayoutprivate.h b/gtk/gtkrenderlayoutprivate.h
index ec4d13b816..e14b5c0b78 100644
--- a/gtk/gtkrenderlayoutprivate.h
+++ b/gtk/gtkrenderlayoutprivate.h
@@ -27,11 +27,20 @@
 
 G_BEGIN_DECLS
 
-void            gtk_css_style_snapshot_layout (GtkCssBoxes *boxes,
-                                               GtkSnapshot *snapshot,
-                                               int          x,
-                                               int          y,
-                                               PangoLayout *layout);
+void            gtk_css_style_snapshot_layout (GtkCssBoxes    *boxes,
+                                               GtkSnapshot    *snapshot,
+                                               int             x,
+                                               int             y,
+                                               PangoLayout    *layout);
+
+void            gtk_css_style_snapshot_caret  (GtkCssBoxes    *boxes,
+                                               GdkDisplay     *display,
+                                               GtkSnapshot    *snapshot,
+                                               int             x,
+                                               int             y,
+                                               PangoLayout    *layout,
+                                               int             index,
+                                               PangoDirection  direction);
 
 
 G_END_DECLS


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