[pango/line-height-attribute] Fix up logical rectangle reporting




commit 9249860623991a1a6a8e90cc78ce412270a20576
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Aug 7 21:02:36 2021 -0400

    Fix up logical rectangle reporting
    
    Fix up the various apis that are reporting logical
    rects to follow these rules:
    
    Logical rectangles of lines are affected by the
    line-height attribute, logical rectangles of smaller
    units (runs, clusters, chars, cursors, etc) are not.
    
    This fixes the text cursors and block cursors in
    GTK to be 'normal' height, even when applying
    line-height for double-spacing.

 pango/pango-layout.c | 141 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 95 insertions(+), 46 deletions(-)
---
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index d23ce5a6..8b3a2f2a 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -174,7 +174,8 @@ static int *pango_layout_line_get_vis2log_map (PangoLayoutLine  *line,
 static void pango_layout_line_leaked (PangoLayoutLine *line);
 
 /* doesn't leak line */
-static PangoLayoutLine* _pango_layout_iter_get_line (PangoLayoutIter *iter);
+static PangoLayoutLine * _pango_layout_iter_get_line (PangoLayoutIter *iter);
+static PangoLayoutRun *  _pango_layout_iter_get_run  (PangoLayoutIter *iter);
 
 static void pango_layout_get_item_properties (PangoItem      *item,
                                               ItemProperties *properties);
@@ -1793,7 +1794,8 @@ pango_layout_index_to_line (PangoLayout      *layout,
 static PangoLayoutLine *
 pango_layout_index_to_line_and_extents (PangoLayout     *layout,
                                         int              index,
-                                        PangoRectangle  *line_rect)
+                                        PangoRectangle  *line_rect,
+                                        PangoRectangle  *run_rect)
 {
   PangoLayoutIter iter;
   PangoLayoutLine *line = NULL;
@@ -1813,7 +1815,25 @@ pango_layout_index_to_line_and_extents (PangoLayout     *layout,
         pango_layout_iter_get_line_extents (&iter, NULL, line_rect);
 
         if (line->start_index + line->length > index)
-          break;
+          {
+            if (run_rect)
+              {
+                while (TRUE)
+                  {
+                    PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
+
+                    pango_layout_iter_get_run_extents (&iter, NULL, run_rect);
+
+                    if (run->item->offset + run->item->length > index)
+                       break;
+
+                    if (!pango_layout_iter_next_run (&iter))
+                      break;
+                  }
+              }
+
+            break;
+          }
 
         if (!pango_layout_iter_next_line (&iter))
           break; /* Use end of last line */
@@ -2223,10 +2243,23 @@ pango_layout_index_to_pos (PangoLayout    *layout,
 
           layout_line = tmp_line;
 
-          pango_layout_iter_get_line_extents (&iter, NULL, &logical_rect);
-
           if (layout_line->start_index + layout_line->length > index)
-            break;
+            {
+              while (TRUE)
+                {
+                  PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
+
+                  pango_layout_iter_get_run_extents (&iter, NULL, &logical_rect);
+
+                  if (run->item->offset + run->item->length > index)
+                    break;
+
+                  if (!pango_layout_iter_next_run (&iter))
+                    break;
+                }
+
+              break;
+            }
 
           if (!pango_layout_iter_next_line (&iter))
             {
@@ -2419,7 +2452,7 @@ pango_layout_get_direction (PangoLayout *layout,
 {
   PangoLayoutLine *line;
 
-  line = pango_layout_index_to_line_and_extents (layout, index, NULL);
+  line = pango_layout_index_to_line (layout, index, NULL, NULL, NULL);
 
   if (line)
     return pango_layout_line_get_char_direction (line, index);
@@ -2451,23 +2484,23 @@ pango_layout_get_cursor_pos (PangoLayout    *layout,
 {
   PangoDirection dir1;
   PangoRectangle line_rect;
-  PangoLayoutLine *layout_line = NULL; /* Quiet GCC */
+  PangoRectangle run_rect;
+  PangoLayoutLine *line = NULL; /* Quiet GCC */
   int x1_trailing;
   int x2;
 
   g_return_if_fail (layout != NULL);
   g_return_if_fail (index >= 0 && index <= layout->length);
 
-  layout_line = pango_layout_index_to_line_and_extents (layout, index,
-                                                        &line_rect);
+  line = pango_layout_index_to_line_and_extents (layout, index, &line_rect, &run_rect);
 
-  g_assert (index >= layout_line->start_index);
+  g_assert (index >= line->start_index);
 
   /* Examine the trailing edge of the character before the cursor */
-  if (index == layout_line->start_index)
+  if (index == line->start_index)
     {
-      dir1 = layout_line->resolved_dir;
-      if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
+      dir1 = line->resolved_dir;
+      if (line->resolved_dir == PANGO_DIRECTION_LTR)
         x1_trailing = 0;
       else
         x1_trailing = line_rect.width;
@@ -2475,49 +2508,49 @@ pango_layout_get_cursor_pos (PangoLayout    *layout,
   else
     {
       gint prev_index = g_utf8_prev_char (layout->text + index) - layout->text;
-      dir1 = pango_layout_line_get_char_direction (layout_line, prev_index);
-      pango_layout_line_index_to_x (layout_line, prev_index, TRUE, &x1_trailing);
+      dir1 = pango_layout_line_get_char_direction (line, prev_index);
+      pango_layout_line_index_to_x (line, prev_index, TRUE, &x1_trailing);
     }
 
   /* Examine the leading edge of the character after the cursor */
-  if (index >= layout_line->start_index + layout_line->length)
+  if (index >= line->start_index + line->length)
     {
-      if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
+      if (line->resolved_dir == PANGO_DIRECTION_LTR)
         x2 = line_rect.width;
       else
         x2 = 0;
     }
   else
     {
-      pango_layout_line_index_to_x (layout_line, index, FALSE, &x2);
+      pango_layout_line_index_to_x (line, index, FALSE, &x2);
     }
 
   if (strong_pos)
     {
       strong_pos->x = line_rect.x;
 
-      if (dir1 == layout_line->resolved_dir)
+      if (dir1 == line->resolved_dir)
         strong_pos->x += x1_trailing;
       else
         strong_pos->x += x2;
 
-      strong_pos->y = line_rect.y;
+      strong_pos->y = run_rect.y;
       strong_pos->width = 0;
-      strong_pos->height = line_rect.height;
+      strong_pos->height = run_rect.height;
     }
 
   if (weak_pos)
     {
       weak_pos->x = line_rect.x;
 
-      if (dir1 == layout_line->resolved_dir)
+      if (dir1 == line->resolved_dir)
         weak_pos->x += x2;
       else
         weak_pos->x += x1_trailing;
 
-      weak_pos->y = line_rect.y;
+      weak_pos->y = run_rect.y;
       weak_pos->width = 0;
-      weak_pos->height = line_rect.height;
+      weak_pos->height = run_rect.height;
     }
 }
 
@@ -5053,10 +5086,11 @@ pango_layout_line_get_empty_extents_and_height (PangoLayoutLine *line,
 }
 
 static void
-pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
-                                         PangoRectangle *run_ink,
-                                         PangoRectangle *run_logical,
-                                         int            *height)
+pango_layout_run_get_extents (PangoLayoutRun *run,
+                              PangoRectangle *run_ink,
+                              PangoRectangle *run_logical,
+                              PangoRectangle *line_logical,
+                              int            *height)
 {
   PangoRectangle logical;
   ItemProperties properties;
@@ -5064,7 +5098,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
   gboolean has_underline;
   gboolean has_overline;
 
-  if (G_UNLIKELY (!run_ink && !run_logical && !height))
+  if (G_UNLIKELY (!run_ink && !run_logical && !line_logical && !height))
     return;
 
   pango_layout_get_item_properties (run->item, &properties);
@@ -5079,6 +5113,9 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
   if (!run_logical && (has_underline || has_overline || properties.strikethrough))
     run_logical = &logical;
 
+  if (!run_logical && line_logical)
+    run_logical = &logical;
+
   if (properties.shape_set)
     _pango_shape_get_extents (run->item->num_chars,
                               properties.shape_ink_rect,
@@ -5153,16 +5190,6 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
       *height = pango_font_metrics_get_height (metrics);
     }
 
-  if (properties.absolute_line_height != 0 || properties.line_height != 0.0)
-    {
-      int line_height, leading;
-
-      line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * 
run_logical->height));
-      leading = line_height - run_logical->height;
-      run_logical->y -= leading / 2;
-      run_logical->height += leading;
-    }
-
   if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
     {
       gboolean is_hinted = (run_logical->y & run_logical->height & (PANGO_SCALE - 1)) == 0;
@@ -5183,6 +5210,21 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
         run_logical->y -= properties.rise;
     }
 
+  if (line_logical)
+    {
+      *line_logical = *run_logical;
+
+      if (properties.absolute_line_height != 0 || properties.line_height != 0.0)
+        {
+          int line_height, leading;
+
+          line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * 
line_logical->height));
+          leading = line_height - line_logical->height;
+          line_logical->y -= leading / 2;
+          line_logical->height += leading;
+        }
+    }
+
   if (metrics)
     pango_font_metrics_unref (metrics);
 }
@@ -5260,10 +5302,11 @@ pango_layout_line_get_extents_and_height (PangoLayoutLine *line,
       PangoRectangle run_logical;
       int run_height;
 
-      pango_layout_run_get_extents_and_height (run,
-                                               ink_rect ? &run_ink : NULL,
-                                               &run_logical,
-                                               height ? &run_height : NULL);
+      pango_layout_run_get_extents (run,
+                                    ink_rect ? &run_ink : NULL,
+                                    NULL,
+                                    &run_logical,
+                                    height ? &run_height : NULL);
 
       if (ink_rect)
         {
@@ -6501,12 +6544,18 @@ pango_layout_iter_get_run_readonly (PangoLayoutIter *iter)
 }
 
 /* an inline-able version for local use */
-static PangoLayoutLine*
+static PangoLayoutLine *
 _pango_layout_iter_get_line (PangoLayoutIter *iter)
 {
   return iter->line;
 }
 
+static PangoLayoutRun *
+_pango_layout_iter_get_run (PangoLayoutIter *iter)
+{
+  return iter->run;
+}
+
 /**
  * pango_layout_iter_get_line:
  * @iter: a `PangoLayoutIter`
@@ -6968,7 +7017,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter,
 
   if (iter->run)
     {
-      pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL);
+      pango_layout_run_get_extents (iter->run, ink_rect, logical_rect, NULL, NULL);
 
       if (ink_rect)
         {


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