[pango/line-breaker: 15/18] wip: editing apis




commit f98e41b4f34fd54dd390175e4eecc020c6ab68c6
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jan 15 08:37:55 2022 -0500

    wip: editing apis

 pango/pango-line-private.h |   9 +++
 pango/pango-line.c         | 116 ++++++++++++++++++----------
 pango/pango-line.h         |  30 --------
 pango/pango-lines.c        | 184 +++++++++++++++++++++++++++++++++++++++++++++
 pango/pango-lines.h        |  51 ++++++++++---
 5 files changed, 310 insertions(+), 80 deletions(-)
---
diff --git a/pango/pango-line-private.h b/pango/pango-line-private.h
index 7d01e751..990c748f 100644
--- a/pango/pango-line-private.h
+++ b/pango/pango-line-private.h
@@ -54,3 +54,12 @@ void        pango_line_ellipsize (PangoLine          *line,
                                   PangoEllipsizeMode  ellipsize,
                                   int                 goal_width);
 
+void        pango_line_index_to_x (PangoLine *line,
+                                   int        index,
+                                   int        trailing,
+                                   int       *x_pos);
+
+gboolean    pango_line_x_to_index (PangoLine *line,
+                                   int        x,
+                                   int       *index,
+                                   int       *trailing);
diff --git a/pango/pango-line.c b/pango/pango-line.c
index f2f5afd7..63903f87 100644
--- a/pango/pango-line.c
+++ b/pango/pango-line.c
@@ -5,6 +5,7 @@
 #include "pango-tabs.h"
 #include "pango-impl-utils.h"
 #include "pango-attributes-private.h"
+#include "pango-item-private.h"
 
 /* {{{ LineData */
 
@@ -68,6 +69,82 @@ pango_line_class_init (PangoLineClass *class)
   object_class->finalize = pango_line_finalize;
 }
 
+/* }}} */
+/* {{{ Private API */
+
+void
+pango_line_index_to_x (PangoLine *line,
+                       int        index,
+                       int        trailing,
+                       int       *x_pos)
+{
+  GSList *run_list = line->runs;
+  int width = 0;
+
+  while (run_list)
+    {
+      PangoLayoutRun *run = run_list->data;
+
+      if (run->item->offset <= index && run->item->offset + run->item->length > index)
+        {
+          int offset = g_utf8_pointer_to_offset (line->data->text, line->data->text + index);
+          int attr_offset;
+
+          if (trailing)
+            {
+              while (index < line->start_index + line->length &&
+                     offset + 1 < line->data->n_chars &&
+                     !line->data->log_attrs[offset + 1].is_cursor_position)
+                {
+                  offset++;
+                  index = g_utf8_next_char (line->data->text + index) - line->data->text;
+                }
+            }
+          else
+            {
+              while (index > line->start_index &&
+                     !line->data->log_attrs[offset].is_cursor_position)
+                {
+                  offset--;
+                  index = g_utf8_prev_char (line->data->text + index) - line->data->text;
+                }
+            }
+
+          /* Note: we simply assert here, since our items are all internally
+           * created. If that ever changes, we need to add a fallback here.
+           */
+          g_assert (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_HAS_CHAR_OFFSET);
+          attr_offset = ((PangoItemPrivate *)run->item)->char_offset;
+          pango_glyph_string_index_to_x_full (run->glyphs,
+                                              line->data->text + run->item->offset,
+                                              run->item->length,
+                                              &run->item->analysis,
+                                              line->data->log_attrs + attr_offset,
+                                              index - run->item->offset, trailing, x_pos);
+          if (x_pos)
+            *x_pos += width;
+
+          return;
+        }
+
+      width += pango_glyph_string_get_width (run->glyphs);
+
+      run_list = run_list->next;
+    }
+
+  if (x_pos)
+    *x_pos = width;
+}
+
+gboolean
+pango_line_x_to_index (PangoLine *line,
+                       int        x,
+                       int       *index,
+                       int       *trailing)
+{
+  return FALSE;
+}
+
 /* }}} */
 /* {{{ Public API */
 
@@ -311,45 +388,6 @@ cached:
   *ext = line->ink_rect;
 }
 
-void
-pango_line_index_to_pos (PangoLine      *line,
-                         int             index,
-                         PangoRectangle *pos)
-{
-  /* FIXME */
-}
-
-gboolean
-pango_line_pos_to_index (PangoLine *lines,
-                         int        x,
-                         int        y,
-                         int       *index,
-                         int       *trailing)
-{
-  /* FIXME */
-  return FALSE;
-}
-
-void
-pango_line_get_cursor_pos (PangoLine      *lines,
-                           int             index,
-                           PangoRectangle *strong_pos,
-                           PangoRectangle *weak_pos)
-{
-  /* FIXME */
-}
-
-void
-pango_line_move_cursor_visually (PangoLine *lines,
-                                 gboolean   strong,
-                                 int        index,
-                                 int       trailing,
-                                 int       *new_index,
-                                 int       *new_trailing)
-{
-  /* FIXME */
-}
-
 /* }}} */
 
 /* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-line.h b/pango/pango-line.h
index 1302de9f..12ead1aa 100644
--- a/pango/pango-line.h
+++ b/pango/pango-line.h
@@ -40,34 +40,4 @@ PANGO_AVAILABLE_IN_ALL
 void                    pango_line_get_ink_extents      (PangoLine             *line,
                                                          PangoRectangle        *ext);
 
-PANGO_AVAILABLE_IN_ALL
-void                    pango_line_index_to_pos         (PangoLine             *line,
-                                                         int                    index,
-                                                         PangoRectangle        *pos);
-
-PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_pos_to_index         (PangoLine             *lines,
-                                                         int                    x,
-                                                         int                    y,
-                                                         int                   *index,
-                                                         int                   *trailing);
-
-PANGO_AVAILABLE_IN_ALL
-void                    pango_line_get_cursor_pos       (PangoLine             *lines,
-                                                         int                    index,
-                                                         PangoRectangle        *strong_pos,
-                                                         PangoRectangle        *weak_pos);
-
-PANGO_AVAILABLE_IN_ALL
-void                    pango_line_move_cursor_visually (PangoLine             *lines,
-                                                         gboolean               strong,
-                                                         int                    index,
-                                                         int                    trailing,
-                                                         int                   *new_index,
-                                                         int                   *new_trailing);
-
-PANGO_AVAILABLE_IN_ALL
-GBytes *                pango_lines_serialize           (PangoLine            **lines,
-                                                         unsigned int           n_lines);
-
 G_END_DECLS
diff --git a/pango/pango-lines.c b/pango/pango-lines.c
index 6c9e5b8c..26dcc7d6 100644
--- a/pango/pango-lines.c
+++ b/pango/pango-lines.c
@@ -1,6 +1,7 @@
 #include "config.h"
 
 #include "pango-lines.h"
+#include "pango-line-private.h"
 
 /* {{{ PangoLine implementation */
 
@@ -145,6 +146,189 @@ pango_lines_get_line (PangoLines  *lines,
   return TRUE;
 }
 
+extern void pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
+                                                     PangoRectangle *run_ink,
+                                                     PangoRectangle *run_logical,
+                                                     PangoRectangle *line_logical,
+                                                     int            *height);
+
+void
+pango_lines_index_to_pos (PangoLines     *lines,
+                          int             index,
+                          PangoRectangle *pos)
+{
+  PangoRectangle line_logical_rect = { 0, };
+  PangoRectangle run_logical_rect = { 0, };
+  PangoLine *prev_line = NULL;
+  int x_pos;
+
+  g_return_if_fail (PANGO_IS_LINES (lines));
+  g_return_if_fail (index >= 0);
+  g_return_if_fail (pos != NULL);
+
+  for (int i = 0; i < lines->lines->len; i++)
+    {
+      Line *l = &g_array_index (lines->lines, Line, i);
+      PangoLine *line = l->line;
+
+      if (line->start_index > index)
+        {
+          /* index is in the paragraph delimiters, move to
+           * end of previous line
+           *
+           * This shouldn’t occur in the first loop iteration as the first
+           * line’s start_index should always be 0.
+           */
+          g_assert (prev_line != NULL);
+          index = prev_line->start_index + prev_line->length;
+          break;
+        }
+
+      pango_line_get_extents (line, &line_logical_rect);
+      prev_line = line;
+
+      if (line->start_index + line->length >= index)
+        {
+          for (GSList *l = line->runs; l; l = l->next)
+            {
+              PangoLayoutRun *run = l->data;
+
+              pango_layout_run_get_extents_and_height (run, NULL, &run_logical_rect, NULL, NULL);
+
+              if (run->item->offset <= index && index < run->item->offset + run->item->length)
+                break;
+            }
+
+          if (line->start_index + line->length > index)
+            break;
+        }
+
+      if (i + 1 == lines->lines->len)
+        {
+          index = line->start_index + line->length;
+          break;
+        }
+
+      pos->y = run_logical_rect.y;
+      pos->height = run_logical_rect.height;
+
+      pango_line_index_to_x (line, index, 0, &x_pos);
+      pos->x = line_logical_rect.x + x_pos;
+
+      if (index < line->start_index + line->length)
+        {
+          pango_line_index_to_x (line, index, 1, &x_pos);
+          pos->width = (line_logical_rect.x + x_pos) - pos->x;
+        }
+      else
+        pos->width = 0;
+    }
+}
+
+static void
+pango_lines_get_line_yrange (PangoLines *lines,
+                             int         index,
+                             int        *first_y,
+                             int        *last_y)
+{
+}
+
+gboolean
+pango_lines_pos_to_index (PangoLines *lines,
+                          int         x,
+                          int         y,
+                          int        *index,
+                          int        *trailing)
+{
+  PangoLine *prev_line = NULL;
+  PangoLine *found = NULL;
+  int found_line_x = 0;
+  int prev_last = 0;
+  int prev_line_x = 0;
+  gboolean retval = FALSE;
+  gboolean outside = FALSE;
+
+  g_return_val_if_fail (PANGO_IS_LINES (lines), FALSE);
+
+  for (int i = 0; i < lines->lines->len; i++)
+    {
+      Line *l = &g_array_index (lines->lines, Line, i);
+      PangoLine *line = l->line;
+      Line *next_l;
+      PangoRectangle line_logical;
+      int first_y, last_y;
+
+      pango_line_get_extents (line, &line_logical);
+      pango_lines_get_line_yrange (lines, i, &first_y, &last_y);
+
+      if (y < first_y)
+        {
+          if (prev_line && y < (prev_last + (first_y - prev_last) / 2))
+            {
+              found = prev_line;
+              found_line_x = prev_line_x;
+            }
+          else
+            {
+              if (prev_line == NULL)
+                outside = TRUE; /* off the top */
+
+              next_l = &g_array_index (lines->lines, Line, i + 1);
+              found = next_l->line;
+              found_line_x = x - line_logical.x;
+            }
+        }
+      else if (y >= first_y && y < last_y)
+        {
+          next_l = &g_array_index (lines->lines, Line, i + 1);
+          found = next_l->line;
+          found_line_x = x - line_logical.x;
+        }
+
+      next_l = &g_array_index (lines->lines, Line, i + 1);
+      prev_line = next_l->line;
+      prev_last = last_y;
+      prev_line_x = x - line_logical.x;
+
+      if (found != NULL)
+        break;
+    }
+
+  if (found == NULL)
+    {
+      /* Off the bottom of the layout */
+      outside = TRUE;
+
+      found = prev_line;
+      found_line_x = prev_line_x;
+    }
+
+  retval = pango_line_x_to_index (found, found_line_x, index, trailing);
+
+  if (outside)
+    retval = FALSE;
+
+  return retval;
+}
+
+void
+pango_lines_get_cursor_pos (PangoLines     *lines,
+                            int             index,
+                            PangoRectangle *strong_pos,
+                            PangoRectangle *weak_pos)
+{
+}
+
+void
+pango_lines_move_cursor (PangoLines *lines,
+                         gboolean    strong,
+                         int         index,
+                         int         trailing,
+                         int        *new_index,
+                         int        *new_trailing)
+{
+}
+
 /* }}} */
 
 /* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-lines.h b/pango/pango-lines.h
index 3641c9c4..bea42e77 100644
--- a/pango/pango-lines.h
+++ b/pango/pango-lines.h
@@ -12,22 +12,51 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (PangoLines, pango_lines, PANGO, LINES, GObject);
 
 PANGO_AVAILABLE_IN_ALL
-PangoLines *            pango_lines_new                 (void);
+PangoLines *            pango_lines_new             (void);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_lines_add_line            (PangoLines  *lines,
-                                                         PangoLine   *line,
-                                                         int          x,
-                                                         int          y);
+void                    pango_lines_add_line        (PangoLines     *lines,
+                                                     PangoLine      *line,
+                                                     int             x,
+                                                     int             y);
 
 PANGO_AVAILABLE_IN_ALL
-int                     pango_lines_get_n_lines         (PangoLines *lines);
+int                     pango_lines_get_n_lines     (PangoLines     *lines);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_lines_get_line            (PangoLines  *lines,
-                                                         int          num,
-                                                         PangoLine  **line,
-                                                         int         *x,
-                                                         int         *y);
+gboolean                pango_lines_get_line        (PangoLines     *lines,
+                                                     int             num,
+                                                     PangoLine     **line,
+                                                     int            *x,
+                                                     int            *y);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_lines_index_to_pos    (PangoLines     *line,
+                                                     int             index,
+                                                     PangoRectangle *pos);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_lines_pos_to_index    (PangoLines     *lines,
+                                                     int             x,
+                                                     int             y,
+                                                     int            *index,
+                                                     int            *trailing);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_lines_get_cursor_pos  (PangoLines     *lines,
+                                                     int             index,
+                                                     PangoRectangle *strong_pos,
+                                                     PangoRectangle *weak_pos);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_lines_move_cursor    (PangoLines      *lines,
+                                                    gboolean         strong,
+                                                    int              index,
+                                                    int              trailing,
+                                                    int             *new_index,
+                                                    int             *new_trailing);
+
+PANGO_AVAILABLE_IN_ALL
+GBytes *                pango_lines_serialize      (PangoLines      *lines);
 
 G_END_DECLS


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