[pango/cursor-move-fixes: 1/3] Fix corner cases around line ends




commit 903c9bf4b0ee86038c5fa4b430a2ceff71d621b9
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Aug 9 14:57:57 2021 -0400

    Fix corner cases around line ends
    
    pango_layout_index_to_line_and_extents needs to
    return a run rect even if the line has no non-empty
    runs. Failing to do so was causing cursors at the
    end of lines to have a height of 0 or 1, which is
    not what we want.
    
    Add a testcase.

 pango/pango-layout.c | 28 ++++++++++++++++------------
 tests/test-bidi.c    |  4 ++++
 2 files changed, 20 insertions(+), 12 deletions(-)
---
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index fa13ad59..e73a001d 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;
@@ -2329,11 +2334,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 +2463,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..995decb2 100644
--- a/tests/test-bidi.c
+++ b/tests/test-bidi.c
@@ -346,6 +346,7 @@ 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 },
   };
   PangoLayout *layout;
   PangoRectangle pos, old_pos;
@@ -395,9 +396,12 @@ test_move_cursor_para (void)
           pango_layout_line_get_extents (line, NULL, &ext);
 
           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);
         }
     }
 


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