summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-08-09 21:41:12 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-08-09 21:41:12 +0000
commit391f2efef525c0dd8e28043c82f350af8160d888 (patch)
tree13cee80c1f658721f46ffa248005f610a667d8f0
parentd892355cfb12d62f9f6e04e4b63c7af2923c9a1f (diff)
parent70fe2aae47b42ad76c6fdb78021009db7bcc164c (diff)
downloadpango-391f2efef525c0dd8e28043c82f350af8160d888.tar.gz
Merge branch 'cursor-move-fixes' into 'main'
Fix corner cases around line ends See merge request GNOME/pango!401
-rw-r--r--pango/pango-layout.c50
-rw-r--r--tests/test-bidi.c56
2 files changed, 86 insertions, 20 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index fa13ad59..a5577acc 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -1820,25 +1820,30 @@ pango_layout_index_to_line_and_extents (PangoLayout *layout,
PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (&iter);
if (tmp_line->start_index > index)
- break; /* index was in paragraph delimiters */
+ break; /* index was in paragraph delimiters */
line = tmp_line;
pango_layout_iter_get_line_extents (&iter, NULL, line_rect);
- if (line->start_index + line->length > index)
+ if (!iter.line_list_link->next ||
+ ((PangoLayoutLine *)iter.line_list_link->next->data)->start_index > index)
{
if (run_rect)
{
+ *run_rect = *line_rect;
+
while (TRUE)
{
PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
+ if (!run)
+ break;
+
+ pango_layout_iter_get_run_extents (&iter, NULL, run_rect);
+
if (run->item->offset <= index && index < run->item->offset + run->item->length)
- {
- pango_layout_iter_get_run_extents (&iter, NULL, run_rect);
- break;
- }
+ break;
if (!pango_layout_iter_next_run (&iter))
break;
@@ -1933,6 +1938,8 @@ pango_layout_line_get_cursors (PangoLayoutLine *line,
GArray *cursors)
{
PangoLayout *layout = line->layout;
+ int line_no;
+ PangoLayoutLine *line2;
const char *start, *end;
int start_offset;
int j;
@@ -1946,7 +1953,12 @@ pango_layout_line_get_cursors (PangoLayoutLine *line,
end = start + line->length;
start_offset = g_utf8_pointer_to_offset (layout->text, start);
- for (j = start_offset, p = start; p <= end; j++, p = g_utf8_next_char (p))
+ pango_layout_index_to_line_x (layout, line->start_index + line->length, 0, &line_no, NULL);
+ line2 = pango_layout_get_line (layout, line_no);
+ if (line2 == line)
+ end++;
+
+ for (j = start_offset, p = start; p < end; j++, p = g_utf8_next_char (p))
{
if (layout->log_attrs[j].is_cursor_position)
{
@@ -2042,8 +2054,6 @@ pango_layout_move_cursor_visually (PangoLayout *layout,
while (old_trailing--)
old_index = g_utf8_next_char (layout->text + old_index) - layout->text;
- n_vis = pango_utf8_strlen (layout->text + line->start_index, line->length);
-
/* Clamp old_index to fit on the line */
if (old_index > (line->start_index + line->length))
old_index = line->start_index + line->length;
@@ -2069,6 +2079,15 @@ pango_layout_move_cursor_visually (PangoLayout *layout,
}
}
+ if (vis_pos == -1 &&
+ old_index == line->start_index + line->length)
+ {
+ if (line->resolved_dir == PANGO_DIRECTION_LTR)
+ vis_pos = cursors->len;
+ else
+ vis_pos = 0;
+ }
+
/* Handling movement between lines */
if (line->resolved_dir == PANGO_DIRECTION_LTR)
{
@@ -2120,7 +2139,7 @@ pango_layout_move_cursor_visually (PangoLayout *layout,
g_array_set_size (cursors, 0);
pango_layout_line_get_cursors (line, strong, cursors);
- n_vis = pango_utf8_strlen (layout->text + line->start_index, line->length);
+ n_vis = cursors->len;
if (off_start && direction < 0)
{
@@ -2329,11 +2348,10 @@ pango_layout_index_to_pos (PangoLayout *layout,
{
PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
+ pango_layout_iter_get_run_extents (&iter, NULL, &logical_rect);
+
if (run->item->offset <= index && index < run->item->offset + run->item->length)
- {
- pango_layout_iter_get_run_extents (&iter, NULL, &logical_rect);
- break;
- }
+ break;
if (!pango_layout_iter_next_run (&iter))
break;
@@ -2459,8 +2477,8 @@ pango_layout_get_cursor_pos (PangoLayout *layout,
{
PangoDirection dir1, dir2;
int level1, level2;
- PangoRectangle line_rect;
- PangoRectangle run_rect;
+ PangoRectangle line_rect = { 666, };
+ PangoRectangle run_rect = { 666, };
PangoLayoutLine *layout_line = NULL; /* Quiet GCC */
int x1_trailing;
int x2;
diff --git a/tests/test-bidi.c b/tests/test-bidi.c
index 7a137518..eb99abbf 100644
--- a/tests/test-bidi.c
+++ b/tests/test-bidi.c
@@ -346,6 +346,8 @@ test_move_cursor_para (void)
{ "你好 Hello שלום Γειά σας", 60 },
{ "你好 Hello שלום Γειά σας", 80 },
{ "line 1
line 2
line 3\nline 4\r\nline 5", -1 }, // various separators
+ { "some text, some more text,\n\n even more text", 60 },
+ { "long word", 40 },
};
PangoLayout *layout;
PangoRectangle pos, old_pos;
@@ -355,6 +357,7 @@ test_move_cursor_para (void)
int line_no;
PangoLayoutLine *line;
PangoRectangle ext;
+ PangoLayoutIter *iter;
layout = pango_layout_new (context);
@@ -374,6 +377,14 @@ test_move_cursor_para (void)
{
old_pos = pos;
+ pango_layout_index_to_line_x (layout, index, FALSE, &line_no, NULL);
+ line = pango_layout_get_line (layout, line_no);
+ iter = pango_layout_get_iter (layout);
+ while (pango_layout_iter_get_line (iter) != line)
+ pango_layout_iter_next_line (iter);
+ pango_layout_iter_get_line_extents (iter, NULL, &ext);
+ pango_layout_iter_free (iter);
+
pango_layout_move_cursor_visually (layout, TRUE,
index, 0,
1,
@@ -390,14 +401,51 @@ test_move_cursor_para (void)
if (index >= strlen (tests[i].text) - 1)
break;
+ pango_layout_get_cursor_pos (layout, index, &pos, NULL);
+
+ // assert that we are either moving to the right
+ // or jumping to the next line
+ g_assert_true (pos.y >= ext.y + ext.height || pos.x > old_pos.x);
+ // no invisible cursors, please
+ g_assert_true (pos.height > 1024);
+ }
+
+ /* and now backwards */
+ index = strlen (text);
+ pango_layout_get_cursor_pos (layout, index, &pos, NULL);
+
+ while (index > -1)
+ {
+ old_pos = pos;
+
pango_layout_index_to_line_x (layout, index, FALSE, &line_no, NULL);
line = pango_layout_get_line (layout, line_no);
- pango_layout_line_get_extents (line, NULL, &ext);
+ iter = pango_layout_get_iter (layout);
+ while (pango_layout_iter_get_line (iter) != line)
+ pango_layout_iter_next_line (iter);
+ pango_layout_iter_get_line_extents (iter, NULL, &ext);
+ pango_layout_iter_free (iter);
+
+ pango_layout_move_cursor_visually (layout, TRUE,
+ index, 0,
+ -1,
+ &index, &trailing);
+ while (trailing--)
+ index = g_utf8_next_char (text + index) - text;
+
+ g_assert (index == -1 || index == G_MAXINT ||
+ (0 <= index && index <= strlen (tests[i].text)));
+
+ if (index == -1 || index == G_MAXINT)
+ break;
pango_layout_get_cursor_pos (layout, index, &pos, NULL);
- // assert that we are either moving to the right
- // or jumping to the next line
- g_assert_true (pos.y > ext.y + ext.height || pos.x > old_pos.x);
+
+ // assert that we are either moving to the left
+ // or jumping to the previous line
+ g_assert_true (pos.y < ext.y || pos.x < old_pos.x);
+ // no invisible cursors, please
+ g_assert_true (pos.height > 1024);
}
}