textview: Track differences between ink and logical rects
authorBenjamin Otte <otte@redhat.com>
Tue, 15 Mar 2016 23:35:45 +0000 (00:35 +0100)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 21 Mar 2016 17:26:57 +0000 (13:26 -0400)
This way, we can ensure that we queue redraws on the full ink rect. This
is particularly visible for squiggly underlines in spell checking.

https://bugzilla.gnome.org/show_bug.cgi?id=763741

gtk/gtktextbtree.c
gtk/gtktextbtree.h
gtk/gtktextlayout.c

index 9e8d8386a8450a019b27f1718557edf0c290ff26..2c995aaeff77a87b6816ed6eac622363c2a26d65 100644 (file)
@@ -2650,14 +2650,18 @@ redisplay_region (GtkTextBTree      *tree,
       else
         end_y = _gtk_text_btree_find_line_top (tree, end_line, view->view_id);
 
+      ld = _gtk_text_line_get_data (start_line, view->view_id);
+      if (ld)
+        start_y -= ld->top_ink;
+
       ld = _gtk_text_line_get_data (end_line, view->view_id);
       if (ld)
-        end_y += ld->height;
+        end_y += ld->height + ld->bottom_ink;
 
       if (cursors_only)
        gtk_text_layout_cursors_changed (view->layout, start_y,
                                         end_y - start_y,
-                                         end_y - start_y);
+                                        end_y - start_y);
       else
        gtk_text_layout_changed (view->layout, start_y,
                                 end_y - start_y,
@@ -3616,6 +3620,8 @@ _gtk_text_line_data_new (GtkTextLayout *layout,
   line_data->next = NULL;
   line_data->width = 0;
   line_data->height = 0;
+  line_data->top_ink = 0;
+  line_data->bottom_ink = 0;
   line_data->valid = FALSE;
 
   return line_data;
index 08662188483559283981abf810580d6f29919a2d..bea48419be57bcf0adb188c42a1fe11c28e56039 100644 (file)
@@ -220,6 +220,8 @@ struct _GtkTextLineData {
   gpointer view_id;
   GtkTextLineData *next;
   gint height;
+  gint top_ink : 16;
+  gint bottom_ink : 16;
   signed int width : 24;
   guint valid : 8;             /* Actually a boolean */
 };
index 6adcdc5ae74b26b7ce5e3c3737512af515fa766f..6829d454c9d347fb65fee57c3ee6bfff9a91248c 100644 (file)
@@ -1041,23 +1041,31 @@ gtk_text_layout_validate_yrange (GtkTextLayout *layout,
       if (!line_data || !line_data->valid)
         {
           gint old_height, new_height;
+          gint top_ink, bottom_ink;
          
          old_height = line_data ? line_data->height : 0;
+          top_ink = line_data ? line_data->top_ink : 0;
+          bottom_ink = line_data ? line_data->bottom_ink : 0;
 
           _gtk_text_btree_validate_line (_gtk_text_buffer_get_btree (layout->buffer),
                                          line, layout);
           line_data = _gtk_text_line_get_data (line, layout);
 
          new_height = line_data ? line_data->height : 0;
+          if (line_data)
+            {
+              top_ink = MAX (top_ink, line_data->top_ink);
+              bottom_ink = MAX (bottom_ink, line_data->bottom_ink);
+            }
 
           delta_height += new_height - old_height;
           
           first_line = line;
-          first_line_y = -seen - new_height;
+          first_line_y = -seen - new_height - top_ink;
           if (!last_line)
             {
               last_line = line;
-              last_line_y = -seen;
+              last_line_y = -seen + bottom_ink;
             }
         }
 
@@ -1074,23 +1082,31 @@ gtk_text_layout_validate_yrange (GtkTextLayout *layout,
       if (!line_data || !line_data->valid)
         {
           gint old_height, new_height;
+          gint top_ink, bottom_ink;
          
          old_height = line_data ? line_data->height : 0;
+          top_ink = line_data ? line_data->top_ink : 0;
+          bottom_ink = line_data ? line_data->bottom_ink : 0;
 
           _gtk_text_btree_validate_line (_gtk_text_buffer_get_btree (layout->buffer),
                                          line, layout);
           line_data = _gtk_text_line_get_data (line, layout);
          new_height = line_data ? line_data->height : 0;
+          if (line_data)
+            {
+              top_ink = MAX (top_ink, line_data->top_ink);
+              bottom_ink = MAX (bottom_ink, line_data->bottom_ink);
+            }
 
           delta_height += new_height - old_height;
           
           if (!first_line)
             {
               first_line = line;
-              first_line_y = seen;
+              first_line_y = seen - top_ink;
             }
           last_line = line;
-          last_line_y = seen + new_height;
+          last_line_y = seen + new_height + bottom_ink;
         }
 
       seen += line_data ? line_data->height : 0;
@@ -1152,6 +1168,7 @@ gtk_text_layout_real_wrap (GtkTextLayout   *layout,
                            GtkTextLineData *line_data)
 {
   GtkTextLineDisplay *display;
+  PangoRectangle ink_rect, logical_rect;
 
   g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), NULL);
   g_return_val_if_fail (line != NULL, NULL);
@@ -1166,6 +1183,9 @@ gtk_text_layout_real_wrap (GtkTextLayout   *layout,
   line_data->width = display->width;
   line_data->height = display->height;
   line_data->valid = TRUE;
+  pango_layout_get_pixel_extents (display->layout, &ink_rect, &logical_rect);
+  line_data->top_ink = MAX (0, logical_rect.x - ink_rect.x);
+  line_data->bottom_ink = MAX (0, logical_rect.x + logical_rect.width - ink_rect.x - ink_rect.width);
   gtk_text_layout_free_line_display (layout, display);
 
   return line_data;