diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-08-09 21:41:12 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2021-08-09 21:41:12 +0000 |
commit | 391f2efef525c0dd8e28043c82f350af8160d888 (patch) | |
tree | 13cee80c1f658721f46ffa248005f610a667d8f0 | |
parent | d892355cfb12d62f9f6e04e4b63c7af2923c9a1f (diff) | |
parent | 70fe2aae47b42ad76c6fdb78021009db7bcc164c (diff) | |
download | pango-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.c | 50 | ||||
-rw-r--r-- | tests/test-bidi.c | 56 |
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); } } |