[pango/line-breaker: 15/18] wip: editing apis
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/line-breaker: 15/18] wip: editing apis
- Date: Sat, 15 Jan 2022 15:37:30 +0000 (UTC)
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]