[pango/caret-slope: 1/2] Add pango_layout_get_caret_pos




commit 492d2945406ab04381add77c8378d4a2d3ccd58d
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Aug 24 16:07:02 2021 -0400

    Add pango_layout_get_caret_pos
    
    This is like pango_layout_get_cursor_pos, but returns
    a rectangle that has caret font metrics applied to it.

 pango/pango-layout.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++---
 pango/pango-layout.h |   7 ++++
 2 files changed, 102 insertions(+), 5 deletions(-)
---
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index b6e0c217..5987dbf1 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -83,6 +83,8 @@
 #include <string.h>
 #include <math.h>
 
+#include <hb-ot.h>
+
 #include "pango-layout-private.h"
 #include "pango-attributes-private.h"
 
@@ -2458,23 +2460,37 @@ pango_layout_index_to_pos (PangoLayout    *layout,
   _pango_layout_iter_destroy (&iter);
 }
 
-static int
-pango_layout_line_get_char_level (PangoLayoutLine *layout_line,
-                                  int              index)
+static PangoLayoutRun *
+pango_layout_line_get_run (PangoLayoutLine *line,
+                           int              index)
 {
   GSList *run_list;
 
-  run_list = layout_line->runs;
+  run_list = line->runs;
   while (run_list)
     {
       PangoLayoutRun *run = run_list->data;
 
       if (run->item->offset <= index && run->item->offset + run->item->length > index)
-        return run->item->analysis.level;
+        return run;
 
       run_list = run_list->next;
     }
 
+  return  NULL;
+}
+
+static int
+pango_layout_line_get_char_level (PangoLayoutLine *line,
+                                  int              index)
+{
+  PangoLayoutRun *run;
+
+  run = pango_layout_line_get_run (line, index);
+
+  if (run)
+    return run->item->analysis.level;
+
   return 0;
 }
 
@@ -2630,6 +2646,80 @@ pango_layout_get_cursor_pos (PangoLayout    *layout,
     }
 }
 
+/**
+ * pango_layout_get_caret_pos:
+ * @layout: a `PangoLayout`
+ * @index_: the byte index of the cursor
+ * @strong_pos: (out) (optional): location to store the strong cursor position
+ * @weak_pos: (out) (optional): location to store the weak cursor position
+ *
+ * Given an index within a layout, determines the positions that of the
+ * strong and weak cursors if the insertion point is at that index.
+ *
+ * This is a variant of [method@Pango.Layout.get_cursor_pos] that applies
+ * font metric information about caret slope and offset to the positions
+ * it returns.
+ *
+ * TOOD: Image here
+ *
+ * Since: 1.50
+ */
+void
+pango_layout_get_caret_pos (PangoLayout    *layout,
+                            int             index,
+                            PangoRectangle *strong_pos,
+                            PangoRectangle *weak_pos)
+{
+  PangoLayoutLine *line;
+  PangoLayoutRun *run;
+  hb_font_t *hb_font;
+  hb_position_t caret_offset, caret_run, caret_rise, descender;
+
+  pango_layout_get_cursor_pos (layout, index, strong_pos, weak_pos);
+
+  /* FIXME: not very efficient to re-iterate here */
+  line = pango_layout_index_to_line_and_extents (layout, index, NULL, NULL);
+  run = pango_layout_line_get_run (line, index);
+  if (!run)
+    run = pango_layout_line_get_run (line, index - 1);
+
+  if (!run)
+    return;
+
+  hb_font = pango_font_get_hb_font (run->item->analysis.font);
+
+  if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, &caret_rise) &&
+      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, &caret_run) &&
+      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, &caret_offset) &&
+      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &descender))
+    {
+      double slope;
+
+      if (strong_pos)
+        strong_pos->x += caret_offset;
+
+      if (weak_pos)
+        weak_pos->x += caret_offset;
+
+      if (caret_run == 0)
+        return;
+
+      slope = caret_rise / (double) caret_run;
+
+      if (strong_pos)
+        {
+          strong_pos->x += descender / slope;
+          strong_pos->width = strong_pos->height / slope;
+        }
+
+      if (weak_pos)
+        {
+          weak_pos->x += descender / slope;
+          weak_pos->width = weak_pos->height / slope;
+        }
+    }
+}
+
 static inline int
 direction_simple (PangoDirection d)
 {
diff --git a/pango/pango-layout.h b/pango/pango-layout.h
index 9436dbcb..3b30a251 100644
--- a/pango/pango-layout.h
+++ b/pango/pango-layout.h
@@ -298,6 +298,13 @@ void     pango_layout_get_cursor_pos       (PangoLayout    *layout,
                                            int             index_,
                                            PangoRectangle *strong_pos,
                                            PangoRectangle *weak_pos);
+
+PANGO_AVAILABLE_IN_1_50
+void     pango_layout_get_caret_pos        (PangoLayout    *layout,
+                                            int             index_,
+                                            PangoRectangle *strong_pos,
+                                            PangoRectangle *weak_pos);
+
 PANGO_AVAILABLE_IN_ALL
 void     pango_layout_move_cursor_visually (PangoLayout    *layout,
                                            gboolean        strong,


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