[pango/line-height: 6/8] layout: Add line-spacing



commit 59e2b1aecfd38e0ca20cfe3e0356346f629e158f
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jul 5 00:00:16 2019 +0000

    layout: Add line-spacing
    
    If line-spacing is set to a non-zero value,
    we place lines so that
    
    baseline2 = baseline1 + line-spacing * height2
    
    where height2 is the line height of the
    second line. In this case, we ignore
    spacing.
    
    If line-spacing is set to zero, spacing
    is applied as before.

 pango/pango-layout-private.h |   1 +
 pango/pango-layout.c         | 113 +++++++++++++++++++++++++++++++++++--------
 pango/pango-layout.h         |   5 ++
 3 files changed, 99 insertions(+), 20 deletions(-)
---
diff --git a/pango/pango-layout-private.h b/pango/pango-layout-private.h
index 4b5327ee..38e2e196 100644
--- a/pango/pango-layout-private.h
+++ b/pango/pango-layout-private.h
@@ -55,6 +55,7 @@ struct _PangoLayout
   int height;                  /* ellipsize width, in device units if positive, number of lines if negative 
*/
   int indent;                  /* amount by which first line should be shorter */
   int spacing;                 /* spacing between lines */
+  float line_spacing;           /* factor to apply to line height */
 
   guint justify : 1;
   guint alignment : 2;
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 0934e6c7..4403fdc1 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -190,6 +190,7 @@ pango_layout_init (PangoLayout *layout)
   layout->height = -1;
   layout->indent = 0;
   layout->spacing = 0;
+  layout->line_spacing = 1.0;
 
   layout->alignment = PANGO_ALIGN_LEFT;
   layout->justify = FALSE;
@@ -556,8 +557,17 @@ pango_layout_get_indent (PangoLayout *layout)
  * @layout: a #PangoLayout.
  * @spacing: the amount of spacing
  *
- * Sets the amount of spacing in Pango unit between the lines of the
- * layout.
+ * Sets the amount of spacing in Pango unit between
+ * the lines of the layout. When placing lines with
+ * spacing, Pango arranges things so that
+ *
+ * line2.top = line1.bottom + spacing
+ *
+ * Note: Since 1.44, Pango defaults to using the
+ * line height (as determined by the font) for placing
+ * lines. The @spacing set with this function is only
+ * taken into account when the line-height factor is
+ * set to zero with pango_layout_set_line_spacing().
  **/
 void
 pango_layout_set_spacing (PangoLayout *layout,
@@ -587,6 +597,59 @@ pango_layout_get_spacing (PangoLayout *layout)
   return layout->spacing;
 }
 
+/**
+ * pango_layout_set_line_spacing:
+ * @layout: a #PangoLayout
+ * @factor: the new line spacing factor
+ *
+ * Sets a factor for line spacing.
+ * Typical values are: 0, 1, 1.5, 2.
+ * The default values is 1.
+ *
+ * If @factor is non-zero, lines are placed
+ * so that
+ *
+ * baseline2 = baseline1 + factor * height2
+ *
+ * where height2 is the line height of the
+ * second line (as determined by the font(s)).
+ * In this case, the spacing set with
+ * pango_layout_set_spacing() is ignored.
+ *
+ * If @factor is zero, spacing is applied as
+ * before.
+ *
+ * Since: 1.44
+ */
+void
+pango_layout_set_line_spacing (PangoLayout *layout,
+                              float        factor)
+{
+  g_return_if_fail (layout != NULL);
+
+  if (layout->line_spacing != factor)
+    {
+      layout->line_spacing = factor;
+      layout_changed (layout);
+    }
+}
+
+/**
+ * pango_layout_get_line_spacing:
+ * @layout: a #PangoLayout
+ *
+ * Gets the value that has been
+ * set with pango_layout_set_line_spacing().
+ *
+ * Since: 1.44
+ */
+float
+pango_layout_get_line_spacing (PangoLayout *layout)
+{
+  g_return_val_if_fail (layout != NULL, 1.0);
+  return layout->line_spacing;
+}
+
 /**
  * pango_layout_set_attributes:
  * @layout: a #PangoLayout
@@ -2492,7 +2555,6 @@ get_line_extents_layout_coords (PangoLayout     *layout,
                                int              layout_width,
                                int              y_offset,
                                int             *baseline,
-                               int             *height,
                                PangoRectangle  *line_ink_layout,
                                PangoRectangle  *line_logical_layout)
 {
@@ -2500,30 +2562,43 @@ get_line_extents_layout_coords (PangoLayout     *layout,
   /* Line extents in line coords (origin at line baseline) */
   PangoRectangle line_ink;
   PangoRectangle line_logical;
+  gboolean first_line;
+  int new_baseline;
+  int height;
+
+  if (layout->lines->data == line)
+    first_line = TRUE;
+  else
+    first_line = FALSE;
 
   pango_layout_line_get_extents_and_height (line, line_ink_layout ? &line_ink : NULL,
                                             &line_logical,
-                                            height);
+                                            &height);
 
   get_x_offset (layout, line, layout_width, line_logical.width, &x_offset);
 
+  if (first_line || !baseline || layout->line_spacing == 0.0)
+    new_baseline = y_offset - line_logical.y;
+  else
+    new_baseline = *baseline + layout->line_spacing * height;
+
   /* Convert the line's extents into layout coordinates */
   if (line_ink_layout)
     {
       *line_ink_layout = line_ink;
       line_ink_layout->x = line_ink.x + x_offset;
-      line_ink_layout->y = y_offset - line_logical.y + line_ink.y;
+      line_ink_layout->y = new_baseline + line_ink.y;
     }
 
   if (line_logical_layout)
     {
       *line_logical_layout = line_logical;
       line_logical_layout->x = line_logical.x + x_offset;
-      line_logical_layout->y = y_offset;
+      line_logical_layout->y = new_baseline + line_logical.y;
     }
 
   if (baseline)
-    *baseline = y_offset - line_logical.y;
+    *baseline = new_baseline;
 }
 
 /* if non-NULL line_extents returns a list of line extents
@@ -2540,6 +2615,7 @@ pango_layout_get_extents_internal (PangoLayout    *layout,
   int width;
   gboolean need_width = FALSE;
   int line_index = 0;
+  int baseline;
 
   g_return_if_fail (layout != NULL);
 
@@ -2606,6 +2682,7 @@ pango_layout_get_extents_internal (PangoLayout    *layout,
       *line_extents = g_malloc (sizeof (Extents) * layout->line_count);
     }
 
+  baseline = 0;
   line_list = layout->lines;
   while (line_list)
     {
@@ -2618,13 +2695,9 @@ pango_layout_get_extents_internal (PangoLayout    *layout,
 
       /* This block gets the line extents in layout coords */
       {
-       int baseline;
-        int height;
-
        get_line_extents_layout_coords (layout, line,
                                        width, y_offset,
                                        &baseline,
-                                        &height,
                                        ink_rect ? &line_ink_layout : NULL,
                                        &line_logical_layout);
 
@@ -2693,14 +2766,10 @@ pango_layout_get_extents_internal (PangoLayout    *layout,
                }
            }
 
-         logical_rect->height += line_logical_layout.height;
-
-         /* No space after the last line, of course. */
-         if (line_list->next != NULL)
-           logical_rect->height += layout->spacing;
+         logical_rect->height = line_logical_layout.y + line_logical_layout.height - logical_rect->y;
        }
 
-      y_offset += line_logical_layout.height + layout->spacing;
+      y_offset = line_logical_layout.y + line_logical_layout.height + layout->spacing;
       line_list = line_list->next;
       line_index ++;
     }
@@ -4739,7 +4808,7 @@ pango_layout_line_get_extents_and_height (PangoLayoutLine *line,
     }
 
   if (height)
-    height = 0;
+    *height = 0;
 
   tmp_list = line->runs;
   while (tmp_list)
@@ -4805,6 +4874,8 @@ pango_layout_line_get_extents_and_height (PangoLayoutLine *line,
        private->ink_rect = *ink_rect;
       if (&private->logical_rect != logical_rect)
        private->logical_rect = *logical_rect;
+      if (&private->height != height)
+        private->height = *height;
       private->cache_status = CACHED;
     }
 }
@@ -6437,7 +6508,6 @@ pango_layout_iter_get_line_extents (PangoLayoutIter *iter,
       get_line_extents_layout_coords (iter->layout, iter->line,
                                      iter->layout_width,
                                      ext->logical_rect.y,
-                                     NULL,
                                       NULL,
                                      ink_rect,
                                      NULL);
@@ -6461,7 +6531,10 @@ pango_layout_iter_get_line_extents (PangoLayoutIter *iter,
  * The Y positions are in layout coordinates (origin at top left of the
  * entire layout).
  *
- **/
+ * Note: Since 1.44, Pango uses line heights for placing lines,
+ * and there may be gaps between the ranges returned by this
+ * function.
+ */
 void
 pango_layout_iter_get_line_yrange (PangoLayoutIter *iter,
                                   int             *y0,
diff --git a/pango/pango-layout.h b/pango/pango-layout.h
index 2019a7b5..96155715 100644
--- a/pango/pango-layout.h
+++ b/pango/pango-layout.h
@@ -206,6 +206,11 @@ void           pango_layout_set_spacing          (PangoLayout                *la
                                                  int                         spacing);
 PANGO_AVAILABLE_IN_ALL
 int            pango_layout_get_spacing          (PangoLayout                *layout);
+PANGO_AVAILABLE_IN_1_44
+void           pango_layout_set_line_spacing     (PangoLayout                *layout,
+                                                  float                       spread);
+PANGO_AVAILABLE_IN_1_44
+float          pango_layout_get_line_spacing     (PangoLayout                *layout);
 PANGO_AVAILABLE_IN_ALL
 void           pango_layout_set_justify          (PangoLayout                *layout,
                                                  gboolean                    justify);


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