[pango/pango2: 70/168] Replace PangoLayout




commit 9f03c1c24955e5743aa24e2eaf503b5496dc83ef
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Jun 5 22:53:42 2022 -0400

    Replace PangoLayout
    
    This commit replaces the old PangoLayout implementation
    with PangoSimpleLayout, and does all the necessary
    cleanups.

 examples/cairoshape.c                              |   18 +-
 examples/cairosimple.c                             |   14 +-
 examples/cairotwisted.c                            |   10 +-
 pango/ellipsize.c                                  |   53 -
 pango/meson.build                                  |    6 +-
 pango/pango-attributes.c                           |   15 +-
 pango/pango-layout-private.h                       |  160 -
 pango/pango-layout.c                               | 8599 +++-----------------
 pango/pango-layout.h                               |  493 +-
 pango/pango-line-breaker.c                         |   42 +-
 pango/pango-line-iter.c                            |   40 +-
 pango/pango-line-iter.h                            |   64 +-
 pango/pango-line-private.h                         |   26 +-
 pango/pango-line.c                                 |   46 +-
 pango/pango-line.h                                 |   99 +-
 pango/pango-lines.c                                |   76 +-
 pango/pango-lines.h                                |    2 -
 pango/pango-renderer.c                             |  177 +-
 pango/pango-renderer.h                             |   31 +-
 ...go-layout-run-private.h => pango-run-private.h} |   11 +-
 pango/{pango-layout-run.c => pango-run.c}          |   42 +-
 pango/{pango-layout-run.h => pango-run.h}          |   14 +-
 pango/pango-simple-layout.c                        | 1555 ----
 pango/pango-simple-layout.h                        |  171 -
 pango/pango-types.h                                |   31 +-
 pango/pango.h                                      |    3 +-
 pango/pangocairo-context.c                         |   28 +-
 pango/pangocairo-font.c                            |   31 +-
 pango/pangocairo-render.c                          |   68 +-
 pango/pangocairo.h                                 |   19 +-
 pango/pangofc-font.c                               |   31 +-
 pango/pangowin32.c                                 |    2 +-
 pango/serializer.c                                 |  562 +-
 tests/test-bidi.c                                  |   28 +-
 tests/test-break.c                                 |   10 +-
 tests/test-ellipsize.c                             |   52 +-
 tests/test-layout.c                                |   17 +-
 tests/test-pangocairo-threads.c                    |   20 +-
 tests/testiter.c                                   |   61 +-
 tests/testmisc.c                                   |  168 +-
 tests/testrandom.c                                 |   38 +-
 utils/pango-segmentation.c                         |   10 +-
 utils/viewer-pangocairo.c                          |  138 +-
 utils/viewer-render.c                              |   39 +-
 44 files changed, 1964 insertions(+), 11156 deletions(-)
---
diff --git a/examples/cairoshape.c b/examples/cairoshape.c
index 4c1de86b..49ac3510 100644
--- a/examples/cairoshape.c
+++ b/examples/cairoshape.c
@@ -122,22 +122,22 @@ mini_svg_shape_renderer (cairo_t        *cr,
 }
 
 
-static PangoSimpleLayout *
+static PangoLayout *
 get_layout (cairo_t *cr)
 {
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoAttrList *attrs;
   PangoRectangle ink_rect     = {1 * PANGO_SCALE, -11 * PANGO_SCALE,  8 * PANGO_SCALE, 10 * PANGO_SCALE};
   PangoRectangle logical_rect = {0 * PANGO_SCALE, -12 * PANGO_SCALE, 10 * PANGO_SCALE, 12 * PANGO_SCALE};
   const char *p;
 
-  /* Create a PangoSimpleLayout, set the font and text */
-  layout = pango_cairo_create_simple_layout (cr);
+  /* Create a PangoLayout, set the font and text */
+  layout = pango_cairo_create_layout (cr);
 
-  pango_cairo_context_set_shape_renderer (pango_simple_layout_get_context (layout),
+  pango_cairo_context_set_shape_renderer (pango_layout_get_context (layout),
                                           mini_svg_shape_renderer, NULL, NULL);
 
-  pango_simple_layout_set_text (layout, text, -1);
+  pango_layout_set_text (layout, text, -1);
 
   attrs = pango_attr_list_new ();
 
@@ -157,7 +157,7 @@ get_layout (cairo_t *cr)
       pango_attr_list_insert (attrs, attr);
     }
 
-  pango_simple_layout_set_attributes (layout, attrs);
+  pango_layout_set_attributes (layout, attrs);
   pango_attr_list_unref (attrs);
 
   return layout;
@@ -166,8 +166,8 @@ get_layout (cairo_t *cr)
 static void
 draw_text (cairo_t *cr, int *width, int *height)
 {
-  PangoSimpleLayout *layout = get_layout (cr);
-  PangoLines *lines = pango_simple_layout_get_lines (layout);
+  PangoLayout *layout = get_layout (cr);
+  PangoLines *lines = pango_layout_get_lines (layout);
 
   /* Adds a fixed 10-pixel margin on the sides. */
 
diff --git a/examples/cairosimple.c b/examples/cairosimple.c
index 3d7a5428..6235a02a 100644
--- a/examples/cairosimple.c
+++ b/examples/cairosimple.c
@@ -17,7 +17,7 @@ draw_text (cairo_t *cr)
  */
 #define TWEAKABLE_SCALE ((double) 0.1)
 
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoLines *lines;
   PangoFontDescription *desc;
   int i;
@@ -26,17 +26,17 @@ draw_text (cairo_t *cr)
    */
   cairo_translate (cr, RADIUS / TWEAKABLE_SCALE, RADIUS / TWEAKABLE_SCALE);
 
-  /* Create a PangoSimpleLayout, set the font and text */
-  layout = pango_cairo_create_simple_layout (cr);
+  /* Create a PangoLayout, set the font and text */
+  layout = pango_cairo_create_layout (cr);
 
-  pango_simple_layout_set_text (layout, "Test\nسَلام", -1);
+  pango_layout_set_text (layout, "Test\nسَلام", -1);
 
   desc = pango_font_description_from_string (FONT_WITH_MANUAL_SIZE);
   pango_font_description_set_absolute_size (desc, FONT_SIZE * DEVICE_DPI * PANGO_SCALE / (72.0 * 
TWEAKABLE_SCALE));
   //pango_font_description_set_size(desc, 27 * PANGO_SCALE / TWEAKABLE_SCALE);
 
   printf("PANGO_SCALE = %d\n", PANGO_SCALE);
-  pango_simple_layout_set_font_description (layout, desc);
+  pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);
 
   /* Draw the layout N_WORDS times in a circle */
@@ -55,9 +55,9 @@ draw_text (cairo_t *cr)
       cairo_rotate (cr, angle * G_PI / 180.);
 
       /* Inform Pango to re-layout the text with the new transformation */
-      pango_cairo_update_simple_layout (cr, layout);
+      pango_cairo_update_layout (cr, layout);
 
-      lines = pango_simple_layout_get_lines (layout);
+      lines = pango_layout_get_lines (layout);
 
       pango_lines_get_extents (lines, NULL, &ext);
       cairo_move_to (cr,( - (((double)ext.width) / PANGO_SCALE) / 2.0) , (- RADIUS)  / TWEAKABLE_SCALE);
diff --git a/examples/cairotwisted.c b/examples/cairotwisted.c
index 8323453a..88f781b4 100644
--- a/examples/cairotwisted.c
+++ b/examples/cairotwisted.c
@@ -471,7 +471,7 @@ draw_text (cairo_t *cr,
            const char *font,
            const char *text)
 {
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoLine *line;
   PangoFontDescription *desc;
   cairo_font_options_t *font_options;
@@ -484,15 +484,15 @@ draw_text (cairo_t *cr,
   cairo_set_font_options (cr, font_options);
   cairo_font_options_destroy (font_options);
 
-  layout = pango_cairo_create_simple_layout (cr);
+  layout = pango_cairo_create_layout (cr);
 
   desc = pango_font_description_from_string (font);
-  pango_simple_layout_set_font_description (layout, desc);
+  pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);
 
-  pango_simple_layout_set_text (layout, text, -1);
+  pango_layout_set_text (layout, text, -1);
 
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
 
   cairo_move_to (cr, x, y);
   pango_cairo_line_path (cr, line);
diff --git a/pango/ellipsize.c b/pango/ellipsize.c
index 7f121a80..ebe8a684 100644
--- a/pango/ellipsize.c
+++ b/pango/ellipsize.c
@@ -23,7 +23,6 @@
 #include <string.h>
 
 #include "pango-glyph-item.h"
-#include "pango-layout-private.h"
 #include "pango-font-private.h"
 #include "pango-attributes-private.h"
 #include "pango-impl-utils.h"
@@ -744,58 +743,6 @@ current_width (EllipsizeState *state)
   return state->total_width - (state->gap_end_x - state->gap_start_x) + state->ellipsis_width;
 }
 
-/**
- * _pango_layout_line_ellipsize:
- * @line: a `PangoLayoutLine`
- * @attrs: Attributes being used for itemization/shaping
- * @shape_flags: Flags to use when shaping
- *
- * Given a `PangoLayoutLine` with the runs still in logical order, ellipsize
- * it according the layout's policy to fit within the set width of the layout.
- *
- * Return value: whether the line had to be ellipsized
- **/
-gboolean
-_pango_layout_line_ellipsize (PangoLayoutLine *line,
-                              PangoAttrList   *attrs,
-                              PangoShapeFlags  shape_flags,
-                              int              goal_width)
-{
-  PangoLayout *layout = line->layout;
-  PangoContext *context = layout->context;
-  const char *text = layout->text;
-  PangoLogAttr *log_attrs = layout->log_attrs;
-  PangoEllipsizeMode ellipsize = layout->ellipsize;
-  EllipsizeState state;
-  gboolean is_ellipsized = FALSE;
-
-  g_return_val_if_fail (ellipsize != PANGO_ELLIPSIZE_NONE && goal_width >= 0, is_ellipsized);
-
-  init_state (&state, context, text, line->start_index, log_attrs, ellipsize, line->runs, attrs, 
shape_flags);
-
-  if (state.total_width <= goal_width)
-    goto out;
-
-  find_initial_span (&state);
-
-  while (current_width (&state) > goal_width)
-    {
-      if (!remove_one_span (&state))
-        break;
-    }
-
-  fixup_ellipsis_run (&state, MAX (goal_width - current_width (&state), 0));
-
-  g_slist_free (line->runs);
-  line->runs = get_run_list (&state);
-  is_ellipsized = TRUE;
-
- out:
-  free_state (&state);
-
-  return is_ellipsized;
-}
-
 void
 pango_line_ellipsize (PangoLine          *line,
                       PangoContext       *context,
diff --git a/pango/meson.build b/pango/meson.build
index 1478bfda..2e52201e 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -33,12 +33,11 @@ pango_sources = [
   'serializer.c',
   'json/gtkjsonparser.c',
   'json/gtkjsonprinter.c',
-  'pango-layout-run.c',
   'pango-line.c',
+  'pango-run.c',
   'pango-line-breaker.c',
   'pango-lines.c',
   'pango-line-iter.c',
-  'pango-simple-layout.c',
 ]
 
 pango_headers = [
@@ -62,8 +61,8 @@ pango_headers = [
   'pango-gravity.h',
   'pango-item.h',
   'pango-language.h',
-  'pango-layout-run.h',
   'pango-line.h',
+  'pango-run.h',
   'pango-line-breaker.h',
   'pango-line-iter.h',
   'pango-lines.h',
@@ -72,7 +71,6 @@ pango_headers = [
   'pango-markup.h',
   'pango-renderer.h',
   'pango-script.h',
-  'pango-simple-layout.h',
   'pango-tabs.h',
   'pango-types.h',
   'pango-utils.h',
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 25f39b11..18232367 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1510,12 +1510,8 @@ pango_attr_overline_color_new (guint16 red,
  * Modify the height of logical line extents by a factor.
  *
  * This affects the values returned by
- * [method@Pango.LayoutLine.get_extents],
- * [method@Pango.LayoutLine.get_pixel_extents] and
- * [method@Pango.LayoutIter.get_line_extents].
- *
- *
- * Since: 1.50
+ * [method Pango Line.get_extents] and
+ * [method@Pango.LineIter.get_line_extents].
  */
 PangoAttribute *
 pango_attr_line_height_new (double factor)
@@ -1537,11 +1533,8 @@ pango_attr_line_height_new (double factor)
  * Override the height of logical line extents to be @height.
  *
  * This affects the values returned by
- * [method@Pango.LayoutLine.get_extents],
- * [method@Pango.LayoutLine.get_pixel_extents] and
- * [method@Pango.LayoutIter.get_line_extents].
- *
- * Since: 1.50
+ * [method Pango Line.get_extents],
+ * [method@Pango.LineIter.get_line_extents].
  */
 PangoAttribute *
 pango_attr_line_height_new_absolute (int height)
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 0062696d..817c1306 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -1,23 +1,11 @@
-/* Pango
- * pango-layout.c: High-level layout driver
- *
- * Copyright (C) 2000, 2001, 2006 Red Hat Software
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
+#include "config.h"
+
+#include "pango-layout.h"
+#include "pango-line-breaker.h"
+#include "pango-line-private.h"
+#include "pango-enum-types.h"
+#include "pango-markup.h"
+#include "pango-context.h"
 
 /**
  * PangoLayout:
@@ -25,19 +13,21 @@
  * A `PangoLayout` structure represents an entire paragraph of text.
  *
  * While complete access to the layout capabilities of Pango is provided
- * using the detailed interfaces for itemization and shaping, using
- * that functionality directly involves writing a fairly large amount
- * of code. `PangoLayout` provides a high-level driver for formatting
- * entire paragraphs of text at once. This includes paragraph-level
- * functionality such as line breaking, justification, alignment and
- * ellipsization.
+ * using the detailed interfaces for itemization, segmentation and shaping,
+ * using that functionality directly involves writing a fairly large amount
+ * of code. `PangoLayout` provides a high-level driver for formatting entire
+ * paragraphs of text at once. This includes paragraph-level functionality
+ * such as line breaking, justification, alignment and ellipsization.
  *
- * A `PangoLayout` is initialized with a `PangoContext`, UTF-8 string
+ * A `PangoLayout` is initialized with a `PangoContext`, a UTF-8 string
  * and set of attributes for that string. Once that is done, the set of
- * formatted lines can be extracted from the object, the layout can be
- * rendered, and conversion between logical character positions within
- * the layout's text, and the physical position of the resulting glyphs
- * can be made.
+ * formatted lines can be extracted in the form of a [class@Pango.Lines]
+ * object, the layout can be rendered, and conversion between logical
+ * character positions within the layout's text, and the physical position
+ * of the resulting glyphs can be made.
+ *
+ * The most convenient way to access the visual extents and components
+ * of a formatted layout is via a [struct@Pango.LineIter] iterator.
  *
  * There are a number of parameters to adjust the formatting of a
  * `PangoLayout`. The following image shows adjustable parameters
@@ -48,130 +38,77 @@
  *   <img alt="Pango Layout Parameters" src="layout-light.png">
  * </picture>
  *
- * The following images demonstrate the effect of alignment and
- * justification on the layout of text:
+ * The following images demonstrate the effect of alignment and justification
+ * on the layout of text:
  *
- * | | |
- * | --- | --- |
- * | ![align=left](align-left.png) | ![align=left, justify](align-left-justify.png) |
- * | ![align=center](align-center.png) | ![align=center, justify](align-center-justify.png) |
- * | ![align=right](align-right.png) | ![align=right, justify](align-right-justify.png) |
+ * | | | |
+ * | --- | --- | --- |
+ * | ![align=left](align-left.png) | ![align=center](align-center.png) | ![align=right](align-right.png) |
+ * | ![align=justify](align-left-justify.png) | | |
  *
+ * It is possible, as well, to ignore the 2-D setup, and simply treat the
+ * resulting `PangoLines` object as a list of lines.
  *
- * It is possible, as well, to ignore the 2-D setup,
- * and simply treat the results of a `PangoLayout` as a list of lines.
+ * If you have more complex line breaking needs, such as shaping text
+ * to flow around images, or multi-column layout, the [class@Pango.LineBreaker]
+ * makes the underlying line-breaking functionality available outside of
+ * `PangoLayout`.
  */
 
-/**
- * PangoLayoutIter:
- *
- * A `PangoLayoutIter` can be used to iterate over the visual
- * extents of a `PangoLayout`.
- *
- * To obtain a `PangoLayoutIter`, use [method@Pango.Layout.get_iter].
- *
- * The `PangoLayoutIter` structure is opaque, and has no user-visible fields.
- */
-
-#include "config.h"
-#include "pango-glyph.h"                /* For pango_shape() */
-#include "pango-break.h"
-#include "pango-item-private.h"
-#include "pango-impl-utils.h"
-#include "pango-glyph-item.h"
-#include <string.h>
-#include <math.h>
-#include <locale.h>
-
-#include <hb-ot.h>
 
-#include "pango-layout-private.h"
-#include "pango-attributes-private.h"
-#include "pango-font-private.h"
-#include "pango-utils-internal.h"
+/* {{{ PangoLayout implementation */
 
-
-typedef struct _ParaBreakState ParaBreakState;
-typedef struct _LastTabState LastTabState;
-
-typedef struct _PangoLayoutLinePrivate PangoLayoutLinePrivate;
-
-struct _PangoLayoutLinePrivate
+struct _PangoLayout
 {
-  PangoLayoutLine line;
-  guint ref_count;
+  GObject parent_instance;
 
-  /* Extents cache status:
-   *
-   * LEAKED means that the user has access to this line structure or a
-   * run included in this line, and so can change the glyphs/glyph-widths.
-   * If this is true, extents caching will be disabled.
-   */
-  enum {
-    NOT_CACHED,
-    CACHED,
-    LEAKED
-  } cache_status;
-  PangoRectangle ink_rect;
-  PangoRectangle logical_rect;
+  PangoContext *context;
+  char *text;
+  int length;
+  PangoAttrList *attrs;
+  PangoFontDescription *font_desc;
+  float line_spacing;
+  int width;
   int height;
+  PangoTabArray *tabs;
+  gboolean single_paragraph;
+  PangoWrapMode wrap;
+  int indent;
+  guint serial;
+  guint context_serial;
+  PangoAlignment alignment;
+  PangoEllipsizeMode ellipsize;
+  gboolean auto_dir;
+
+  PangoLines *lines;
 };
 
 struct _PangoLayoutClass
 {
   GObjectClass parent_class;
-
-
 };
 
-#define LINE_IS_VALID(line) ((line) && (line)->layout != NULL)
-
-#ifdef G_DISABLE_CHECKS
-#define ITER_IS_INVALID(iter) FALSE
-#else
-#define ITER_IS_INVALID(iter) G_UNLIKELY (check_invalid ((iter), G_STRLOC))
-static gboolean
-check_invalid (PangoLayoutIter *iter,
-               const char      *loc)
-{
-  if (iter->line->layout == NULL)
-    {
-      g_warning ("%s: PangoLayout changed since PangoLayoutIter was created, iterator invalid", loc);
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-}
-#endif
-
-static void check_context_changed  (PangoLayout *layout);
-static void layout_changed  (PangoLayout *layout);
-
-static void pango_layout_clear_lines (PangoLayout *layout);
-static void pango_layout_check_lines (PangoLayout *layout);
-
-static PangoAttrList *pango_layout_get_effective_attributes (PangoLayout *layout);
-
-static PangoLayoutLine * pango_layout_line_new         (PangoLayout     *layout);
-static void              pango_layout_line_postprocess (PangoLayoutLine *line,
-                                                        ParaBreakState  *state,
-                                                        gboolean         wrapped);
-
-static void pango_layout_line_leaked (PangoLayoutLine *line);
-
-/* doesn't leak line */
-static PangoLayoutLine * _pango_layout_iter_get_line (PangoLayoutIter *iter);
-static PangoLayoutRun *  _pango_layout_iter_get_run  (PangoLayoutIter *iter);
-
-static void pango_layout_get_empty_extents_and_height_at_index (PangoLayout    *layout,
-                                                                int             index,
-                                                                PangoRectangle *logical_rect,
-                                                                gboolean        apply_line_height,
-                                                                int            *height);
+enum
+{
+  PROP_CONTEXT = 1,
+  PROP_TEXT,
+  PROP_ATTRIBUTES,
+  PROP_FONT_DESCRIPTION,
+  PROP_LINE_SPACING,
+  PROP_WIDTH,
+  PROP_HEIGHT,
+  PROP_TABS,
+  PROP_SINGLE_PARAGRAPH,
+  PROP_WRAP,
+  PROP_INDENT,
+  PROP_ALIGNMENT,
+  PROP_ELLIPSIZE,
+  PROP_AUTO_DIR,
+  PROP_LINES,
+  NUM_PROPERTIES
+};
 
-static void pango_layout_finalize    (GObject          *object);
+static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
 
 G_DEFINE_TYPE (PangoLayout, pango_layout, G_TYPE_OBJECT)
 
@@ -179,7710 +116,1514 @@ static void
 pango_layout_init (PangoLayout *layout)
 {
   layout->serial = 1;
-  layout->attrs = NULL;
-  layout->font_desc = NULL;
-  layout->text = NULL;
-  layout->length = 0;
   layout->width = -1;
   layout->height = -1;
   layout->indent = 0;
-  layout->spacing = 0;
-  layout->line_spacing = 0.0;
-
-  layout->alignment = PANGO_ALIGN_LEFT;
-  layout->justify = FALSE;
-  layout->justify_last_line = FALSE;
-  layout->auto_dir = TRUE;
-  layout->single_paragraph = FALSE;
-
-  layout->log_attrs = NULL;
-  layout->lines = NULL;
-  layout->line_count = 0;
-
-  layout->tab_width = -1;
-  layout->decimal = 0;
-  layout->unknown_glyphs_count = -1;
-
   layout->wrap = PANGO_WRAP_WORD;
-  layout->is_wrapped = FALSE;
+  layout->alignment = PANGO_ALIGN_LEFT;
   layout->ellipsize = PANGO_ELLIPSIZE_NONE;
-  layout->is_ellipsized = FALSE;
+  layout->line_spacing = 0.0;
+  layout->auto_dir = TRUE;
+  layout->text = g_strdup ("");
+  layout->length = 0;
 }
 
 static void
-pango_layout_class_init (PangoLayoutClass *klass)
+pango_layout_finalize (GObject *object)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  PangoLayout *layout = PANGO_LAYOUT (object);
 
-  object_class->finalize = pango_layout_finalize;
+  g_clear_pointer (&layout->font_desc, pango_font_description_free);
+  g_object_unref (layout->context);
+  g_free (layout->text);
+  g_clear_pointer (&layout->attrs, pango_attr_list_unref);
+  g_clear_pointer (&layout->tabs, pango_tab_array_free);
+  g_clear_object (&layout->lines);
+
+  G_OBJECT_CLASS (pango_layout_parent_class)->finalize (object);
 }
 
 static void
-pango_layout_finalize (GObject *object)
+pango_layout_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
 {
-  PangoLayout *layout;
+  PangoLayout *layout = PANGO_LAYOUT (object);
 
-  layout = PANGO_LAYOUT (object);
+  switch (prop_id)
+    {
+    case PROP_CONTEXT:
+      layout->context = g_value_dup_object (value);
+      layout->context_serial = pango_context_get_serial (layout->context);
+      break;
 
-  pango_layout_clear_lines (layout);
-  g_free (layout->log_attrs);
+    case PROP_TEXT:
+      pango_layout_set_text (layout, g_value_get_string (value), -1);
+      break;
 
-  if (layout->context)
-    g_object_unref (layout->context);
+    case PROP_ATTRIBUTES:
+      pango_layout_set_attributes (layout, g_value_get_boxed (value));
+      break;
 
-  if (layout->attrs)
-    pango_attr_list_unref (layout->attrs);
+    case PROP_FONT_DESCRIPTION:
+      pango_layout_set_font_description (layout, g_value_get_boxed (value));
+      break;
 
-  g_free (layout->text);
+    case PROP_LINE_SPACING:
+      pango_layout_set_line_spacing (layout, g_value_get_float (value));
+      break;
 
-  if (layout->font_desc)
-    pango_font_description_free (layout->font_desc);
+    case PROP_WIDTH:
+      pango_layout_set_width (layout, g_value_get_int (value));
+      break;
 
-  if (layout->tabs)
-    pango_tab_array_free (layout->tabs);
+    case PROP_HEIGHT:
+      pango_layout_set_height (layout, g_value_get_int (value));
+      break;
 
-  G_OBJECT_CLASS (pango_layout_parent_class)->finalize (object);
-}
+    case PROP_TABS:
+      pango_layout_set_tabs (layout, g_value_get_boxed (value));
+      break;
 
-/**
- * pango_layout_new:
- * @context: a `PangoContext`
- *
- * Create a new `PangoLayout` object with attributes initialized to
- * default values for a particular `PangoContext`.
- *
- * Return value: the newly allocated `PangoLayout`
- */
-PangoLayout *
-pango_layout_new (PangoContext *context)
-{
-  PangoLayout *layout;
+    case PROP_SINGLE_PARAGRAPH:
+      pango_layout_set_single_paragraph (layout, g_value_get_boolean (value));
+      break;
 
-  g_return_val_if_fail (context != NULL, NULL);
+    case PROP_WRAP:
+      pango_layout_set_wrap (layout, g_value_get_enum (value));
+      break;
 
-  layout = g_object_new (PANGO_TYPE_LAYOUT, NULL);
+    case PROP_INDENT:
+      pango_layout_set_indent (layout, g_value_get_int (value));
+      break;
 
-  layout->context = context;
-  layout->context_serial = pango_context_get_serial (context);
-  g_object_ref (context);
+    case PROP_ALIGNMENT:
+      pango_layout_set_alignment (layout, g_value_get_enum (value));
+      break;
 
-  return layout;
-}
+    case PROP_ELLIPSIZE:
+      pango_layout_set_ellipsize (layout, g_value_get_enum (value));
+      break;
 
-/**
- * pango_layout_copy:
- * @src: a `PangoLayout`
- *
- * Creates a deep copy-by-value of the layout.
- *
- * The attribute list, tab array, and text from the original layout
- * are all copied by value.
- *
- * Return value: (transfer full): the newly allocated `PangoLayout`
- */
-PangoLayout*
-pango_layout_copy (PangoLayout *src)
-{
-  PangoLayout *layout;
+    case PROP_AUTO_DIR:
+      pango_layout_set_auto_dir (layout, g_value_get_boolean (value));
+      break;
 
-  g_return_val_if_fail (PANGO_IS_LAYOUT (src), NULL);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
 
-  /* Copy referenced members */
+static void
+pango_layout_get_property (GObject      *object,
+                           guint         prop_id,
+                           GValue       *value,
+                           GParamSpec   *pspec)
+{
+  PangoLayout *layout = PANGO_LAYOUT (object);
 
-  layout = pango_layout_new (src->context);
-  if (src->attrs)
-    layout->attrs = pango_attr_list_copy (src->attrs);
-  if (src->font_desc)
-    layout->font_desc = pango_font_description_copy (src->font_desc);
-  if (src->tabs)
-    layout->tabs = pango_tab_array_copy (src->tabs);
+  switch (prop_id)
+    {
+    case PROP_CONTEXT:
+      g_value_set_object (value, layout->context);
+      break;
 
-  /* Dupped */
-  layout->text = g_strdup (src->text);
+    case PROP_TEXT:
+      g_value_set_string (value, layout->text);
+      break;
 
-  /* Value fields */
-  memcpy (&layout->copy_begin, &src->copy_begin,
-          G_STRUCT_OFFSET (PangoLayout, copy_end) - G_STRUCT_OFFSET (PangoLayout, copy_begin));
+    case PROP_ATTRIBUTES:
+      g_value_set_boxed (value, layout->attrs);
+      break;
 
-  return layout;
-}
+    case PROP_FONT_DESCRIPTION:
+      g_value_set_boxed (value, layout->font_desc);
+      break;
 
-/**
- * pango_layout_get_context:
- * @layout: a `PangoLayout`
- *
- * Retrieves the `PangoContext` used for this layout.
- *
- * Return value: (transfer none): the `PangoContext` for the layout
- */
-PangoContext *
-pango_layout_get_context (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, NULL);
+    case PROP_LINE_SPACING:
+      g_value_set_float (value, layout->line_spacing);
+      break;
 
-  return layout->context;
-}
+    case PROP_WIDTH:
+      g_value_set_int (value, layout->width);
+      break;
 
-/**
- * pango_layout_set_width:
- * @layout: a `PangoLayout`.
- * @width: the desired width in Pango units, or -1 to indicate that no
- *   wrapping or ellipsization should be performed.
- *
- * Sets the width to which the lines of the `PangoLayout` should wrap or
- * ellipsized.
- *
- * The default value is -1: no width set.
- */
-void
-pango_layout_set_width (PangoLayout *layout,
-                        int          width)
-{
-  g_return_if_fail (layout != NULL);
+    case PROP_HEIGHT:
+      g_value_set_int (value, layout->height);
+      break;
 
-  if (width < 0)
-    width = -1;
+    case PROP_TABS:
+      g_value_set_boxed (value, layout->tabs);
+      break;
 
-  if (width != layout->width)
-    {
-      layout->width = width;
-      layout_changed (layout);
-    }
-}
+    case PROP_SINGLE_PARAGRAPH:
+      g_value_set_boolean (value, layout->single_paragraph);
+      break;
 
-/**
- * pango_layout_get_width:
- * @layout: a `PangoLayout`
- *
- * Gets the width to which the lines of the `PangoLayout` should wrap.
- *
- * Return value: the width in Pango units, or -1 if no width set.
- */
-int
-pango_layout_get_width (PangoLayout    *layout)
-{
-  g_return_val_if_fail (layout != NULL, 0);
-  return layout->width;
-}
+    case PROP_WRAP:
+      g_value_set_enum (value, layout->wrap);
+      break;
 
-/**
- * pango_layout_set_height:
- * @layout: a `PangoLayout`.
- * @height: the desired height of the layout in Pango units if positive,
- *   or desired number of lines if negative.
- *
- * Sets the height to which the `PangoLayout` should be ellipsized at.
- *
- * There are two different behaviors, based on whether @height is positive
- * or negative.
- *
- * If @height is positive, it will be the maximum height of the layout. Only
- * lines would be shown that would fit, and if there is any text omitted,
- * an ellipsis added. At least one line is included in each paragraph regardless
- * of how small the height value is. A value of zero will render exactly one
- * line for the entire layout.
- *
- * If @height is negative, it will be the (negative of) maximum number of lines
- * per paragraph. That is, the total number of lines shown may well be more than
- * this value if the layout contains multiple paragraphs of text.
- * The default value of -1 means that the first line of each paragraph is ellipsized.
- * This behavior may be changed in the future to act per layout instead of per
- * paragraph. File a bug against pango at
- * [https://gitlab.gnome.org/gnome/pango](https://gitlab.gnome.org/gnome/pango)
- * if your code relies on this behavior.
- *
- * Height setting only has effect if a positive width is set on
- * @layout and ellipsization mode of @layout is not %PANGO_ELLIPSIZE_NONE.
- * The behavior is undefined if a height other than -1 is set and
- * ellipsization mode is set to %PANGO_ELLIPSIZE_NONE, and may change in the
- * future.
- *
- * Since: 1.20
- */
-void
-pango_layout_set_height (PangoLayout *layout,
-                         int          height)
-{
-  g_return_if_fail (layout != NULL);
+    case PROP_INDENT:
+      g_value_set_int (value, layout->indent);
+      break;
 
-  if (height != layout->height)
-    {
-      layout->height = height;
-
-      /* Do not invalidate if the number of lines requested is
-       * larger than the total number of lines in layout.
-       * Bug 549003
-       */
-      if (layout->ellipsize != PANGO_ELLIPSIZE_NONE &&
-          !(layout->lines && layout->is_ellipsized == FALSE &&
-            height < 0 && layout->line_count <= (guint) -height))
-        layout_changed (layout);
-    }
-}
+    case PROP_ALIGNMENT:
+      g_value_set_enum (value, layout->alignment);
+      break;
 
-/**
- * pango_layout_get_height:
- * @layout: a `PangoLayout`
- *
- * Gets the height of layout used for ellipsization.
- *
- * See [method@Pango.Layout.set_height] for details.
- *
- * Return value: the height, in Pango units if positive,
- *   or number of lines if negative.
- *
- * Since: 1.20
- */
-int
-pango_layout_get_height (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, 0);
-  return layout->height;
-}
+    case PROP_ELLIPSIZE:
+      g_value_set_enum (value, layout->ellipsize);
+      break;
 
-/**
- * pango_layout_set_wrap:
- * @layout: a `PangoLayout`
- * @wrap: the wrap mode
- *
- * Sets the wrap mode.
- *
- * The wrap mode only has effect if a width is set on the layout
- * with [method@Pango.Layout.set_width]. To turn off wrapping,
- * set the width to -1.
- *
- * The default value is %PANGO_WRAP_WORD.
- */
-void
-pango_layout_set_wrap (PangoLayout   *layout,
-                       PangoWrapMode  wrap)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+    case PROP_AUTO_DIR:
+      g_value_set_boolean (value, layout->auto_dir);
+      break;
 
-  if (layout->wrap != wrap)
-    {
-      layout->wrap = wrap;
+    case PROP_LINES:
+      g_value_set_object (value, pango_layout_get_lines (layout));
+      break;
 
-      if (layout->width != -1)
-        layout_changed (layout);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
     }
 }
 
-/**
- * pango_layout_get_wrap:
- * @layout: a `PangoLayout`
- *
- * Gets the wrap mode for the layout.
- *
- * Use [method@Pango.Layout.is_wrapped] to query whether
- * any paragraphs were actually wrapped.
- *
- * Return value: active wrap mode.
- */
-PangoWrapMode
-pango_layout_get_wrap (PangoLayout *layout)
+static void
+pango_layout_class_init (PangoLayoutClass *class)
 {
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
-
-  return layout->wrap;
-}
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
 
-/**
- * pango_layout_is_wrapped:
- * @layout: a `PangoLayout`
- *
- * Queries whether the layout had to wrap any paragraphs.
- *
- * This returns %TRUE if a positive width is set on @layout,
- * ellipsization mode of @layout is set to %PANGO_ELLIPSIZE_NONE,
- * and there are paragraphs exceeding the layout width that have
- * to be wrapped.
- *
- * Return value: %TRUE if any paragraphs had to be wrapped, %FALSE
- *   otherwise
- *
- * Since: 1.16
- */
-gboolean
-pango_layout_is_wrapped (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, FALSE);
+  object_class->finalize = pango_layout_finalize;
+  object_class->set_property = pango_layout_set_property;
+  object_class->get_property = pango_layout_get_property;
 
-  pango_layout_check_lines (layout);
+  /**
+   * PangoLayout:context: (attributes org.gtk.Property.get=pango_layout_get_context)
+   *
+   * The context for the `PangoLayout`.
+   */
+  props[PROP_CONTEXT] = g_param_spec_object ("context", "context", "context",
+                                             PANGO_TYPE_CONTEXT,
+                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 
-  return layout->is_wrapped;
-}
+  /**
+   * PangoLayout:text: (attributes org.gtk.Property.get=pango_layout_get_text 
org.gtk.Property.set=pango_layout_set_text)
+   *
+   * The text of the `PangoLayout`.
+   */
+  props[PROP_TEXT] = g_param_spec_string ("text", "text", "text",
+                                          "",
+                                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-/**
- * pango_layout_set_indent:
- * @layout: a `PangoLayout`
- * @indent: the amount by which to indent
- *
- * Sets the width in Pango units to indent each paragraph.
- *
- * A negative value of @indent will produce a hanging indentation.
- * That is, the first line will have the full width, and subsequent
- * lines will be indented by the absolute value of @indent.
- *
- * The indent setting is ignored if layout alignment is set to
- * %PANGO_ALIGN_CENTER.
- *
- * The default value is 0.
- */
-void
-pango_layout_set_indent (PangoLayout *layout,
-                         int          indent)
-{
-  g_return_if_fail (layout != NULL);
-
-  if (indent != layout->indent)
-    {
-      layout->indent = indent;
-      layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_indent:
- * @layout: a `PangoLayout`
- *
- * Gets the paragraph indent width in Pango units.
- *
- * A negative value indicates a hanging indentation.
- *
- * Return value: the indent in Pango units
- */
-int
-pango_layout_get_indent (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, 0);
-  return layout->indent;
-}
-
-/**
- * pango_layout_set_spacing:
- * @layout: a `PangoLayout`
- * @spacing: the amount of spacing
- *
- * Sets the amount of spacing in Pango units between
- * the lines of the layout.
- *
- * When placing lines with spacing, Pango arranges things so that
- *
- *     line2.top = line1.bottom + spacing
- *
- * The default value is 0.
- *
- * Note: Since 1.44, Pango is using the line height (as determined
- * by the font) for placing lines when the line spacing factor is set
- * to a non-zero value with [method@Pango.Layout.set_line_spacing].
- * In that case, the @spacing set with this function is ignored.
- *
- * Note: for semantics that are closer to the CSS line-height
- * property, see [func@Pango.attr_line_height_new].
- */
-void
-pango_layout_set_spacing (PangoLayout *layout,
-                          int          spacing)
-{
-  g_return_if_fail (layout != NULL);
-
-  if (spacing != layout->spacing)
-    {
-      layout->spacing = spacing;
-      layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_spacing:
- * @layout: a `PangoLayout`
- *
- * Gets the amount of spacing between the lines of the layout.
- *
- * Return value: the spacing in Pango units
- */
-int
-pango_layout_get_spacing (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, 0);
-  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 0.
- *
- * 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 [method@Pango.Layout.set_spacing] is ignored.
- *
- * If @factor is zero (the default), spacing is applied as before.
- *
- * Note: for semantics that are closer to the CSS line-height
- * property, see [func@Pango.attr_line_height_new].
- *
- * 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 line spacing factor of @layout.
- *
- * See [method@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`
- * @attrs: (nullable) (transfer none): a `PangoAttrList`
- *
- * Sets the text attributes for a layout object.
- *
- * References @attrs, so the caller can unref its reference.
- */
-void
-pango_layout_set_attributes (PangoLayout   *layout,
-                             PangoAttrList *attrs)
-{
-  PangoAttrList *old_attrs;
-
-  g_return_if_fail (layout != NULL);
-
-  /* Both empty */
-  if (!attrs && !layout->attrs)
-    return;
-
-  if (layout->attrs &&
-      pango_attr_list_equal (layout->attrs, attrs))
-    return;
-
-  old_attrs = layout->attrs;
-
-  /* We always clear lines such that this function can be called
-   * whenever attrs changes.
-   */
-  layout->attrs = attrs;
-  if (layout->attrs)
-    pango_attr_list_ref (layout->attrs);
-
-  g_clear_pointer (&layout->log_attrs, g_free);
-  layout_changed (layout);
-
-  if (old_attrs)
-    pango_attr_list_unref (old_attrs);
-  layout->tab_width = -1;
-}
-
-/**
- * pango_layout_get_attributes:
- * @layout: a `PangoLayout`
- *
- * Gets the attribute list for the layout, if any.
- *
- * Return value: (transfer none) (nullable): a `PangoAttrList`
- */
-PangoAttrList*
-pango_layout_get_attributes (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
-
-  return layout->attrs;
-}
-
-/**
- * pango_layout_set_font_description:
- * @layout: a `PangoLayout`
- * @desc: (nullable): the new `PangoFontDescription`
- *   to unset the current font description
- *
- * Sets the default font description for the layout.
- *
- * If no font description is set on the layout, the
- * font description from the layout's context is used.
- */
-void
-pango_layout_set_font_description (PangoLayout                *layout,
-                                   const PangoFontDescription *desc)
-{
-  g_return_if_fail (layout != NULL);
-
-  if (desc != layout->font_desc &&
-      (!desc || !layout->font_desc || !pango_font_description_equal(desc, layout->font_desc)))
-    {
-      if (layout->font_desc)
-        pango_font_description_free (layout->font_desc);
-
-      layout->font_desc = desc ? pango_font_description_copy (desc) : NULL;
-
-      layout_changed (layout);
-      layout->tab_width = -1;
-    }
-}
-
-/**
- * pango_layout_get_font_description:
- * @layout: a `PangoLayout`
- *
- * Gets the font description for the layout, if any.
- *
- * Return value: (transfer none) (nullable): a pointer to the
- *   layout's font description, or %NULL if the font description
- *   from the layout's context is inherited.
- *
- * Since: 1.8
- */
-const PangoFontDescription *
-pango_layout_get_font_description (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
-
-  return layout->font_desc;
-}
-
-/**
- * pango_layout_set_justify:
- * @layout: a `PangoLayout`
- * @justify: whether the lines in the layout should be justified
- *
- * Sets whether each complete line should be stretched to fill the
- * entire width of the layout.
- *
- * Stretching is typically done by adding whitespace, but for some scripts
- * (such as Arabic), the justification may be done in more complex ways,
- * like extending the characters.
- *
- * Note that this setting is not implemented and so is ignored in
- * Pango older than 1.18.
- *
- * Note that tabs and justification conflict with each other:
- * Justification will move content away from its tab-aligned
- * positions.
- *
- * The default value is %FALSE.
- *
- * Also see [method@Pango.Layout.set_justify_last_line].
- */
-void
-pango_layout_set_justify (PangoLayout *layout,
-                          gboolean     justify)
-{
-  g_return_if_fail (layout != NULL);
-
-  if (justify != layout->justify)
-    {
-      layout->justify = justify;
-
-      if (layout->is_ellipsized ||
-          layout->is_wrapped ||
-          layout->justify_last_line)
-        layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_justify:
- * @layout: a `PangoLayout`
- *
- * Gets whether each complete line should be stretched to fill the entire
- * width of the layout.
- *
- * Return value: the justify value
- */
-gboolean
-pango_layout_get_justify (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, FALSE);
-  return layout->justify;
-}
-
-/**
- * pango_layout_set_justify_last_line:
- * @layout: a `PangoLayout`
- * @justify: whether the last line in the layout should be justified
- *
- * Sets whether the last line should be stretched to fill the
- * entire width of the layout.
- *
- * This only has an effect if [method@Pango.Layout.set_justify] has
- * been called as well.
- *
- * The default value is %FALSE.
- *
- * Since: 1.50
- */
-void
-pango_layout_set_justify_last_line (PangoLayout *layout,
-                                    gboolean     justify)
-{
-  g_return_if_fail (layout != NULL);
-
-  if (justify != layout->justify_last_line)
-    {
-      layout->justify_last_line = justify;
-
-      if (layout->justify)
-        layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_justify_last_line:
- * @layout: a `PangoLayout`
- *
- * Gets whether the last line should be stretched
- * to fill the entire width of the layout.
- *
- * Return value: the justify value
- *
- * Since: 1.50
- */
-gboolean
-pango_layout_get_justify_last_line (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, FALSE);
-  return layout->justify_last_line;
-}
-
-/**
- * pango_layout_set_auto_dir:
- * @layout: a `PangoLayout`
- * @auto_dir: if %TRUE, compute the bidirectional base direction
- *   from the layout's contents
- *
- * Sets whether to calculate the base direction
- * for the layout according to its contents.
- *
- * When this flag is on (the default), then paragraphs in @layout that
- * begin with strong right-to-left characters (Arabic and Hebrew principally),
- * will have right-to-left layout, paragraphs with letters from other scripts
- * will have left-to-right layout. Paragraphs with only neutral characters
- * get their direction from the surrounding paragraphs.
- *
- * When %FALSE, the choice between left-to-right and right-to-left
- * layout is done according to the base direction of the layout's
- * `PangoContext`. (See [method@Pango.Context.set_base_dir]).
- *
- * When the auto-computed direction of a paragraph differs from the
- * base direction of the context, the interpretation of
- * %PANGO_ALIGN_LEFT and %PANGO_ALIGN_RIGHT are swapped.
- *
- * Since: 1.4
- */
-void
-pango_layout_set_auto_dir (PangoLayout *layout,
-                           gboolean     auto_dir)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-  auto_dir = auto_dir != FALSE;
-
-  if (auto_dir != layout->auto_dir)
-    {
-      layout->auto_dir = auto_dir;
-      layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_auto_dir:
- * @layout: a `PangoLayout`
- *
- * Gets whether to calculate the base direction for the layout
- * according to its contents.
- *
- * See [method@Pango.Layout.set_auto_dir].
- *
- * Return value: %TRUE if the bidirectional base direction
- *   is computed from the layout's contents, %FALSE otherwise
- *
- * Since: 1.4
- */
-gboolean
-pango_layout_get_auto_dir (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), TRUE);
-
-  return layout->auto_dir;
-}
-
-/**
- * pango_layout_set_alignment:
- * @layout: a `PangoLayout`
- * @alignment: the alignment
- *
- * Sets the alignment for the layout: how partial lines are
- * positioned within the horizontal space available.
- *
- * The default alignment is %PANGO_ALIGN_LEFT.
- */
-void
-pango_layout_set_alignment (PangoLayout   *layout,
-                            PangoAlignment alignment)
-{
-  g_return_if_fail (layout != NULL);
-
-  if (alignment != layout->alignment)
-    {
-      layout->alignment = alignment;
-      layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_alignment:
- * @layout: a `PangoLayout`
- *
- * Gets the alignment for the layout: how partial lines are
- * positioned within the horizontal space available.
- *
- * Return value: the alignment
- */
-PangoAlignment
-pango_layout_get_alignment (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, PANGO_ALIGN_LEFT);
-  return layout->alignment;
-}
-
-
-/**
- * pango_layout_set_tabs:
- * @layout: a `PangoLayout`
- * @tabs: (nullable): a `PangoTabArray`
- *
- * Sets the tabs to use for @layout, overriding the default tabs.
- *
- * `PangoLayout` will place content at the next tab position
- * whenever it meets a Tab character (U+0009).
- *
- * By default, tabs are every 8 spaces. If @tabs is %NULL, the
- * default tabs are reinstated. @tabs is copied into the layout;
- * you must free your copy of @tabs yourself.
- *
- * Note that tabs and justification conflict with each other:
- * Justification will move content away from its tab-aligned
- * positions. The same is true for alignments other than
- * %PANGO_ALIGN_LEFT.
- */
-void
-pango_layout_set_tabs (PangoLayout   *layout,
-                       PangoTabArray *tabs)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-
-  if (tabs != layout->tabs)
-    {
-      g_clear_pointer (&layout->tabs, pango_tab_array_free);
-
-      if (tabs)
-        {
-          layout->tabs = pango_tab_array_copy (tabs);
-          pango_tab_array_sort (layout->tabs);
-        }
-
-      layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_tabs:
- * @layout: a `PangoLayout`
- *
- * Gets the current `PangoTabArray` used by this layout.
- *
- * If no `PangoTabArray` has been set, then the default tabs are
- * in use and %NULL is returned. Default tabs are every 8 spaces.
- *
- * The return value should be freed with [method Pango TabArray free].
- *
- * Return value: (transfer full) (nullable): a copy of the tabs for this layout
- */
-PangoTabArray*
-pango_layout_get_tabs (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
-
-  if (layout->tabs)
-    return pango_tab_array_copy (layout->tabs);
-  else
-    return NULL;
-}
-
-/**
- * pango_layout_set_single_paragraph_mode:
- * @layout: a `PangoLayout`
- * @setting: new setting
- *
- * Sets the single paragraph mode of @layout.
- *
- * If @setting is %TRUE, do not treat newlines and similar characters
- * as paragraph separators; instead, keep all text in a single paragraph,
- * and display a glyph for paragraph separator characters. Used when
- * you want to allow editing of newlines on a single text line.
- *
- * The default value is %FALSE.
- */
-void
-pango_layout_set_single_paragraph_mode (PangoLayout *layout,
-                                        gboolean     setting)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-  setting = setting != FALSE;
-
-  if (layout->single_paragraph != setting)
-    {
-      layout->single_paragraph = setting;
-      layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_single_paragraph_mode:
- * @layout: a `PangoLayout`
- *
- * Obtains whether @layout is in single paragraph mode.
- *
- * See [method@Pango.Layout.set_single_paragraph_mode].
- *
- * Return value: %TRUE if the layout does not break paragraphs
- *   at paragraph separator characters, %FALSE otherwise
- */
-gboolean
-pango_layout_get_single_paragraph_mode (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
-
-  return layout->single_paragraph;
-}
-
-/**
- * pango_layout_set_ellipsize:
- * @layout: a `PangoLayout`
- * @ellipsize: the new ellipsization mode for @layout
- *
- * Sets the type of ellipsization being performed for @layout.
- *
- * Depending on the ellipsization mode @ellipsize text is
- * removed from the start, middle, or end of text so they
- * fit within the width and height of layout set with
- * [method@Pango.Layout.set_width] and [method@Pango.Layout.set_height].
- *
- * If the layout contains characters such as newlines that
- * force it to be layed out in multiple paragraphs, then whether
- * each paragraph is ellipsized separately or the entire layout
- * is ellipsized as a whole depends on the set height of the layout.
- *
- * The default value is %PANGO_ELLIPSIZE_NONE.
- *
- * See [method@Pango.Layout.set_height] for details.
- *
- * Since: 1.6
- */
-void
-pango_layout_set_ellipsize (PangoLayout        *layout,
-                            PangoEllipsizeMode  ellipsize)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-  if (ellipsize != layout->ellipsize)
-    {
-      layout->ellipsize = ellipsize;
-
-      if (layout->is_ellipsized || layout->is_wrapped)
-        layout_changed (layout);
-    }
-}
-
-/**
- * pango_layout_get_ellipsize:
- * @layout: a `PangoLayout`
- *
- * Gets the type of ellipsization being performed for @layout.
- *
- * See [method@Pango.Layout.set_ellipsize].
- *
- * Use [method@Pango.Layout.is_ellipsized] to query whether any
- * paragraphs were actually ellipsized.
- *
- * Return value: the current ellipsization mode for @layout
- *
- * Since: 1.6
- */
-PangoEllipsizeMode
-pango_layout_get_ellipsize (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), PANGO_ELLIPSIZE_NONE);
-
-  return layout->ellipsize;
-}
-
-/**
- * pango_layout_is_ellipsized:
- * @layout: a `PangoLayout`
- *
- * Queries whether the layout had to ellipsize any paragraphs.
- *
- * This returns %TRUE if the ellipsization mode for @layout
- * is not %PANGO_ELLIPSIZE_NONE, a positive width is set on @layout,
- * and there are paragraphs exceeding that width that have to be
- * ellipsized.
- *
- * Return value: %TRUE if any paragraphs had to be ellipsized,
- *   %FALSE otherwise
- *
- * Since: 1.16
- */
-gboolean
-pango_layout_is_ellipsized (PangoLayout *layout)
-{
-  g_return_val_if_fail (layout != NULL, FALSE);
-
-  pango_layout_check_lines (layout);
-
-  return layout->is_ellipsized;
-}
-
-/**
- * pango_layout_set_text:
- * @layout: a `PangoLayout`
- * @text: the text
- * @length: maximum length of @text, in bytes. -1 indicates that
- *   the string is nul-terminated and the length should be calculated.
- *   The text will also be truncated on encountering a nul-termination
- *   even when @length is positive.
- *
- * Sets the text of the layout.
- *
- * This function validates @text and renders invalid UTF-8
- * with a placeholder glyph.
- *
- * Note that if you have used [method@Pango.Layout.set_markup] or
- * [method@Pango.Layout.set_markup_with_accel] on @layout before, you
- * may want to call [method@Pango.Layout.set_attributes] to clear the
- * attributes set on the layout from the markup as this function does
- * not clear attributes.
- */
-void
-pango_layout_set_text (PangoLayout *layout,
-                       const char  *text,
-                       int          length)
-{
-  char *old_text, *start, *end;
-
-  g_return_if_fail (layout != NULL);
-  g_return_if_fail (length == 0 || text != NULL);
-
-  old_text = layout->text;
-
-  if (length < 0)
-    {
-      layout->length = strlen (text);
-      layout->text = g_strndup (text, layout->length);
-    }
-  else if (length > 0)
-    {
-      /* This is not exactly what we want.  We don't need the padding...
-       */
-      layout->length = length;
-      layout->text = g_strndup (text, length);
-    }
-  else
-    {
-      layout->length = 0;
-      layout->text = g_malloc0 (1);
-    }
-
-  /* validate it, and replace invalid bytes with -1 */
-  start = layout->text;
-  for (;;) {
-    gboolean valid;
-
-    valid = g_utf8_validate (start, -1, (const char **)&end);
-
-    if (!*end)
-      break;
-
-    /* Replace invalid bytes with -1.  The -1 will be converted to
-     * ((gunichar) -1) by glib, and that in turn yields a glyph value of
-     * ((PangoGlyph) -1) by PANGO_GET_UNKNOWN_GLYPH(-1),
-     * and that's PANGO_GLYPH_INVALID_INPUT.
-     */
-    if (!valid)
-      *end++ = -1;
-
-    start = end;
-  }
-
-  if (start != layout->text)
-    /* TODO: Write out the beginning excerpt of text? */
-    g_warning ("Invalid UTF-8 string passed to pango_layout_set_text()");
-
-  layout->n_chars = pango_utf8_strlen (layout->text, -1);
-  layout->length = strlen (layout->text);
-
-  g_clear_pointer (&layout->log_attrs, g_free);
-  layout_changed (layout);
-
-  g_free (old_text);
-}
-
-/**
- * pango_layout_get_text:
- * @layout: a `PangoLayout`
- *
- * Gets the text in the layout.
- *
- * The returned text should not be freed or modified.
- *
- * Return value: (transfer none): the text in the @layout
- */
-const char*
-pango_layout_get_text (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
-
-  /* We don't ever want to return NULL as the text.
-   */
-  if (G_UNLIKELY (!layout->text))
-    return "";
-
-  return layout->text;
-}
-
-/**
- * pango_layout_get_character_count:
- * @layout: a `PangoLayout`
- *
- * Returns the number of Unicode characters in the
- * the text of @layout.
- *
- * Return value: the number of Unicode characters
- *   in the text of @layout
- *
- * Since: 1.30
- */
-gint
-pango_layout_get_character_count (PangoLayout *layout)
-{
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
-
-  return layout->n_chars;
-}
-
-/**
- * pango_layout_set_markup:
- * @layout: a `PangoLayout`
- * @markup: marked-up text
- * @length: length of marked-up text in bytes, or -1 if @markup is
- *   `NUL`-terminated
- *
- * Sets the layout text and attribute list from marked-up text.
- *
- * See [Pango Markup](pango_markup.html)).
- *
- * Replaces the current text and attribute list.
- *
- * This is the same as [method@Pango.Layout.set_markup_with_accel],
- * but the markup text isn't scanned for accelerators.
- */
-void
-pango_layout_set_markup (PangoLayout *layout,
-                         const char  *markup,
-                         int          length)
-{
-  pango_layout_set_markup_with_accel (layout, markup, length, 0, NULL);
-}
-
-/**
- * pango_layout_set_markup_with_accel:
- * @layout: a `PangoLayout`
- * @markup: marked-up text (see [Pango Markup](pango_markup.html))
- * @length: length of marked-up text in bytes, or -1 if @markup is
- *   `NUL`-terminated
- * @accel_marker: marker for accelerators in the text
- * @accel_char: (out caller-allocates) (optional): return location
- *   for first located accelerator
- *
- * Sets the layout text and attribute list from marked-up text.
- *
- * See [Pango Markup](pango_markup.html)).
- *
- * Replaces the current text and attribute list.
- *
- * If @accel_marker is nonzero, the given character will mark the
- * character following it as an accelerator. For example, @accel_marker
- * might be an ampersand or underscore. All characters marked
- * as an accelerator will receive a %PANGO_UNDERLINE_LOW attribute,
- * and the first character so marked will be returned in @accel_char.
- * Two @accel_marker characters following each other produce a single
- * literal @accel_marker character.
- */
-void
-pango_layout_set_markup_with_accel (PangoLayout *layout,
-                                    const char  *markup,
-                                    int          length,
-                                    gunichar     accel_marker,
-                                    gunichar    *accel_char)
-{
-  PangoAttrList *list = NULL;
-  char *text = NULL;
-  GError *error;
-
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-  g_return_if_fail (markup != NULL);
-
-  error = NULL;
-  if (!pango_parse_markup (markup, length,
-                           accel_marker,
-                           &list, &text,
-                           accel_char,
-                           &error))
-    {
-      g_warning ("pango_layout_set_markup_with_accel: %s", error->message);
-      g_error_free (error);
-      return;
-    }
-
-  pango_layout_set_text (layout, text, -1);
-  pango_layout_set_attributes (layout, list);
-  pango_attr_list_unref (list);
-  g_free (text);
-}
-
-/**
- * pango_layout_get_unknown_glyphs_count:
- * @layout: a `PangoLayout`
- *
- * Counts the number of unknown glyphs in @layout.
- *
- * This function can be used to determine if there are any fonts
- * available to render all characters in a certain string, or when
- * used in combination with %PANGO_ATTR_FALLBACK, to check if a
- * certain font supports all the characters in the string.
- *
- * Return value: The number of unknown glyphs in @layout
- *
- * Since: 1.16
- */
-int
-pango_layout_get_unknown_glyphs_count (PangoLayout *layout)
-{
-    PangoLayoutLine *line;
-    PangoLayoutRun *run;
-    GSList *lines_list;
-    GSList *runs_list;
-    int i, count = 0;
-
-    g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
-
-    pango_layout_check_lines (layout);
-
-    if (layout->unknown_glyphs_count >= 0)
-      return layout->unknown_glyphs_count;
-
-    lines_list = layout->lines;
-    while (lines_list)
-      {
-        line = lines_list->data;
-        runs_list = line->runs;
-
-        while (runs_list)
-          {
-            run = runs_list->data;
-
-            for (i = 0; i < run->glyphs->num_glyphs; i++)
-              {
-                if (run->glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)
-                    count++;
-              }
-
-            runs_list = runs_list->next;
-          }
-        lines_list = lines_list->next;
-      }
-
-    layout->unknown_glyphs_count = count;
-    return count;
-}
-
-static void
-check_context_changed (PangoLayout *layout)
-{
-  guint old_serial = layout->context_serial;
-
-  layout->context_serial = pango_context_get_serial (layout->context);
-
-  if (old_serial != layout->context_serial)
-    pango_layout_context_changed (layout);
-}
-
-static void
-layout_changed (PangoLayout *layout)
-{
-  layout->serial++;
-  if (layout->serial == 0)
-    layout->serial++;
-
-  pango_layout_clear_lines (layout);
-}
-
-/**
- * pango_layout_context_changed:
- * @layout: a `PangoLayout`
- *
- * Forces recomputation of any state in the `PangoLayout` that
- * might depend on the layout's context.
- *
- * This function should be called if you make changes to the context
- * subsequent to creating the layout.
- */
-void
-pango_layout_context_changed (PangoLayout *layout)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-  layout_changed (layout);
-  layout->tab_width = -1;
-}
-
-/**
- * pango_layout_get_serial:
- * @layout: a `PangoLayout`
- *
- * Returns the current serial number of @layout.
- *
- * The serial number is initialized to an small number larger than zero
- * when a new layout is created and is increased whenever the layout is
- * changed using any of the setter functions, or the `PangoContext` it
- * uses has changed. The serial may wrap, but will never have the value 0.
- * Since it can wrap, never compare it with "less than", always use "not equals".
- *
- * This can be used to automatically detect changes to a `PangoLayout`,
- * and is useful for example to decide whether a layout needs redrawing.
- * To force the serial to be increased, use
- * [method@Pango.Layout.context_changed].
- *
- * Return value: The current serial number of @layout.
- *
- * Since: 1.32.4
- */
-guint
-pango_layout_get_serial (PangoLayout *layout)
-{
-  check_context_changed (layout);
-  return layout->serial;
-}
-
-/**
- * pango_layout_get_log_attrs:
- * @layout: a `PangoLayout`
- * @attrs: (out)(array length=n_attrs)(transfer container):
- *   location to store a pointer to an array of logical attributes.
- *   This value must be freed with g_free().
- * @n_attrs: (out): location to store the number of the attributes in the
- *   array. (The stored value will be one more than the total number
- *   of characters in the layout, since there need to be attributes
- *   corresponding to both the position before the first character
- *   and the position after the last character.)
- *
- * Retrieves an array of logical attributes for each character in
- * the @layout.
- */
-void
-pango_layout_get_log_attrs (PangoLayout   *layout,
-                            PangoLogAttr **attrs,
-                            gint          *n_attrs)
-{
-  g_return_if_fail (layout != NULL);
-
-  pango_layout_check_lines (layout);
-
-  if (attrs)
-    {
-      *attrs = g_new (PangoLogAttr, layout->n_chars + 1);
-      memcpy (*attrs, layout->log_attrs, sizeof(PangoLogAttr) * (layout->n_chars + 1));
-    }
-
-  if (n_attrs)
-    *n_attrs = layout->n_chars + 1;
-}
-
-/**
- * pango_layout_get_log_attrs_readonly:
- * @layout: a `PangoLayout`
- * @n_attrs: (out): location to store the number of the attributes in
- *   the array
- *
- * Retrieves an array of logical attributes for each character in
- * the @layout.
- *
- * This is a faster alternative to [method@Pango.Layout.get_log_attrs].
- * The returned array is part of @layout and must not be modified.
- * Modifying the layout will invalidate the returned array.
- *
- * The number of attributes returned in @n_attrs will be one more
- * than the total number of characters in the layout, since there
- * need to be attributes corresponding to both the position before
- * the first character and the position after the last character.
- *
- * Returns: (array length=n_attrs): an array of logical attributes
- *
- * Since: 1.30
- */
-const PangoLogAttr *
-pango_layout_get_log_attrs_readonly (PangoLayout *layout,
-                                     gint        *n_attrs)
-{
-  if (n_attrs)
-    *n_attrs = 0;
-  g_return_val_if_fail (layout != NULL, NULL);
-
-  pango_layout_check_lines (layout);
-
-  if (n_attrs)
-    *n_attrs = layout->n_chars + 1;
-
-  return layout->log_attrs;
-}
-
-
-/**
- * pango_layout_get_line_count:
- * @layout: `PangoLayout`
- *
- * Retrieves the count of lines for the @layout.
- *
- * Return value: the line count
- */
-int
-pango_layout_get_line_count (PangoLayout   *layout)
-{
-  g_return_val_if_fail (layout != NULL, 0);
-
-  pango_layout_check_lines (layout);
-  return layout->line_count;
-}
-
-/**
- * pango_layout_get_lines:
- * @layout: a `PangoLayout`
- *
- * Returns the lines of the @layout as a list.
- *
- * Use the faster [method@Pango.Layout.get_lines_readonly] if you do not
- * plan to modify the contents of the lines (glyphs, glyph widths, etc.).
- *
- * Return value: (element-type Pango.LayoutLine) (transfer none): a `GSList`
- *   containing the lines in the layout. This points to internal data of the
- *   `PangoLayout` and must be used with care. It will become invalid on any
- *   change to the layout's text or properties.
- */
-GSList *
-pango_layout_get_lines (PangoLayout *layout)
-{
-  pango_layout_check_lines (layout);
-
-  if (layout->lines)
-    {
-      GSList *tmp_list = layout->lines;
-      while (tmp_list)
-        {
-          PangoLayoutLine *line = tmp_list->data;
-          tmp_list = tmp_list->next;
-
-          pango_layout_line_leaked (line);
-        }
-    }
-
-  return layout->lines;
-}
-
-/**
- * pango_layout_get_lines_readonly:
- * @layout: a `PangoLayout`
- *
- * Returns the lines of the @layout as a list.
- *
- * This is a faster alternative to [method@Pango.Layout.get_lines],
- * but the user is not expected to modify the contents of the lines
- * (glyphs, glyph widths, etc.).
- *
- * Return value: (element-type Pango.LayoutLine) (transfer none): a `GSList`
- *   containing the lines in the layout. This points to internal data of the
- *   `PangoLayout` and must be used with care. It will become invalid on any
- *   change to the layout's text or properties. No changes should be made to
- *   the lines.
- *
- * Since: 1.16
- */
-GSList *
-pango_layout_get_lines_readonly (PangoLayout *layout)
-{
-  pango_layout_check_lines (layout);
-
-  return layout->lines;
-}
-
-/**
- * pango_layout_get_line:
- * @layout: a `PangoLayout`
- * @line: the index of a line, which must be between 0 and
- *   `pango_layout_get_line_count(layout) - 1`, inclusive.
- *
- * Retrieves a particular line from a `PangoLayout`.
- *
- * Use the faster [method@Pango.Layout.get_line_readonly] if you do not
- * plan to modify the contents of the line (glyphs, glyph widths, etc.).
- *
- * Return value: (transfer none) (nullable): the requested `PangoLayoutLine`,
- *   or %NULL if the index is out of range. This layout line can be ref'ed
- *   and retained, but will become invalid if changes are made to the
- *   `PangoLayout`.
- */
-PangoLayoutLine *
-pango_layout_get_line (PangoLayout *layout,
-                       int          line)
-{
-  GSList *list_item;
-  g_return_val_if_fail (layout != NULL, NULL);
-
-  if (line < 0)
-    return NULL;
-
-  pango_layout_check_lines (layout);
-
-  list_item = g_slist_nth (layout->lines, line);
-
-  if (list_item)
-    {
-      PangoLayoutLine *line = list_item->data;
-
-      pango_layout_line_leaked (line);
-      return line;
-    }
-
-  return NULL;
-}
-
-/**
- * pango_layout_get_line_readonly:
- * @layout: a `PangoLayout`
- * @line: the index of a line, which must be between 0 and
- *   `pango_layout_get_line_count(layout) - 1`, inclusive.
- *
- * Retrieves a particular line from a `PangoLayout`.
- *
- * This is a faster alternative to [method@Pango.Layout.get_line],
- * but the user is not expected to modify the contents of the line
- * (glyphs, glyph widths, etc.).
- *
- * Return value: (transfer none) (nullable): the requested `PangoLayoutLine`,
- *   or %NULL if the index is out of range. This layout line can be ref'ed
- *   and retained, but will become invalid if changes are made to the
- *   `PangoLayout`. No changes should be made to the line.
- *
- * Since: 1.16
- */
-PangoLayoutLine *
-pango_layout_get_line_readonly (PangoLayout *layout,
-                                int          line)
-{
-  GSList *list_item;
-  g_return_val_if_fail (layout != NULL, NULL);
-
-  if (line < 0)
-    return NULL;
-
-  pango_layout_check_lines (layout);
-
-  list_item = g_slist_nth (layout->lines, line);
-
-  if (list_item)
-    {
-      PangoLayoutLine *line = list_item->data;
-      return line;
-    }
-
-  return NULL;
-}
-
-/**
- * pango_layout_line_index_to_x:
- * @line: a `PangoLayoutLine`
- * @index_: byte offset of a grapheme within the layout
- * @trailing: an integer indicating the edge of the grapheme to retrieve
- *   the position of. If > 0, the trailing edge of the grapheme,
- *   if 0, the leading of the grapheme
- * @x_pos: (out): location to store the x_offset (in Pango units)
- *
- * Converts an index within a line to a X position.
- */
-void
-pango_layout_line_index_to_x (PangoLayoutLine *line,
-                              int              index,
-                              int              trailing,
-                              int             *x_pos)
-{
-  PangoLayout *layout = line->layout;
-  GSList *run_list = line->runs;
-  int width = 0;
-
-  while (run_list)
-    {
-      PangoLayoutRun *run = run_list->data;
-
-      if (run->item->offset <= index && run->item->offset + run->item->length > index)
-        {
-          int offset = g_utf8_pointer_to_offset (layout->text, layout->text + index);
-          int attr_offset;
-
-          if (trailing)
-            {
-              while (index < line->start_index + line->length &&
-                     offset + 1 < layout->n_chars &&
-                     !layout->log_attrs[offset + 1].is_cursor_position)
-                {
-                  offset++;
-                  index = g_utf8_next_char (layout->text + index) - layout->text;
-                }
-            }
-          else
-            {
-              while (index > line->start_index &&
-                     !layout->log_attrs[offset].is_cursor_position)
-                {
-                  offset--;
-                  index = g_utf8_prev_char (layout->text + index) - layout->text;
-                }
-            }
-
-          /* Note: we simply assert here, since our items are all internally
-           * created. If that ever changes, we need to add a fallback here.
-           */
-          attr_offset = run->item->char_offset;
-
-          pango_glyph_string_index_to_x_full (run->glyphs,
-                                              layout->text + run->item->offset,
-                                              run->item->length,
-                                              &run->item->analysis,
-                                              layout->log_attrs + attr_offset,
-                                              index - run->item->offset, trailing, x_pos);
-          if (x_pos)
-            *x_pos += width;
-
-          return;
-        }
-
-      width += pango_glyph_string_get_width (run->glyphs);
-
-      run_list = run_list->next;
-    }
-
-  if (x_pos)
-    *x_pos = width;
-}
-
-static PangoLayoutLine *
-pango_layout_index_to_line (PangoLayout      *layout,
-                            int               index,
-                            int              *line_nr,
-                            PangoLayoutLine **line_before,
-                            PangoLayoutLine **line_after)
-{
-  GSList *tmp_list;
-  GSList *line_list;
-  PangoLayoutLine *line = NULL;
-  PangoLayoutLine *prev_line = NULL;
-  int i = -1;
-
-  line_list = tmp_list = layout->lines;
-  while (tmp_list)
-    {
-      PangoLayoutLine *tmp_line = tmp_list->data;
-
-      if (tmp_line->start_index > index)
-        break; /* index was in paragraph delimiters */
-
-      prev_line = line;
-      line = tmp_line;
-      line_list = tmp_list;
-      i++;
-
-      if (line->start_index + line->length > index)
-        break;
-
-      tmp_list = tmp_list->next;
-    }
-
-  if (line_nr)
-    *line_nr = i;
-
-  if (line_before)
-    *line_before = prev_line;
-
-  if (line_after)
-    *line_after = (line_list && line_list->next) ? line_list->next->data : NULL;
-
-  return line;
-}
-
-static PangoLayoutLine *
-pango_layout_index_to_line_and_extents (PangoLayout     *layout,
-                                        int              index,
-                                        PangoRectangle  *line_rect,
-                                        PangoRectangle  *run_rect)
-{
-  PangoLayoutIter iter;
-  PangoLayoutLine *line = NULL;
-
-  _pango_layout_get_iter (layout, &iter);
-
-  if (!ITER_IS_INVALID (&iter))
-    while (TRUE)
-      {
-        PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (&iter);
-
-        if (tmp_line->start_index > index)
-          break; /* index was in paragraph delimiters */
-
-        line = tmp_line;
-
-        pango_layout_iter_get_line_extents (&iter, NULL, line_rect);
-
-        if (!iter.line_list_link->next ||
-            ((PangoLayoutLine *)iter.line_list_link->next->data)->start_index > index)
-          {
-            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)
-                      break;
-
-                    if (run->item->offset <= index && index < run->item->offset + run->item->length)
-                      break;
-
-                    if (!pango_layout_iter_next_run (&iter))
-                      break;
-                  }
-              }
-
-            break;
-          }
-
-        if (!pango_layout_iter_next_line (&iter))
-          break; /* Use end of last line */
-      }
-
-  _pango_layout_iter_destroy (&iter);
-
-  return line;
-}
-
-/**
- * pango_layout_index_to_line_x:
- * @layout: a `PangoLayout`
- * @index_: the byte index of a grapheme within the layout
- * @trailing: an integer indicating the edge of the grapheme to retrieve the
- *   position of. If > 0, the trailing edge of the grapheme, if 0,
- *   the leading of the grapheme
- * @line: (out) (optional): location to store resulting line index. (which will
- *   between 0 and pango_layout_get_line_count(layout) - 1)
- * @x_pos: (out) (optional): location to store resulting position within line
- *   (%PANGO_SCALE units per device unit)
- *
- * Converts from byte @index_ within the @layout to line and X position.
- *
- * The X position is measured from the left edge of the line.
- */
-void
-pango_layout_index_to_line_x (PangoLayout *layout,
-                              int          index,
-                              gboolean     trailing,
-                              int         *line,
-                              int         *x_pos)
-{
-  int line_num;
-  PangoLayoutLine *layout_line = NULL;
-
-  g_return_if_fail (layout != NULL);
-  g_return_if_fail (index >= 0);
-  g_return_if_fail (index <= layout->length);
-
-  pango_layout_check_lines (layout);
-
-  layout_line = pango_layout_index_to_line (layout, index,
-                                            &line_num, NULL, NULL);
-
-  if (layout_line)
-    {
-      /* use end of line if index was in the paragraph delimiters */
-      if (index > layout_line->start_index + layout_line->length)
-        index = layout_line->start_index + layout_line->length;
-
-      if (line)
-        *line = line_num;
-
-      pango_layout_line_index_to_x (layout_line, index, trailing, x_pos);
-    }
-  else
-    {
-      if (line)
-        *line = -1;
-      if (x_pos)
-        *x_pos = -1;
-    }
-}
-
-typedef struct {
-  int x;
-  int pos;
-} CursorPos;
-
-static int
-compare_cursor (gconstpointer v1,
-                gconstpointer v2)
-{
-  const CursorPos *c1 = v1;
-  const CursorPos *c2 = v2;
-
-  return c1->x - c2->x;
-}
-
-static void
-pango_layout_line_get_cursors (PangoLayoutLine *line,
-                               gboolean         strong,
-                               GArray          *cursors)
-{
-  PangoLayout *layout = line->layout;
-  int line_no;
-  PangoLayoutLine *line2;
-  const char *start, *end;
-  int start_offset;
-  int j;
-  const char *p;
-  PangoRectangle pos;
-
-  g_assert (g_array_get_element_size (cursors) == sizeof (CursorPos));
-  g_assert (cursors->len == 0);
-
-  start = layout->text + line->start_index;
-  end = start + line->length;
-  start_offset = g_utf8_pointer_to_offset (layout->text, start);
-
-  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)
-        {
-          CursorPos cursor;
-
-          pango_layout_get_cursor_pos (layout, p - layout->text,
-                                       strong ? &pos : NULL,
-                                       strong ? NULL : &pos);
-
-          cursor.x = pos.x;
-          cursor.pos = p - layout->text;
-          g_array_append_val (cursors, cursor);
-        }
-    }
-
-  g_array_sort (cursors, compare_cursor);
-}
-
-/**
- * pango_layout_move_cursor_visually:
- * @layout: a `PangoLayout`
- * @strong: whether the moving cursor is the strong cursor or the
- *   weak cursor. The strong cursor is the cursor corresponding
- *   to text insertion in the base direction for the layout.
- * @old_index: the byte index of the current cursor position
- * @old_trailing: if 0, the cursor was at the leading edge of the
- *   grapheme indicated by @old_index, if > 0, the cursor
- *   was at the trailing edge.
- * @direction: direction to move cursor. A negative
- *   value indicates motion to the left
- * @new_index: (out): location to store the new cursor byte index.
- *   A value of -1 indicates that the cursor has been moved off the
- *   beginning of the layout. A value of %G_MAXINT indicates that
- *   the cursor has been moved off the end of the layout.
- * @new_trailing: (out): number of characters to move forward from
- *   the location returned for @new_index to get the position where
- *   the cursor should be displayed. This allows distinguishing the
- *   position at the beginning of one line from the position at the
- *   end of the preceding line. @new_index is always on the line where
- *   the cursor should be displayed.
- *
- * Computes a new cursor position from an old position and a direction.
- *
- * If @direction is positive, then the new position will cause the strong
- * or weak cursor to be displayed one position to right of where it was
- * with the old cursor position. If @direction is negative, it will be
- * moved to the left.
- *
- * In the presence of bidirectional text, the correspondence between
- * logical and visual order will depend on the direction of the current
- * run, and there may be jumps when the cursor is moved off of the end
- * of a run.
- *
- * Motion here is in cursor positions, not in characters, so a single
- * call to this function may move the cursor over multiple characters
- * when multiple characters combine to form a single grapheme.
- */
-void
-pango_layout_move_cursor_visually (PangoLayout *layout,
-                                   gboolean     strong,
-                                   int          old_index,
-                                   int          old_trailing,
-                                   int          direction,
-                                   int         *new_index,
-                                   int         *new_trailing)
-{
-  PangoLayoutLine *line = NULL;
-  PangoLayoutLine *prev_line;
-  PangoLayoutLine *next_line;
-  GArray *cursors;
-  int n_vis;
-  int vis_pos;
-  int start_offset;
-  gboolean off_start = FALSE;
-  gboolean off_end = FALSE;
-  PangoRectangle pos;
-  int j;
-
-  g_return_if_fail (layout != NULL);
-  g_return_if_fail (old_index >= 0 && old_index <= layout->length);
-  g_return_if_fail (old_trailing >= 0);
-  g_return_if_fail (old_index < layout->length || old_trailing == 0);
-  g_return_if_fail (new_index != NULL);
-  g_return_if_fail (new_trailing != NULL);
-
-  direction = (direction >= 0 ? 1 : -1);
-
-  pango_layout_check_lines (layout);
-
-  /* Find the line the old cursor is on */
-  line = pango_layout_index_to_line (layout, old_index, NULL, &prev_line, &next_line);
-
-  while (old_trailing--)
-    old_index = g_utf8_next_char (layout->text + old_index) - layout->text;
-
-  /* Clamp old_index to fit on the line */
-  if (old_index > (line->start_index + line->length))
-    old_index = line->start_index + line->length;
-
-  cursors = g_array_new (FALSE, FALSE, sizeof (CursorPos));
-  pango_layout_line_get_cursors (line, strong, cursors);
-
-  pango_layout_get_cursor_pos (layout, old_index, strong ? &pos : NULL, strong ? NULL : &pos);
-
-  vis_pos = -1;
-  for (j = 0; j < cursors->len; j++)
-    {
-      CursorPos *cursor = &g_array_index (cursors, CursorPos, j);
-      if (cursor->x == pos.x)
-        {
-          vis_pos = j;
-
-          /* If moving left, we pick the leftmost match, otherwise
-           * the rightmost one. Without this, we can get stuck
-           */
-          if (direction < 0)
-            break;
-        }
-    }
-
-  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)
-    {
-      if (old_index == line->start_index && direction < 0)
-        off_start = TRUE;
-      if (old_index == line->start_index + line->length && direction > 0)
-        off_end = TRUE;
-    }
-  else
-    {
-      if (old_index == line->start_index + line->length && direction < 0)
-        off_end = TRUE;
-      if (old_index == line->start_index && direction > 0)
-        off_start = TRUE;
-    }
-
-  if (off_start || off_end)
-    {
-      /* If we move over a paragraph boundary, count that as
-       * an extra position in the motion
-       */
-      gboolean paragraph_boundary;
-
-      if (off_start)
-        {
-          if (!prev_line)
-            {
-              *new_index = -1;
-              *new_trailing = 0;
-              g_array_unref (cursors);
-              return;
-            }
-          line = prev_line;
-          paragraph_boundary = (line->start_index + line->length != old_index);
-        }
-      else
-        {
-          if (!next_line)
-            {
-              *new_index = G_MAXINT;
-              *new_trailing = 0;
-              g_array_unref (cursors);
-              return;
-            }
-          line = next_line;
-          paragraph_boundary = (line->start_index != old_index);
-        }
-
-      g_array_set_size (cursors, 0);
-      pango_layout_line_get_cursors (line, strong, cursors);
-
-      n_vis = cursors->len;
-
-      if (off_start && direction < 0)
-        {
-          vis_pos = n_vis;
-          if (paragraph_boundary)
-            vis_pos++;
-        }
-      else if (off_end && direction > 0)
-        {
-          vis_pos = 0;
-          if (paragraph_boundary)
-            vis_pos--;
-        }
-    }
-
-  if (direction < 0)
-    vis_pos--;
-  else
-    vis_pos++;
-
-  if (0 <= vis_pos && vis_pos < cursors->len)
-    *new_index = g_array_index (cursors, CursorPos, vis_pos).pos;
-  else if (vis_pos >= cursors->len - 1)
-    *new_index = line->start_index + line->length;
-
-  *new_trailing = 0;
-
-  if (*new_index == line->start_index + line->length && line->length > 0)
-    {
-      int log_pos;
-
-      start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
-      log_pos = start_offset + pango_utf8_strlen (layout->text + line->start_index, line->length);
-      do
-        {
-          log_pos--;
-          *new_index = g_utf8_prev_char (layout->text + *new_index) - layout->text;
-          (*new_trailing)++;
-        }
-      while (log_pos > start_offset && !layout->log_attrs[log_pos].is_cursor_position);
-    }
-
-  g_array_unref (cursors);
-}
-
-/**
- * pango_layout_xy_to_index:
- * @layout: a `PangoLayout`
- * @x: the X offset (in Pango units) from the left edge of the layout
- * @y: the Y offset (in Pango units) from the top edge of the layout
- * @index_: (out): location to store calculated byte index
- * @trailing: (out): location to store a integer indicating where
- *   in the grapheme the user clicked. It will either be zero, or the
- *   number of characters in the grapheme. 0 represents the leading edge
- *   of the grapheme.
- *
- * Converts from X and Y position within a layout to the byte index to the
- * character at that logical position.
- *
- * If the Y position is not inside the layout, the closest position is
- * chosen (the position will be clamped inside the layout). If the X position
- * is not within the layout, then the start or the end of the line is
- * chosen as described for [method@Pango.LayoutLine.x_to_index]. If either
- * the X or Y positions were not inside the layout, then the function returns
- * %FALSE; on an exact hit, it returns %TRUE.
- *
- * Return value: %TRUE if the coordinates were inside text, %FALSE otherwise
- */
-gboolean
-pango_layout_xy_to_index (PangoLayout *layout,
-                          int          x,
-                          int          y,
-                          int         *index,
-                          gint        *trailing)
-{
-  PangoLayoutIter iter;
-  PangoLayoutLine *prev_line = NULL;
-  PangoLayoutLine *found = NULL;
-  int found_line_x = 0;
-  int prev_last = 0;
-  int prev_line_x = 0;
-  gboolean retval = FALSE;
-  gboolean outside = FALSE;
-
-  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
-
-  _pango_layout_get_iter (layout, &iter);
-
-  do
-    {
-      PangoRectangle line_logical;
-      int first_y, last_y;
-
-      g_assert (!ITER_IS_INVALID (&iter));
-
-      pango_layout_iter_get_line_extents (&iter, NULL, &line_logical);
-      pango_layout_iter_get_line_yrange (&iter, &first_y, &last_y);
-
-      if (y < first_y)
-        {
-          if (prev_line && y < (prev_last + (first_y - prev_last) / 2))
-            {
-              found = prev_line;
-              found_line_x = prev_line_x;
-            }
-          else
-            {
-              if (prev_line == NULL)
-                outside = TRUE; /* off the top */
-
-              found = _pango_layout_iter_get_line (&iter);
-              found_line_x = x - line_logical.x;
-            }
-        }
-      else if (y >= first_y &&
-               y < last_y)
-        {
-          found = _pango_layout_iter_get_line (&iter);
-          found_line_x = x - line_logical.x;
-        }
-
-      prev_line = _pango_layout_iter_get_line (&iter);
-      prev_last = last_y;
-      prev_line_x = x - line_logical.x;
-
-      if (found != NULL)
-        break;
-    }
-  while (pango_layout_iter_next_line (&iter));
-
-  _pango_layout_iter_destroy (&iter);
-
-  if (found == NULL)
-    {
-      /* Off the bottom of the layout */
-      outside = TRUE;
-
-      found = prev_line;
-      found_line_x = prev_line_x;
-    }
-
-  retval = pango_layout_line_x_to_index (found,
-                                         found_line_x,
-                                         index, trailing);
-
-  if (outside)
-    retval = FALSE;
-
-  return retval;
-}
-
-/**
- * pango_layout_index_to_pos:
- * @layout: a `PangoLayout`
- * @index_: byte index within @layout
- * @pos: (out): rectangle in which to store the position of the grapheme
- *
- * Converts from an index within a `PangoLayout` to the onscreen position
- * corresponding to the grapheme at that index.
- *
- * The return value is represented as rectangle. Note that `pos->x` is
- * always the leading edge of the grapheme and `pos->x + pos->width` the
- * trailing edge of the grapheme. If the directionality of the grapheme
- * is right-to-left, then `pos->width` will be negative.
- */
-void
-pango_layout_index_to_pos (PangoLayout    *layout,
-                           int             index,
-                           PangoRectangle *pos)
-{
-  PangoRectangle line_logical_rect = { 0, };
-  PangoRectangle run_logical_rect = { 0, };
-  PangoLayoutIter iter;
-  PangoLayoutLine *layout_line = NULL;
-  int x_pos;
-
-  g_return_if_fail (layout != NULL);
-  g_return_if_fail (index >= 0);
-  g_return_if_fail (pos != NULL);
-
-  _pango_layout_get_iter (layout, &iter);
-
-  if (!ITER_IS_INVALID (&iter))
-    {
-      while (TRUE)
-        {
-          PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (&iter);
-
-          if (tmp_line->start_index > index)
-            {
-              /* index is in the paragraph delimiters, move to
-               * end of previous line
-               *
-               * This shouldn’t occur in the first loop iteration as the first
-               * line’s start_index should always be 0.
-               */
-              g_assert (layout_line != NULL);
-              index = layout_line->start_index + layout_line->length;
-              break;
-            }
-
-          pango_layout_iter_get_line_extents (&iter, NULL, &line_logical_rect);
-
-          layout_line = tmp_line;
-
-          if (layout_line->start_index + layout_line->length >= index)
-            {
-              do
-                {
-                  PangoLayoutRun *run = _pango_layout_iter_get_run (&iter);
-
-                  pango_layout_iter_get_run_extents (&iter, NULL, &run_logical_rect);
-
-                  if (!run)
-                    break;
-
-                  if (run->item->offset <= index && index < run->item->offset + run->item->length)
-                    break;
-                 }
-               while (pango_layout_iter_next_run (&iter));
-
-              if (layout_line->start_index + layout_line->length > index)
-                break;
-            }
-
-          if (!pango_layout_iter_next_line (&iter))
-            {
-              index = layout_line->start_index + layout_line->length;
-              break;
-            }
-        }
-
-      pos->y = run_logical_rect.y;
-      pos->height = run_logical_rect.height;
-
-      pango_layout_line_index_to_x (layout_line, index, 0, &x_pos);
-      pos->x = line_logical_rect.x + x_pos;
-
-      if (index < layout_line->start_index + layout_line->length)
-        {
-          pango_layout_line_index_to_x (layout_line, index, 1, &x_pos);
-          pos->width = (line_logical_rect.x + x_pos) - pos->x;
-        }
-      else
-        pos->width = 0;
-    }
-
-  _pango_layout_iter_destroy (&iter);
-}
-
-static PangoLayoutRun *
-pango_layout_line_get_run (PangoLayoutLine *line,
-                           int              index)
-{
-  GSList *run_list;
-
-  run_list = line->runs;
-  while (run_list)
-    {
-      PangoLayoutRun *run = run_list->data;
-
-      if (run->item->offset <= index && run->item->offset + run->item->length > index)
-        return run;
-
-      run_list = run_list->next;
-    }
-
-  return  NULL;
-}
-
-static int
-pango_layout_line_get_char_level (PangoLayoutLine *line,
-                                  int              index)
-{
-  PangoLayoutRun *run;
-
-  run = pango_layout_line_get_run (line, index);
-
-  if (run)
-    return run->item->analysis.level;
-
-  return 0;
-}
-
-static PangoDirection
-pango_layout_line_get_char_direction (PangoLayoutLine *layout_line,
-                                      int              index)
-{
-   return pango_layout_line_get_char_level (layout_line, index) % 2
-          ? PANGO_DIRECTION_RTL
-          : PANGO_DIRECTION_LTR;
-}
-
-/**
- * pango_layout_get_direction:
- * @layout: a `PangoLayout`
- * @index: the byte index of the char
- *
- * Gets the text direction at the given character position in @layout.
- *
- * Returns: the text direction at @index
- *
- * Since: 1.46
- */
-PangoDirection
-pango_layout_get_direction (PangoLayout *layout,
-                            int          index)
-{
-  PangoLayoutLine *line;
-
-  line = pango_layout_index_to_line_and_extents (layout, index, NULL, NULL);
-
-  if (line)
-    return pango_layout_line_get_char_direction (line, index);
-
-  return PANGO_DIRECTION_LTR;
-}
-
-/**
- * pango_layout_get_cursor_pos:
- * @layout: a `PangoLayout`
- * @index_: the byte index of the cursor
- * @strong_pos: (out) (optional): location to store the strong cursor position
- * @weak_pos: (out) (optional): location to store the weak cursor position
- *
- * Given an index within a layout, determines the positions that of the
- * strong and weak cursors if the insertion point is at that index.
- *
- * The position of each cursor is stored as a zero-width rectangle
- * with the height of the run extents.
- *
- * <picture>
- *   <source srcset="cursor-positions-dark.png" media="(prefers-color-scheme: dark)">
- *   <img alt="Cursor positions" src="cursor-positions-light.png">
- * </picture>
- *
- * The strong cursor location is the location where characters of the
- * directionality equal to the base direction of the layout are inserted.
- * The weak cursor location is the location where characters of the
- * directionality opposite to the base direction of the layout are inserted.
- *
- * The following example shows text with both a strong and a weak cursor.
- *
- * <picture>
- *   <source srcset="split-cursor-dark.png" media="(prefers-color-scheme: dark)">
- *   <img alt="Strong and weak cursors" src="split-cursor-light.png">
- * </picture>
- *
- * The strong cursor has a little arrow pointing to the right, the weak
- * cursor to the left. Typing a 'c' in this situation will insert the
- * character after the 'b', and typing another Hebrew character, like 'ג',
- * will insert it at the end.
- */
-void
-pango_layout_get_cursor_pos (PangoLayout    *layout,
-                             int             index,
-                             PangoRectangle *strong_pos,
-                             PangoRectangle *weak_pos)
-{
-  PangoDirection dir1, dir2;
-  int level1, level2;
-  PangoRectangle line_rect = { 666, };
-  PangoRectangle run_rect = { 666, };
-  PangoLayoutLine *layout_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, &run_rect);
-
-  g_assert (index >= layout_line->start_index);
-
-  /* Examine the trailing edge of the character before the cursor */
-  if (index == layout_line->start_index)
-    {
-      dir1 = layout_line->resolved_dir;
-      level1 = dir1 == PANGO_DIRECTION_LTR ? 0 : 1;
-      if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
-        x1_trailing = 0;
-      else
-        x1_trailing = line_rect.width;
-    }
-  else
-    {
-      gint prev_index = g_utf8_prev_char (layout->text + index) - layout->text;
-      level1 = pango_layout_line_get_char_level (layout_line, prev_index);
-      dir1 = level1 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
-      pango_layout_line_index_to_x (layout_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)
-    {
-      dir2 = layout_line->resolved_dir;
-      level2 = dir2 == PANGO_DIRECTION_LTR ? 0 : 1;
-      if (layout_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);
-      level2 = pango_layout_line_get_char_level (layout_line, index);
-      dir2 = level2 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
-    }
-
-  if (strong_pos)
-    {
-      strong_pos->x = line_rect.x;
-
-      if (dir1 == layout_line->resolved_dir &&
-          (dir2 != dir1 || level1 < level2))
-        strong_pos->x += x1_trailing;
-      else
-        strong_pos->x += x2;
-
-      strong_pos->y = run_rect.y;
-      strong_pos->width = 0;
-      strong_pos->height = run_rect.height;
-    }
-
-  if (weak_pos)
-    {
-      weak_pos->x = line_rect.x;
-
-      if (dir1 == layout_line->resolved_dir &&
-          (dir2 != dir1 || level1 < level2))
-        weak_pos->x += x2;
-      else
-        weak_pos->x += x1_trailing;
-
-      weak_pos->y = run_rect.y;
-      weak_pos->width = 0;
-      weak_pos->height = run_rect.height;
-    }
-}
-
-/**
- * pango_layout_get_caret_pos:
- * @layout: a `PangoLayout`
- * @index_: the byte index of the cursor
- * @strong_pos: (out) (optional): location to store the strong cursor position
- * @weak_pos: (out) (optional): location to store the weak cursor position
- *
- * Given an index within a layout, determines the positions that of the
- * strong and weak cursors if the insertion point is at that index.
- *
- * This is a variant of [method@Pango.Layout.get_cursor_pos] that applies
- * font metric information about caret slope and offset to the positions
- * it returns.
- *
- * <picture>
- *   <source srcset="caret-metrics-dark.png" media="(prefers-color-scheme: dark)">
- *   <img alt="Caret metrics" src="caret-metrics-light.png">
- * </picture>
- *
- * Since: 1.50
- */
-void
-pango_layout_get_caret_pos (PangoLayout    *layout,
-                            int             index,
-                            PangoRectangle *strong_pos,
-                            PangoRectangle *weak_pos)
-{
-  PangoLayoutLine *line;
-  PangoLayoutRun *run;
-  hb_font_t *hb_font;
-  hb_position_t caret_offset, caret_run, caret_rise, descender;
-
-  pango_layout_get_cursor_pos (layout, index, strong_pos, weak_pos);
-
-  /* FIXME: not very efficient to re-iterate here */
-  line = pango_layout_index_to_line_and_extents (layout, index, NULL, NULL);
-  run = pango_layout_line_get_run (line, index);
-  if (!run)
-    run = pango_layout_line_get_run (line, index - 1);
-
-  if (!run)
-    return;
-
-  hb_font = pango_font_get_hb_font (run->item->analysis.font);
-
-  if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, &caret_rise) &&
-      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, &caret_run) &&
-      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, &caret_offset) &&
-      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &descender))
-    {
-      double slope_inv;
-      int x_scale, y_scale;
-
-      if (strong_pos)
-        strong_pos->x += caret_offset;
-
-      if (weak_pos)
-        weak_pos->x += caret_offset;
-
-      if (caret_rise == 0)
-        return;
-
-      hb_font_get_scale (hb_font, &x_scale, &y_scale);
-      slope_inv = (caret_run * y_scale) / (double) (caret_rise * x_scale);
-
-      if (strong_pos)
-        {
-          strong_pos->x += descender * slope_inv;
-          strong_pos->width = strong_pos->height * slope_inv;
-          if (slope_inv < 0)
-            strong_pos->x -= strong_pos->width;
-        }
-
-      if (weak_pos)
-        {
-          weak_pos->x += descender * slope_inv;
-          weak_pos->width = weak_pos->height * slope_inv;
-          if (slope_inv < 0)
-            weak_pos->x -= weak_pos->width;
-        }
-    }
-}
-
-static inline int
-direction_simple (PangoDirection d)
-{
-  switch (d)
-    {
-    case PANGO_DIRECTION_LTR :
-    case PANGO_DIRECTION_WEAK_LTR :
-    case PANGO_DIRECTION_TTB_RTL :
-      return 1;
-    case PANGO_DIRECTION_RTL :
-    case PANGO_DIRECTION_WEAK_RTL :
-    case PANGO_DIRECTION_TTB_LTR :
-      return -1;
-    case PANGO_DIRECTION_NEUTRAL :
-      return 0;
-    default:
-      break;
-    }
-  /* not reached */
-  return 0;
-}
-
-static PangoAlignment
-get_alignment (PangoLayout     *layout,
-               PangoLayoutLine *line)
-{
-  PangoAlignment alignment = layout->alignment;
-
-  if (alignment != PANGO_ALIGN_CENTER && line->layout->auto_dir &&
-      direction_simple (line->resolved_dir) ==
-      -direction_simple (pango_context_get_base_dir (layout->context)))
-    {
-      if (alignment == PANGO_ALIGN_LEFT)
-        alignment = PANGO_ALIGN_RIGHT;
-      else if (alignment == PANGO_ALIGN_RIGHT)
-        alignment = PANGO_ALIGN_LEFT;
-    }
-
-  return alignment;
-}
-
-static void
-get_x_offset (PangoLayout     *layout,
-              PangoLayoutLine *line,
-              int              layout_width,
-              int              line_width,
-              int             *x_offset)
-{
-  PangoAlignment alignment = get_alignment (layout, line);
-
-  /* Alignment */
-  if (layout_width == 0)
-    *x_offset = 0;
-  else if (alignment == PANGO_ALIGN_RIGHT)
-    *x_offset = layout_width - line_width;
-  else if (alignment == PANGO_ALIGN_CENTER) {
-    *x_offset = (layout_width - line_width) / 2;
-    /* hinting */
-    if (((layout_width | line_width) & (PANGO_SCALE - 1)) == 0)
-      {
-        *x_offset = PANGO_UNITS_ROUND (*x_offset);
-      }
-  } else
-    *x_offset = 0;
-
-  /* Indentation */
-
-  /* For center, we ignore indentation; I think I've seen word
-   * processors that still do the indentation here as if it were
-   * indented left/right, though we can't sensibly do that without
-   * knowing whether left/right is the "normal" thing for this text
-   */
-
-  if (alignment == PANGO_ALIGN_CENTER)
-    return;
-
-  if (line->is_paragraph_start)
-    {
-      if (layout->indent > 0)
-        {
-          if (alignment == PANGO_ALIGN_LEFT)
-            *x_offset += layout->indent;
-          else
-            *x_offset -= layout->indent;
-        }
-    }
-  else
-    {
-      if (layout->indent < 0)
-        {
-          if (alignment == PANGO_ALIGN_LEFT)
-            *x_offset -= layout->indent;
-          else
-            *x_offset += layout->indent;
-        }
-    }
-}
-
-static void
-pango_layout_line_get_extents_and_height (PangoLayoutLine *line,
-                                          PangoRectangle *ink,
-                                          PangoRectangle *logical,
-                                          int            *height);
-static void
-get_line_extents_layout_coords (PangoLayout     *layout,
-                                PangoLayoutLine *line,
-                                int              layout_width,
-                                int              y_offset,
-                                int             *baseline,
-                                PangoRectangle  *line_ink_layout,
-                                PangoRectangle  *line_logical_layout)
-{
-  int x_offset;
-  /* 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);
-
-  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 = 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 = new_baseline + line_logical.y;
-    }
-
-  if (baseline)
-    *baseline = new_baseline;
-}
-
-/* if non-NULL line_extents returns a list of line extents
- * in layout coordinates
- */
-static void
-pango_layout_get_extents_internal (PangoLayout    *layout,
-                                   PangoRectangle *ink_rect,
-                                   PangoRectangle *logical_rect,
-                                   Extents        **line_extents)
-{
-  GSList *line_list;
-  int y_offset = 0;
-  int width;
-  gboolean need_width = FALSE;
-  int line_index = 0;
-  int baseline;
-
-  g_return_if_fail (layout != NULL);
-
-  pango_layout_check_lines (layout);
-
-  if (ink_rect && layout->ink_rect_cached)
-    {
-      *ink_rect = layout->ink_rect;
-      ink_rect = NULL;
-    }
-  if (logical_rect && layout->logical_rect_cached)
-    {
-      *logical_rect = layout->logical_rect;
-      logical_rect = NULL;
-    }
-  if (!ink_rect && !logical_rect && !line_extents)
-    return;
-
-  /* When we are not wrapping, we need the overall width of the layout to
-   * figure out the x_offsets of each line. However, we only need the
-   * x_offsets if we are computing the ink_rect or individual line extents.
-   */
-  width = layout->width;
-
-  if (layout->auto_dir)
-    {
-      /* If one of the lines of the layout is not left aligned, then we need
-       * the width of the layout to calculate line x-offsets; this requires
-       * looping through the lines for layout->auto_dir.
-       */
-      line_list = layout->lines;
-      while (line_list && !need_width)
-        {
-          PangoLayoutLine *line = line_list->data;
-
-          if (get_alignment (layout, line) != PANGO_ALIGN_LEFT)
-            need_width = TRUE;
-
-          line_list = line_list->next;
-        }
-    }
-  else if (layout->alignment != PANGO_ALIGN_LEFT)
-    need_width = TRUE;
-
-  if (width == -1 && need_width && (ink_rect || line_extents))
-    {
-      PangoRectangle overall_logical;
-
-      pango_layout_get_extents_internal (layout, NULL, &overall_logical, NULL);
-      width = overall_logical.width;
-    }
-
-  if (logical_rect)
-    {
-      logical_rect->x = 0;
-      logical_rect->y = 0;
-      logical_rect->width = 0;
-      logical_rect->height = 0;
-    }
-
-
-  if (line_extents && layout->line_count > 0)
-    {
-      *line_extents = g_malloc (sizeof (Extents) * layout->line_count);
-    }
-
-  baseline = 0;
-  line_list = layout->lines;
-  while (line_list)
-    {
-      PangoLayoutLine *line = line_list->data;
-      /* Line extents in layout coords (origin at 0,0 of the layout) */
-      PangoRectangle line_ink_layout;
-      PangoRectangle line_logical_layout;
-
-      int new_pos;
-
-      /* This block gets the line extents in layout coords */
-      {
-        get_line_extents_layout_coords (layout, line,
-                                        width, y_offset,
-                                        &baseline,
-                                        ink_rect ? &line_ink_layout : NULL,
-                                        &line_logical_layout);
-
-        if (line_extents && layout->line_count > 0)
-          {
-            Extents *ext = &(*line_extents)[line_index];
-            ext->baseline = baseline;
-            ext->ink_rect = line_ink_layout;
-            ext->logical_rect = line_logical_layout;
-          }
-      }
-
-      if (ink_rect)
-        {
-          /* Compute the union of the current ink_rect with
-           * line_ink_layout
-           */
-
-          if (line_list == layout->lines)
-            {
-              *ink_rect = line_ink_layout;
-            }
-          else
-            {
-              new_pos = MIN (ink_rect->x, line_ink_layout.x);
-              ink_rect->width =
-                MAX (ink_rect->x + ink_rect->width,
-                     line_ink_layout.x + line_ink_layout.width) - new_pos;
-              ink_rect->x = new_pos;
-
-              new_pos = MIN (ink_rect->y, line_ink_layout.y);
-              ink_rect->height =
-                MAX (ink_rect->y + ink_rect->height,
-                     line_ink_layout.y + line_ink_layout.height) - new_pos;
-              ink_rect->y = new_pos;
-            }
-        }
-
-      if (logical_rect)
-        {
-          if (layout->width == -1)
-            {
-              /* When no width is set on layout, we can just compute the max of the
-               * line lengths to get the horizontal extents ... logical_rect.x = 0.
-               */
-              logical_rect->width = MAX (logical_rect->width, line_logical_layout.width);
-            }
-          else
-            {
-              /* When a width is set, we have to compute the union of the horizontal
-               * extents of all the lines.
-               */
-              if (line_list == layout->lines)
-                {
-                  logical_rect->x = line_logical_layout.x;
-                  logical_rect->width = line_logical_layout.width;
-                }
-              else
-                {
-                  new_pos = MIN (logical_rect->x, line_logical_layout.x);
-                  logical_rect->width =
-                    MAX (logical_rect->x + logical_rect->width,
-                         line_logical_layout.x + line_logical_layout.width) - new_pos;
-                  logical_rect->x = new_pos;
-
-                }
-            }
-
-          logical_rect->height = line_logical_layout.y + line_logical_layout.height - logical_rect->y;
-        }
-
-      y_offset = line_logical_layout.y + line_logical_layout.height + layout->spacing;
-      line_list = line_list->next;
-      line_index ++;
-    }
-
-  if (ink_rect)
-    {
-      layout->ink_rect = *ink_rect;
-      layout->ink_rect_cached = TRUE;
-    }
-  if (logical_rect)
-    {
-      layout->logical_rect = *logical_rect;
-      layout->logical_rect_cached = TRUE;
-    }
-}
-
-/**
- * pango_layout_get_extents:
- * @layout: a `PangoLayout`
- * @ink_rect: (out) (optional): rectangle used to store the extents of the
- *   layout as drawn
- * @logical_rect: (out) (optional):rectangle used to store the logical
- *   extents of the layout
- *
- * Computes the logical and ink extents of @layout.
- *
- * Logical extents are usually what you want for positioning things. Note
- * that both extents may have non-zero x and y. You may want to use those
- * to offset where you render the layout. Not doing that is a very typical
- * bug that shows up as right-to-left layouts not being correctly positioned
- * in a layout with a set width.
- *
- * The extents are given in layout coordinates and in Pango units; layout
- * coordinates begin at the top left corner of the layout.
- */
-void
-pango_layout_get_extents (PangoLayout    *layout,
-                          PangoRectangle *ink_rect,
-                          PangoRectangle *logical_rect)
-{
-  g_return_if_fail (layout != NULL);
-
-  pango_layout_get_extents_internal (layout, ink_rect, logical_rect, NULL);
-}
-
-/**
- * pango_layout_get_pixel_extents:
- * @layout: a `PangoLayout`
- * @ink_rect: (out) (optional): rectangle used to store the extents of the
- *   layout as drawn
- * @logical_rect: (out) (optional): rectangle used to store the logical
- *   extents of the layout
- *
- * Computes the logical and ink extents of @layout in device units.
- *
- * This function just calls [method@Pango.Layout.get_extents] followed by
- * two [func@extents_to_pixels] calls, rounding @ink_rect and @logical_rect
- * such that the rounded rectangles fully contain the unrounded one (that is,
- * passes them as first argument to [func@Pango.extents_to_pixels]).
- */
-void
-pango_layout_get_pixel_extents (PangoLayout    *layout,
-                                PangoRectangle *ink_rect,
-                                PangoRectangle *logical_rect)
-{
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-  pango_layout_get_extents (layout, ink_rect, logical_rect);
-  pango_extents_to_pixels (ink_rect, NULL);
-  pango_extents_to_pixels (logical_rect, NULL);
-}
-
-/**
- * pango_layout_get_size:
- * @layout: a `PangoLayout`
- * @width: (out) (optional): location to store the logical width
- * @height: (out) (optional): location to store the logical height
- *
- * Determines the logical width and height of a `PangoLayout` in Pango
- * units.
- *
- * This is simply a convenience function around [method@Pango.Layout.get_extents].
- */
-void
-pango_layout_get_size (PangoLayout *layout,
-                       int         *width,
-                       int         *height)
-{
-  PangoRectangle logical_rect;
-
-  pango_layout_get_extents (layout, NULL, &logical_rect);
-
-  if (width)
-    *width = logical_rect.width;
-  if (height)
-    *height = logical_rect.height;
-}
-
-/**
- * pango_layout_get_pixel_size:
- * @layout: a `PangoLayout`
- * @width: (out) (optional): location to store the logical width
- * @height: (out) (optional): location to store the logical height
- *
- * Determines the logical width and height of a `PangoLayout` in device
- * units.
- *
- * [method@Pango.Layout.get_size] returns the width and height
- * scaled by %PANGO_SCALE. This is simply a convenience function
- * around [method@Pango.Layout.get_pixel_extents].
- */
-void
-pango_layout_get_pixel_size (PangoLayout *layout,
-                             int         *width,
-                             int         *height)
-{
-  PangoRectangle logical_rect;
-
-  pango_layout_get_extents_internal (layout, NULL, &logical_rect, NULL);
-  pango_extents_to_pixels (&logical_rect, NULL);
-
-  if (width)
-    *width = logical_rect.width;
-  if (height)
-    *height = logical_rect.height;
-}
-
-/**
- * pango_layout_get_baseline:
- * @layout: a `PangoLayout`
- *
- * Gets the Y position of baseline of the first line in @layout.
- *
- * Return value: baseline of first line, from top of @layout
- *
- * Since: 1.22
- */
-int
-pango_layout_get_baseline (PangoLayout *layout)
-{
-  int baseline;
-  Extents *extents = NULL;
-
-  /* XXX this is kinda inefficient */
-  pango_layout_get_extents_internal (layout, NULL, NULL, &extents);
-  baseline = extents ? extents[0].baseline : 0;
-
-  g_free (extents);
-
-  return baseline;
-}
-
-static void
-pango_layout_clear_lines (PangoLayout *layout)
-{
-  if (layout->lines)
-    {
-      GSList *tmp_list = layout->lines;
-      while (tmp_list)
-        {
-          PangoLayoutLine *line = tmp_list->data;
-          tmp_list = tmp_list->next;
-
-          line->layout = NULL;
-          pango_layout_line_unref (line);
-        }
-
-      g_slist_free (layout->lines);
-      layout->lines = NULL;
-      layout->line_count = 0;
-    }
-
-  layout->unknown_glyphs_count = -1;
-  layout->logical_rect_cached = FALSE;
-  layout->ink_rect_cached = FALSE;
-  layout->is_ellipsized = FALSE;
-  layout->is_wrapped = FALSE;
-}
-
-static void
-pango_layout_line_leaked (PangoLayoutLine *line)
-{
-  PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
-
-  private->cache_status = LEAKED;
-
-  if (line->layout)
-    {
-      line->layout->logical_rect_cached = FALSE;
-      line->layout->ink_rect_cached = FALSE;
-    }
-}
-
-
-/*****************
- * Line Breaking *
- *****************/
-
-static void shape_tab (PangoLayoutLine  *line,
-                       LastTabState     *tab_state,
-                       ItemProperties   *properties,
-                       int               current_width,
-                       PangoItem        *item,
-                       PangoGlyphString *glyphs);
-
-static void
-free_run (PangoLayoutRun *run, gpointer data)
-{
-  gboolean free_item = data != NULL;
-  if (free_item)
-    pango_item_free (run->item);
-
-  pango_glyph_string_free (run->glyphs);
-  g_slice_free (PangoLayoutRun, run);
-}
-
-static PangoItem *
-uninsert_run (PangoLayoutLine *line)
-{
-  PangoLayoutRun *run;
-  PangoItem *item;
-
-  GSList *tmp_node = line->runs;
-
-  run = tmp_node->data;
-  item = run->item;
-
-  line->runs = tmp_node->next;
-  line->length -= item->length;
-
-  g_slist_free_1 (tmp_node);
-  free_run (run, (gpointer)FALSE);
-
-  return item;
-}
-
-static void
-ensure_tab_width (PangoLayout *layout)
-{
-  if (layout->tab_width == -1)
-    {
-      /* Find out how wide 8 spaces are in the context's default
-       * font. Utter performance killer. :-(
-       */
-      PangoGlyphString *glyphs = pango_glyph_string_new ();
-      PangoItem *item;
-      GList *items;
-      PangoAttribute *attr;
-      PangoAttrList *layout_attrs;
-      PangoAttrList tmp_attrs;
-      PangoFontDescription *font_desc = pango_font_description_copy_static 
(pango_context_get_font_description (layout->context));
-      PangoLanguage *language = NULL;
-      PangoShapeFlags shape_flags = PANGO_SHAPE_NONE;
-
-      if (pango_context_get_round_glyph_positions (layout->context))
-        shape_flags |= PANGO_SHAPE_ROUND_POSITIONS;
-
-      layout_attrs = pango_layout_get_effective_attributes (layout);
-      if (layout_attrs)
-        {
-          PangoAttrIterator iter;
-
-          _pango_attr_list_get_iterator (layout_attrs, &iter);
-          pango_attr_iterator_get_font (&iter, font_desc, &language, NULL);
-          _pango_attr_iterator_destroy (&iter);
-        }
-
-      _pango_attr_list_init (&tmp_attrs);
-
-      attr = pango_attr_font_desc_new (font_desc);
-      pango_font_description_free (font_desc);
-      pango_attr_list_insert_before (&tmp_attrs, attr);
-
-      if (language)
-        {
-          attr = pango_attr_language_new (language);
-          pango_attr_list_insert_before (&tmp_attrs, attr);
-        }
-
-      items = pango_itemize (layout->context,
-                             pango_context_get_base_dir (layout->context),
-                             " ", 0, 1, &tmp_attrs);
-
-      if (layout_attrs != layout->attrs)
-        {
-          pango_attr_list_unref (layout_attrs);
-          layout_attrs = NULL;
-        }
-      _pango_attr_list_destroy (&tmp_attrs);
-
-      item = items->data;
-      pango_shape ("        ", 8, "        ", 8, &item->analysis, glyphs, shape_flags);
-
-      pango_item_free (item);
-      g_list_free (items);
-
-      layout->tab_width = pango_glyph_string_get_width (glyphs);
-
-      pango_glyph_string_free (glyphs);
-
-      /* We need to make sure the tab_width is > 0 so finding tab positions
-       * terminates. This check should be necessary only under extreme
-       * problems with the font.
-       */
-      if (layout->tab_width <= 0)
-        layout->tab_width = 50 * PANGO_SCALE; /* pretty much arbitrary */
-    }
-}
-
-static void
-get_tab_pos (PangoLayoutLine *line,
-             int              index,
-             int             *tab_pos,
-             PangoTabAlign   *alignment,
-             gunichar        *decimal,
-             gboolean        *is_default)
-{
-  PangoLayout *layout = line->layout;
-  int n_tabs;
-  gboolean in_pixels;
-  int offset = 0;
-
-  if (layout->alignment != PANGO_ALIGN_CENTER)
-    {
-      if (line->is_paragraph_start && layout->indent >= 0)
-        offset = layout->indent;
-      else if (!line->is_paragraph_start && layout->indent < 0)
-        offset = - layout->indent;
-    }
-
-  if (layout->tabs)
-    {
-      n_tabs = pango_tab_array_get_size (layout->tabs);
-      in_pixels = pango_tab_array_get_positions_in_pixels (layout->tabs);
-      *is_default = FALSE;
-    }
-  else
-    {
-      n_tabs = 0;
-      in_pixels = FALSE;
-      *is_default = TRUE;
-    }
-
-  if (index < n_tabs)
-    {
-      pango_tab_array_get_tab (layout->tabs, index, alignment, tab_pos);
-
-      if (in_pixels)
-        *tab_pos *= PANGO_SCALE;
-
-      *decimal = pango_tab_array_get_decimal_point (layout->tabs, index);
-    }
-  else if (n_tabs > 0)
-    {
-      /* Extrapolate tab position, repeating the last tab gap to infinity. */
-      int last_pos = 0;
-      int next_to_last_pos = 0;
-      int tab_width;
-
-      pango_tab_array_get_tab (layout->tabs, n_tabs - 1, alignment, &last_pos);
-      *decimal = pango_tab_array_get_decimal_point (layout->tabs, n_tabs - 1);
-
-      if (n_tabs > 1)
-        pango_tab_array_get_tab (layout->tabs, n_tabs - 2, NULL, &next_to_last_pos);
-      else
-        next_to_last_pos = 0;
-
-      if (in_pixels)
-        {
-          next_to_last_pos *= PANGO_SCALE;
-          last_pos *= PANGO_SCALE;
-        }
-
-      if (last_pos > next_to_last_pos)
-        tab_width = last_pos - next_to_last_pos;
-      else
-        tab_width = layout->tab_width;
-
-      *tab_pos = last_pos + tab_width * (index - n_tabs + 1);
-    }
-  else
-    {
-      /* No tab array set, so use default tab width */
-      *tab_pos = layout->tab_width * index;
-      *alignment = PANGO_TAB_LEFT;
-      *decimal = 0;
-    }
-
-  *tab_pos -= offset;
-}
-
-static void
-ensure_decimal (PangoLayout *layout)
-{
-  if (layout->decimal == 0)
-    layout->decimal = g_utf8_get_char (localeconv ()->decimal_point);
-}
-
-struct _LastTabState {
-  PangoGlyphString *glyphs;
-  int index;
-  int width;
-  int pos;
-  PangoTabAlign align;
-  gunichar decimal;
-};
-
-static void
-shape_tab (PangoLayoutLine  *line,
-           LastTabState     *tab_state,
-           ItemProperties   *properties,
-           int               current_width,
-           PangoItem        *item,
-           PangoGlyphString *glyphs)
-{
-  int i, space_width;
-  int tab_pos;
-  PangoTabAlign tab_align;
-  gunichar tab_decimal;
-
-  pango_glyph_string_set_size (glyphs, 1);
-
-  if (properties->showing_space)
-    glyphs->glyphs[0].glyph = PANGO_GET_UNKNOWN_GLYPH ('\t');
-  else
-    glyphs->glyphs[0].glyph = PANGO_GLYPH_EMPTY;
-
-  glyphs->glyphs[0].geometry.x_offset = 0;
-  glyphs->glyphs[0].geometry.y_offset = 0;
-  glyphs->glyphs[0].attr.is_cluster_start = 1;
-  glyphs->glyphs[0].attr.is_color = 0;
-
-  glyphs->log_clusters[0] = 0;
-
-  ensure_tab_width (line->layout);
-  space_width = line->layout->tab_width / 8;
-
-  for (i = tab_state->index; ; i++)
-    {
-      gboolean is_default;
-
-      get_tab_pos (line, i, &tab_pos, &tab_align, &tab_decimal, &is_default);
-
-      /* Make sure there is at least a space-width of space between
-       * tab-aligned text and the text before it. However, only do
-       * this if no tab array is set on the layout, ie. using default
-       * tab positions. If the user has set tab positions, respect it
-       * to the pixel.
-       */
-      if (tab_pos >= current_width + (is_default ? space_width : 1))
-        {
-          glyphs->glyphs[0].geometry.width = tab_pos - current_width;
-          break;
-        }
-    }
-
-  if (tab_decimal == 0)
-    {
-      ensure_decimal (line->layout);
-      tab_decimal = line->layout->decimal;
-    }
-
-  tab_state->glyphs = glyphs;
-  tab_state->index = i;
-  tab_state->width = current_width;
-  tab_state->pos = tab_pos;
-  tab_state->align = tab_align;
-  tab_state->decimal = tab_decimal;
-}
-
-static inline gboolean
-can_break_at (PangoLayout   *layout,
-              gint           offset,
-              PangoWrapMode  wrap)
-{
-  if (offset == layout->n_chars)
-    return TRUE;
-  else if (wrap == PANGO_WRAP_CHAR)
-    return layout->log_attrs[offset].is_char_break;
-  else
-    return layout->log_attrs[offset].is_line_break;
-}
-
-static inline gboolean
-can_break_in (PangoLayout *layout,
-              int          start_offset,
-              int          num_chars,
-              gboolean     allow_break_at_start)
-{
-  int i;
-
-  for (i = allow_break_at_start ? 0 : 1; i < num_chars; i++)
-    if (can_break_at (layout, start_offset + i, layout->wrap))
-      return TRUE;
-
-  return FALSE;
-}
-
-static inline void
-distribute_letter_spacing (int  letter_spacing,
-                           int *space_left,
-                           int *space_right)
-{
-  *space_left = letter_spacing / 2;
-  /* hinting */
-  if ((letter_spacing & (PANGO_SCALE - 1)) == 0)
-    {
-      *space_left = PANGO_UNITS_ROUND (*space_left);
-    }
-  *space_right = letter_spacing - *space_left;
-}
-
-typedef enum
-{
-  BREAK_NONE_FIT,
-  BREAK_SOME_FIT,
-  BREAK_ALL_FIT,
-  BREAK_EMPTY_FIT,
-  BREAK_LINE_SEPARATOR
-} BreakResult;
-
-struct _ParaBreakState
-{
-  /* maintained per layout */
-  int line_height;              /* Estimate of height of current line; < 0 is no estimate */
-  int remaining_height;         /* Remaining height of the layout;  only defined if layout->height >= 0 */
-
-  /* maintained per paragraph */
-  PangoAttrList *attrs;         /* Attributes being used for itemization */
-  GList *items;                 /* This paragraph turned into items */
-  PangoDirection base_dir;      /* Current resolved base direction */
-  int line_of_par;              /* Line of the paragraph, starting at 1 for first line */
-
-  PangoGlyphString *glyphs;     /* Glyphs for the first item in state->items */
-  int start_offset;             /* Character offset of first item in state->items in layout->text */
-  ItemProperties properties;    /* Properties for the first item in state->items */
-  int *log_widths;              /* Logical widths for first item in state->items.. */
-  int num_log_widths;           /* Length of log_widths */
-  int log_widths_offset;        /* Offset into log_widths to the point corresponding
-                                 * to the remaining portion of the first item */
-
-  int line_start_index;         /* Start index (byte offset) of line in layout->text */
-  int line_start_offset;        /* Character offset of line in layout->text */
-
-  /* maintained per line */
-  int line_width;               /* Goal width of line currently processing; < 0 is infinite */
-  int remaining_width;          /* Amount of space remaining on line; < 0 is infinite */
-
-  int hyphen_width;             /* How much space a hyphen will take */
-
-  GList *baseline_shifts;
-
-  LastTabState last_tab;
-};
-
-static gboolean
-should_ellipsize_current_line (PangoLayout    *layout,
-                               ParaBreakState *state);
-
-static void
-get_decimal_prefix_width (PangoItem        *item,
-                          PangoGlyphString *glyphs,
-                          const char       *text,
-                          gunichar          decimal,
-                          int              *width,
-                          gboolean         *found)
-{
-  PangoGlyphItem glyph_item = { item, glyphs, 0, 0, 0 };
-  int *log_widths;
-  int i;
-  const char *p;
-
-  log_widths = g_new (int, item->num_chars);
-
-  pango_glyph_item_get_logical_widths (&glyph_item, text, log_widths);
-
-  *width = 0;
-  *found = FALSE;
-
-  for (i = 0, p = text + item->offset; i < item->num_chars; i++, p = g_utf8_next_char (p))
-    {
-      if (g_utf8_get_char (p) == decimal)
-        {
-          *width += log_widths[i] / 2;
-          *found = TRUE;
-          break;
-        }
-
-      *width += log_widths[i];
-    }
-
-  g_free (log_widths);
-}
-
-static int
-line_width (ParaBreakState  *state,
-            PangoLayoutLine *line)
-{
-  GSList *l;
-  int i;
-  int width = 0;
-
-  if (state->remaining_width > -1)
-    return state->line_width - state->remaining_width;
-
-  /* Compute the width of the line currently - inefficient, but easier
-   * than keeping the current width of the line up to date everywhere
-   */
-  for (l = line->runs; l; l = l->next)
-    {
-      PangoLayoutRun *run = l->data;
-
-      for (i = 0; i < run->glyphs->num_glyphs; i++)
-        width += run->glyphs->glyphs[i].geometry.width;
-    }
-
-  return width;
-}
-
-static PangoGlyphString *
-shape_run (PangoLayoutLine *line,
-           ParaBreakState  *state,
-           PangoItem       *item)
-{
-  PangoLayout *layout = line->layout;
-  PangoGlyphString *glyphs = pango_glyph_string_new ();
-
-  if (layout->text[item->offset] == '\t')
-    shape_tab (line, &state->last_tab, &state->properties, line_width (state, line), item, glyphs);
-  else
-    {
-      PangoShapeFlags shape_flags = PANGO_SHAPE_NONE;
-
-      if (pango_context_get_round_glyph_positions (layout->context))
-        shape_flags |= PANGO_SHAPE_ROUND_POSITIONS;
-
-      if (state->properties.shape_set)
-        _pango_shape_shape (layout->text + item->offset, item->num_chars,
-                            state->properties.shape_ink_rect, state->properties.shape_logical_rect,
-                            glyphs);
-      else
-        pango_shape_item (item,
-                          layout->text, layout->length,
-                          layout->log_attrs + state->start_offset,
-                          glyphs,
-                          shape_flags);
-
-      if (state->properties.letter_spacing)
-        {
-          PangoGlyphItem glyph_item;
-          int space_left, space_right;
-
-          glyph_item.item = item;
-          glyph_item.glyphs = glyphs;
-
-          pango_glyph_item_letter_space (&glyph_item,
-                                         layout->text,
-                                         layout->log_attrs + state->start_offset,
-                                         state->properties.letter_spacing);
-
-          distribute_letter_spacing (state->properties.letter_spacing, &space_left, &space_right);
-
-          glyphs->glyphs[0].geometry.width += space_left;
-          glyphs->glyphs[0].geometry.x_offset += space_left;
-          glyphs->glyphs[glyphs->num_glyphs - 1].geometry.width += space_right;
-        }
-
-      if (state->last_tab.glyphs != NULL)
-        {
-          int w;
-
-          g_assert (state->last_tab.glyphs->num_glyphs == 1);
-
-          /* Update the width of the current tab to position this run properly */
-
-          w = state->last_tab.pos - state->last_tab.width;
-
-          if (state->last_tab.align == PANGO_TAB_RIGHT)
-            w -= pango_glyph_string_get_width (glyphs);
-          else if (state->last_tab.align == PANGO_TAB_CENTER)
-            w -= pango_glyph_string_get_width (glyphs) / 2;
-          else if (state->last_tab.align == PANGO_TAB_DECIMAL)
-            {
-              int width;
-              gboolean found;
-
-              get_decimal_prefix_width (item, glyphs, layout->text, state->last_tab.decimal, &width, &found);
-
-              w -= width;
-            }
-
-          state->last_tab.glyphs->glyphs[0].geometry.width = MAX (w, 0);
-        }
-    }
-
-  return glyphs;
-}
-
-static void
-insert_run (PangoLayoutLine  *line,
-            ParaBreakState   *state,
-            PangoItem        *run_item,
-            PangoGlyphString *glyphs,
-            gboolean          last_run)
-{
-  PangoLayoutRun *run = g_slice_new (PangoLayoutRun);
-
-  run->item = run_item;
-
-  if (glyphs)
-    run->glyphs = glyphs;
-  else if (last_run && state->log_widths_offset == 0 &&
-           !(run_item->analysis.flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN))
-    {
-      run->glyphs = state->glyphs;
-      state->glyphs = NULL;
-    }
-  else
-    run->glyphs = shape_run (line, state, run_item);
-
-  if (last_run && state->glyphs)
-    {
-      pango_glyph_string_free (state->glyphs);
-      state->glyphs = NULL;
-    }
-
-  line->runs = g_slist_prepend (line->runs, run);
-  line->length += run_item->length;
-
-  if (state->last_tab.glyphs && run->glyphs != state->last_tab.glyphs)
-    {
-      gboolean found_decimal = FALSE;
-      int width;
-
-      /* Adjust the tab position so placing further runs will continue to
-       * maintain the tab placement. In the case of decimal tabs, we are
-       * done once we've placed the run with the decimal point.
-       */
-
-      if (state->last_tab.align == PANGO_TAB_RIGHT)
-        state->last_tab.width += pango_glyph_string_get_width (run->glyphs);
-      else if (state->last_tab.align == PANGO_TAB_CENTER)
-        state->last_tab.width += pango_glyph_string_get_width (run->glyphs) / 2;
-      else if (state->last_tab.align == PANGO_TAB_DECIMAL)
-        {
-          int width;
-
-          get_decimal_prefix_width (run->item, run->glyphs, line->layout->text, state->last_tab.decimal, 
&width, &found_decimal);
-
-          state->last_tab.width += width;
-        }
-
-      width = MAX (state->last_tab.pos - state->last_tab.width, 0);
-      state->last_tab.glyphs->glyphs[0].geometry.width = width;
-
-      if (found_decimal || width == 0)
-        state->last_tab.glyphs = NULL;
-    }
-}
-
-static gboolean
-break_needs_hyphen (PangoLayout    *layout,
-                    ParaBreakState *state,
-                    int             pos)
-{
-  return layout->log_attrs[state->start_offset + pos].break_inserts_hyphen ||
-         layout->log_attrs[state->start_offset + pos].break_removes_preceding;
-}
-
-static int
-find_hyphen_width (PangoItem *item)
-{
-  hb_font_t *hb_font;
-  hb_codepoint_t glyph;
-
-  if (!item->analysis.font)
-    return 0;
-
-  /* This is not technically correct, since
-   * a) we may end up inserting a different hyphen
-   * b) we should reshape the entire run
-   * But it is close enough in practice
-   */
-  hb_font = pango_font_get_hb_font (item->analysis.font);
-  if (hb_font_get_nominal_glyph (hb_font, 0x2010, &glyph) ||
-      hb_font_get_nominal_glyph (hb_font, '-', &glyph))
-    return hb_font_get_glyph_h_advance (hb_font, glyph);
-
-  return 0;
-}
-
-static inline void
-ensure_hyphen_width (ParaBreakState *state)
-{
-  if (state->hyphen_width < 0)
-    {
-      PangoItem *item = state->items->data;
-      state->hyphen_width = find_hyphen_width (item);
-    }
-}
-
-static int
-find_break_extra_width (PangoLayout    *layout,
-                        ParaBreakState *state,
-                        int             pos)
-{
-  /* Check whether to insert a hyphen,
-   * or whether we are breaking after one of those
-   * characters that turn into a hyphen,
-   * or after a space.
-  */
-  if (layout->log_attrs[state->start_offset + pos].break_inserts_hyphen)
-    {
-      ensure_hyphen_width (state);
-
-      if (layout->log_attrs[state->start_offset + pos].break_removes_preceding && pos > 0)
-        return state->hyphen_width - state->log_widths[state->log_widths_offset + pos - 1];
-      else
-        return state->hyphen_width;
-    }
-  else if (pos > 0 &&
-           layout->log_attrs[state->start_offset + pos - 1].is_white)
-    {
-      return - state->log_widths[state->log_widths_offset + pos - 1];
-    }
-
-  return 0;
-}
-
-#if 0
-# define DEBUG debug
-static int pango_layout_line_get_width (PangoLayoutLine *line);
-static void
-debug (const char *where, PangoLayoutLine *line, ParaBreakState *state)
-{
-  int line_width = pango_layout_line_get_width (line);
-
-  g_debug ("rem %d + line %d = %d               %s",
-           state->remaining_width,
-           line_width,
-           state->remaining_width + line_width,
-           where);
-}
-# define DEBUG1(...) g_debug (__VA_ARGS__)
-#else
-# define DEBUG(where, line, state) do { } while (0)
-# define DEBUG1(...) do { } while (0)
-#endif
-
-static inline void
-compute_log_widths (PangoLayout    *layout,
-                    ParaBreakState *state)
-{
-  PangoItem *item = state->items->data;
-  PangoGlyphItem glyph_item = { item, state->glyphs };
-
-  if (item->num_chars > state->num_log_widths)
-    {
-      state->log_widths = g_renew (int, state->log_widths, item->num_chars);
-      state->num_log_widths = item->num_chars;
-    }
-
-  pango_glyph_item_get_logical_widths (&glyph_item, layout->text, state->log_widths);
-}
-
-/* If last_tab is set, we've added a tab and remaining_width has been updated to
- * account for its origin width, which is last_tab_pos - last_tab_width. shape_run
- * updates the tab width, so we need to consider the delta when comparing
- * against remaining_width.
- */
-static int
-tab_width_change (ParaBreakState *state)
-{
-  if (state->last_tab.glyphs)
-    return state->last_tab.glyphs->glyphs[0].geometry.width - (state->last_tab.pos - state->last_tab.width);
-
-  return 0;
-}
-
-/* Tries to insert as much as possible of the item at the head of
- * state->items onto @line. Five results are possible:
- *
- *  %BREAK_NONE_FIT: Couldn't fit anything.
- *  %BREAK_SOME_FIT: The item was broken in the middle.
- *  %BREAK_ALL_FIT: Everything fit.
- *  %BREAK_EMPTY_FIT: Nothing fit, but that was ok, as we can break at the first char.
- *  %BREAK_LINE_SEPARATOR: Item begins with a line separator.
- *
- * If @force_fit is %TRUE, then %BREAK_NONE_FIT will never
- * be returned, a run will be added even if inserting the minimum amount
- * will cause the line to overflow. This is used at the start of a line
- * and until we've found at least some place to break.
- *
- * If @no_break_at_end is %TRUE, then %BREAK_ALL_FIT will never be
- * returned even everything fits; the run will be broken earlier,
- * or %BREAK_NONE_FIT returned. This is used when the end of the
- * run is not a break position.
- *
- * This function is the core of our line-breaking, and it is long and involved.
- * Here is an outline of the algorithm, without all the bookkeeping:
- *
- * if item appears to fit entirely
- *   measure it
- *   if it actually fits
- *     return BREAK_ALL_FIT
- *
- * retry_break:
- *   for each position p in the item
- *     if adding more is 'obviously' not going to help and we have a breakpoint
- *       exit the loop
- *     if p is a possible break position
- *       if p is 'obviously' going to fit
- *         bc = p
- *       else
- *         measure breaking at p (taking extra break width into account
- *         if we don't have a break candidate yet
- *           bc = p
- *         else
- *           if p is better than bc
- *             bc = p
- *
- *   if bc does not fit and we can loosen break conditions
- *     loosen break conditions and retry break
- *
- * return bc
- */
-static BreakResult
-process_item (PangoLayout     *layout,
-              PangoLayoutLine *line,
-              ParaBreakState  *state,
-              gboolean         force_fit,
-              gboolean         no_break_at_end,
-              gboolean         is_last_item)
-{
-  PangoItem *item = state->items->data;
-  gboolean shape_set = FALSE;
-  int width;
-  int extra_width;
-  int orig_extra_width;
-  int length;
-  int i;
-  int processing_new_item;
-  int num_chars;
-  int orig_width;
-  PangoWrapMode wrap;
-  int break_num_chars;
-  int break_width;
-  int break_extra_width;
-  PangoGlyphString *break_glyphs;
-  PangoFontMetrics *metrics;
-  int safe_distance;
-
-  DEBUG1 ("process item '%.*s'. Remaining width %d",
-          item->length, layout->text + item->offset,
-          state->remaining_width);
-
-  /* We don't want to shape more than necessary, so we keep the results
-   * of shaping a new item in state->glyphs, state->log_widths. Once
-   * we break off initial parts of the item, we update state->log_widths_offset
-   * to take that into account. Note that the widths we calculate from the
-   * log_widths are an approximation, because a) log_widths are just
-   * evenly divided for clusters, and b) clusters may change as we
-   * break in the middle (think ff- i).
-   *
-   * We use state->log_widths_offset != 0 to detect if we are dealing
-   * with the original item, or one that has been chopped off.
-   */
-  if (!state->glyphs)
-    {
-      pango_item_get_properties (item, &state->properties);
-      state->glyphs = shape_run (line, state, item);
-      state->log_widths_offset = 0;
-      processing_new_item = TRUE;
-    }
-  else
-    processing_new_item = FALSE;
-
-  /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 5.0;
-   * update this if that changes.
-   */
-#define LINE_SEPARATOR 0x2028
-
-  if (!layout->single_paragraph &&
-      g_utf8_get_char (layout->text + item->offset) == LINE_SEPARATOR &&
-      !should_ellipsize_current_line (layout, state))
-    {
-      insert_run (line, state, item, NULL, TRUE);
-      state->log_widths_offset += item->num_chars;
-
-      return BREAK_LINE_SEPARATOR;
-    }
-
-  if (state->remaining_width < 0 && !no_break_at_end)  /* Wrapping off */
-    {
-      insert_run (line, state, item, NULL, TRUE);
-      DEBUG1 ("no wrapping, all-fit");
-      return BREAK_ALL_FIT;
-    }
-
-  if (processing_new_item)
-    {
-      width = pango_glyph_string_get_width (state->glyphs);
-    }
-  else
-    {
-      width = 0;
-      for (i = 0; i < item->num_chars; i++)
-        width += state->log_widths[state->log_widths_offset + i];
-    }
-
-  if (layout->text[item->offset] == '\t')
-    {
-      insert_run (line, state, item, NULL, TRUE);
-      state->remaining_width -= width;
-      state->remaining_width = MAX (state->remaining_width, 0);
-
-      DEBUG1 ("tab run, all-fit");
-      return BREAK_ALL_FIT;
-    }
-
-  wrap = layout->wrap;
-
-  if (!no_break_at_end &&
-      can_break_at (layout, state->start_offset + item->num_chars, wrap))
-    {
-      if (processing_new_item)
-        {
-          compute_log_widths (layout, state);
-          processing_new_item = FALSE;
-        }
-
-      extra_width = find_break_extra_width (layout, state, item->num_chars);
-    }
-  else
-    extra_width = 0;
-
-  if ((width + extra_width <= state->remaining_width || (item->num_chars == 1 && !line->runs) ||
-      (state->last_tab.glyphs && state->last_tab.align != PANGO_TAB_LEFT)) &&
-      !no_break_at_end)
-    {
-      PangoGlyphString *glyphs;
-
-      DEBUG1 ("%d + %d <= %d", width, extra_width, state->remaining_width);
-      glyphs = shape_run (line, state, item);
-
-      width = pango_glyph_string_get_width (glyphs) + tab_width_change (state);
-
-      if (width + extra_width <= state->remaining_width || (item->num_chars == 1 && !line->runs))
-        {
-          insert_run (line, state, item, glyphs, TRUE);
-
-          state->remaining_width -= width;
-          state->remaining_width = MAX (state->remaining_width, 0);
-
-          DEBUG1 ("early accept '%.*s', all-fit, remaining %d",
-                  item->length, layout->text + item->offset,
-                  state->remaining_width);
-          return BREAK_ALL_FIT;
-        }
-
-      /* if it doesn't fit after shaping, discard and proceed to break the item */
-      pango_glyph_string_free (glyphs);
-    }
-
-  /*** From here on, we look for a way to break item ***/
-
-  orig_width = width;
-  orig_extra_width = extra_width;
-  break_width = width;
-  break_extra_width = extra_width;
-  break_num_chars = item->num_chars;
-  wrap = layout->wrap;
-  break_glyphs = NULL;
-
-  /* Add some safety margin here. If we are farther away from the end of the
-   * line than this, we don't look carefully at a break possibility.
-   */
-  metrics = pango_font_get_metrics (item->analysis.font, item->analysis.language);
-  safe_distance = pango_font_metrics_get_approximate_char_width (metrics) * 3;
-  pango_font_metrics_unref (metrics);
-
-  if (processing_new_item)
-    {
-      compute_log_widths (layout, state);
-      processing_new_item = FALSE;
-    }
-
-retry_break:
-
-  for (num_chars = 0, width = 0; num_chars < (no_break_at_end ? item->num_chars : (item->num_chars + 1)); 
num_chars++)
-    {
-      extra_width = find_break_extra_width (layout, state, num_chars);
-
-      /* We don't want to walk the entire item if we can help it, but
-       * we need to keep going at least until we've found a breakpoint
-       * that 'works' (as in, it doesn't overflow the budget we have,
-       * or there is no hope of finding a better one).
-       *
-       * We rely on the fact that MIN(width + extra_width, width) is
-       * monotonically increasing.
-       */
-
-      if (MIN (width + extra_width, width) > state->remaining_width + safe_distance &&
-          break_num_chars < item->num_chars)
-        {
-          DEBUG1 ("at %d, MIN(%d, %d + %d) > %d + MARGIN, breaking at %d",
-                  num_chars, width, extra_width, width, state->remaining_width, break_num_chars);
-          break;
-        }
-
-      /* If there are no previous runs we have to take care to grab at least one char. */
-      if (can_break_at (layout, state->start_offset + num_chars, wrap) &&
-          (num_chars > 0 || line->runs))
-        {
-          DEBUG1 ("possible breakpoint: %d, extra_width %d", num_chars, extra_width);
-          if (num_chars == 0 ||
-              width + extra_width < state->remaining_width - safe_distance)
-            {
-              DEBUG1 ("trivial accept");
-              break_num_chars = num_chars;
-              break_width = width;
-              break_extra_width = extra_width;
-            }
-          else
-            {
-              int length;
-              int new_break_width;
-              PangoItem *new_item;
-              PangoGlyphString *glyphs;
-
-              length = g_utf8_offset_to_pointer (layout->text + item->offset, num_chars) - (layout->text + 
item->offset);
-
-              if (num_chars < item->num_chars)
-                {
-                  new_item = pango_item_split (item, length, num_chars);
-
-                  if (break_needs_hyphen (layout, state, num_chars))
-                    new_item->analysis.flags |= PANGO_ANALYSIS_FLAG_NEED_HYPHEN;
-                  else
-                    new_item->analysis.flags &= ~PANGO_ANALYSIS_FLAG_NEED_HYPHEN;
-                }
-              else
-                new_item = item;
-
-              glyphs = shape_run (line, state, new_item);
-
-              new_break_width = pango_glyph_string_get_width (glyphs) + tab_width_change (state);
-
-              if (num_chars > 0 &&
-                  (item != new_item || !is_last_item) && /* We don't collapse space at the very end */
-                  layout->log_attrs[state->start_offset + num_chars - 1].is_white)
-                extra_width = - state->log_widths[state->log_widths_offset + num_chars - 1];
-              else if (item == new_item && !is_last_item &&
-                       break_needs_hyphen (layout, state, num_chars))
-                extra_width = state->hyphen_width;
-              else
-                extra_width = 0;
-
-              DEBUG1 ("measured breakpoint %d: %d, extra %d", num_chars, new_break_width, extra_width);
-
-              if (new_item != item)
-                {
-                  pango_item_free (new_item);
-                  pango_item_unsplit (item, length, num_chars);
-                }
-
-              if (break_num_chars == item->num_chars ||
-                  new_break_width + extra_width <= state->remaining_width ||
-                  new_break_width + extra_width < break_width + break_extra_width)
-                {
-                  DEBUG1 ("accept breakpoint %d: %d + %d <= %d + %d",
-                          num_chars, new_break_width, extra_width, break_width, break_extra_width);
-                  DEBUG1 ("replace bp %d by %d", break_num_chars, num_chars);
-                  break_num_chars = num_chars;
-                  break_width = new_break_width;
-                  break_extra_width = extra_width;
-
-                  if (break_glyphs)
-                    pango_glyph_string_free (break_glyphs);
-                  break_glyphs = glyphs;
-                }
-              else
-                {
-                  DEBUG1 ("ignore breakpoint %d", num_chars);
-                  pango_glyph_string_free (glyphs);
-                }
-            }
-        }
-
-      DEBUG1 ("bp now %d", break_num_chars);
-      if (num_chars < item->num_chars)
-        width += state->log_widths[state->log_widths_offset + num_chars];
-    }
-
-   if (wrap == PANGO_WRAP_WORD_CHAR && force_fit && break_width + break_extra_width > state->remaining_width)
-    {
-      /* Try again, with looser conditions */
-      DEBUG1 ("does not fit, try again with wrap-char");
-      wrap = PANGO_WRAP_CHAR;
-      break_num_chars = item->num_chars;
-      break_width = orig_width;
-      break_extra_width = orig_extra_width;
-      if (break_glyphs)
-        pango_glyph_string_free (break_glyphs);
-      break_glyphs = NULL;
-      goto retry_break;
-    }
-
-  if (force_fit || break_width + break_extra_width <= state->remaining_width)       /* Successfully broke 
the item */
-    {
-      if (state->remaining_width >= 0)
-        {
-          state->remaining_width -= break_width + break_extra_width;
-          state->remaining_width = MAX (state->remaining_width, 0);
-        }
-
-      if (break_num_chars == item->num_chars)
-        {
-          if (can_break_at (layout, state->start_offset + break_num_chars, wrap) &&
-              break_needs_hyphen (layout, state, break_num_chars))
-            item->analysis.flags |= PANGO_ANALYSIS_FLAG_NEED_HYPHEN;
-
-          insert_run (line, state, item, NULL, TRUE);
-
-          if (break_glyphs)
-            pango_glyph_string_free (break_glyphs);
-
-          DEBUG1 ("all-fit '%.*s', remaining %d",
-                  item->length, layout->text + item->offset,
-                  state->remaining_width);
-          return BREAK_ALL_FIT;
-        }
-      else if (break_num_chars == 0)
-        {
-          if (break_glyphs)
-            pango_glyph_string_free (break_glyphs);
-
-          DEBUG1 ("empty-fit, remaining %d", state->remaining_width);
-          return BREAK_EMPTY_FIT;
-        }
-      else
-        {
-          PangoItem *new_item;
-
-          length = g_utf8_offset_to_pointer (layout->text + item->offset, break_num_chars) - (layout->text + 
item->offset);
-
-          new_item = pango_item_split (item, length, break_num_chars);
-
-          insert_run (line, state, new_item, break_glyphs, FALSE);
-
-          state->log_widths_offset += break_num_chars;
-
-          /* Shaped items should never be broken */
-          g_assert (!shape_set);
-
-          DEBUG1 ("some-fit '%.*s', remaining %d",
-                  new_item->length, layout->text + new_item->offset,
-                  state->remaining_width);
-          return BREAK_SOME_FIT;
-        }
-    }
-  else
-    {
-      pango_glyph_string_free (state->glyphs);
-      state->glyphs = NULL;
-
-      if (break_glyphs)
-        pango_glyph_string_free (break_glyphs);
-
-      DEBUG1 ("none-fit, remaining %d", state->remaining_width);
-      return BREAK_NONE_FIT;
-    }
-}
-
-/* The resolved direction for the line is always one
- * of LTR/RTL; not a week or neutral directions
- */
-static void
-line_set_resolved_dir (PangoLayoutLine *line,
-                       PangoDirection   direction)
-{
-  switch (direction)
-    {
-    default:
-    case PANGO_DIRECTION_LTR:
-    case PANGO_DIRECTION_TTB_RTL:
-    case PANGO_DIRECTION_WEAK_LTR:
-    case PANGO_DIRECTION_NEUTRAL:
-      line->resolved_dir = PANGO_DIRECTION_LTR;
-      break;
-    case PANGO_DIRECTION_RTL:
-    case PANGO_DIRECTION_WEAK_RTL:
-    case PANGO_DIRECTION_TTB_LTR:
-      line->resolved_dir = PANGO_DIRECTION_RTL;
-      break;
-    }
-
-  /* The direction vs. gravity dance:
-   *    - If gravity is SOUTH, leave direction untouched.
-   *    - If gravity is NORTH, switch direction.
-   *    - If gravity is EAST, set to LTR, as
-   *      it's a clockwise-rotated layout, so the rotated
-   *      top is unrotated left.
-   *    - If gravity is WEST, set to RTL, as
-   *      it's a counter-clockwise-rotated layout, so the rotated
-   *      top is unrotated right.
-   *
-   * A similar dance is performed in pango-context.c:
-   * itemize_state_add_character().  Keep in synch.
-   */
-  switch (pango_context_get_gravity (line->layout->context))
-    {
-    default:
-    case PANGO_GRAVITY_AUTO:
-    case PANGO_GRAVITY_SOUTH:
-      break;
-    case PANGO_GRAVITY_NORTH:
-      line->resolved_dir = PANGO_DIRECTION_LTR
-                         + PANGO_DIRECTION_RTL
-                         - line->resolved_dir;
-      break;
-    case PANGO_GRAVITY_EAST:
-      /* This is in fact why deprecated TTB_RTL is LTR */
-      line->resolved_dir = PANGO_DIRECTION_LTR;
-      break;
-    case PANGO_GRAVITY_WEST:
-      /* This is in fact why deprecated TTB_LTR is RTL */
-      line->resolved_dir = PANGO_DIRECTION_RTL;
-      break;
-    }
-}
-
-static gboolean
-should_ellipsize_current_line (PangoLayout    *layout,
-                               ParaBreakState *state)
-{
-  if (G_LIKELY (layout->ellipsize == PANGO_ELLIPSIZE_NONE || layout->width < 0))
-    return FALSE;
-
-  if (layout->height >= 0)
-    {
-      /* state->remaining_height is height of layout left */
-
-      /* if we can't stuff two more lines at the current guess of line height,
-       * the line we are going to produce is going to be the last line
-       */
-      return state->line_height * 2 > state->remaining_height;
-    }
-  else
-    {
-      /* -layout->height is number of lines per paragraph to show */
-      return state->line_of_par == - layout->height;
-    }
-}
-
-static void
-add_line (PangoLayoutLine *line,
-          ParaBreakState  *state)
-{
-  PangoLayout *layout = line->layout;
-
-  /* we prepend, then reverse the list later */
-  layout->lines = g_slist_prepend (layout->lines, line);
-  layout->line_count++;
-
-  if (layout->height >= 0)
-    {
-      PangoRectangle logical_rect;
-      pango_layout_line_get_extents (line, NULL, &logical_rect);
-      state->remaining_height -= logical_rect.height;
-      state->remaining_height -= layout->spacing;
-      state->line_height = logical_rect.height;
-    }
-}
-
-static void
-process_line (PangoLayout    *layout,
-              ParaBreakState *state)
-{
-  PangoLayoutLine *line;
-
-  gboolean have_break = FALSE;      /* If we've seen a possible break yet */
-  int break_remaining_width = 0;    /* Remaining width before adding run with break */
-  int break_start_offset = 0;       /* Start offset before adding run with break */
-  GSList *break_link = NULL;        /* Link holding run before break */
-  gboolean wrapped = FALSE;         /* If we had to wrap the line */
-
-  line = pango_layout_line_new (layout);
-  line->start_index = state->line_start_index;
-  line->is_paragraph_start = state->line_of_par == 1;
-  line_set_resolved_dir (line, state->base_dir);
-
-  state->line_width = layout->width;
-  if (state->line_width >= 0 && layout->alignment != PANGO_ALIGN_CENTER)
-    {
-      if (line->is_paragraph_start && layout->indent >= 0)
-        state->line_width -= layout->indent;
-      else if (!line->is_paragraph_start && layout->indent < 0)
-        state->line_width += layout->indent;
-
-      if (state->line_width < 0)
-        state->line_width = 0;
-    }
-
-  if (G_UNLIKELY (should_ellipsize_current_line (layout, state)))
-    state->remaining_width = -1;
-  else
-    state->remaining_width = state->line_width;
-
-  state->last_tab.glyphs = NULL;
-  state->last_tab.index = 0;
-  state->last_tab.align = PANGO_TAB_LEFT;
-
-  DEBUG ("starting to fill line", line, state);
-
-  while (state->items)
-    {
-      PangoItem *item = state->items->data;
-      BreakResult result;
-      int old_num_chars;
-      int old_remaining_width;
-      gboolean first_item_in_line;
-      gboolean last_item_in_line;
-
-      old_num_chars = item->num_chars;
-      old_remaining_width = state->remaining_width;
-      first_item_in_line = line->runs == NULL;
-      last_item_in_line = state->items->next == NULL;
-
-      result = process_item (layout, line, state, !have_break, FALSE, last_item_in_line);
-
-      switch (result)
-        {
-        case BREAK_ALL_FIT:
-          if (layout->text[item->offset] != '\t' &&
-              can_break_in (layout, state->start_offset, old_num_chars, !first_item_in_line))
-            {
-              have_break = TRUE;
-              break_remaining_width = old_remaining_width;
-              break_start_offset = state->start_offset;
-              break_link = line->runs->next;
-              DEBUG1 ("all-fit, have break");
-            }
-
-          state->items = g_list_delete_link (state->items, state->items);
-          state->start_offset += old_num_chars;
-
-          break;
-
-        case BREAK_EMPTY_FIT:
-          wrapped = TRUE;
-          goto done;
-
-        case BREAK_SOME_FIT:
-          state->start_offset += old_num_chars - item->num_chars;
-          wrapped = TRUE;
-          goto done;
-
-        case BREAK_NONE_FIT:
-          /* Back up over unused runs to run where there is a break */
-          while (line->runs && line->runs != break_link)
-            {
-              PangoLayoutRun *run = line->runs->data;
-
-              /* If we uninsert the current tab run,
-               * we need to reset the tab state
-               */
-              if (run->glyphs == state->last_tab.glyphs)
-                {
-                  state->last_tab.glyphs = NULL;
-                  state->last_tab.index = 0;
-                  state->last_tab.align = PANGO_TAB_LEFT;
-                }
-
-              state->items = g_list_prepend (state->items, uninsert_run (line));
-            }
-
-          state->start_offset = break_start_offset;
-          state->remaining_width = break_remaining_width;
-          last_item_in_line = state->items->next == NULL;
-
-          /* Reshape run to break */
-          item = state->items->data;
-
-          old_num_chars = item->num_chars;
-          result = process_item (layout, line, state, TRUE, TRUE, last_item_in_line);
-          g_assert (result == BREAK_SOME_FIT || result == BREAK_EMPTY_FIT);
-
-          state->start_offset += old_num_chars - item->num_chars;
-
-          wrapped = TRUE;
-          goto done;
-
-        case BREAK_LINE_SEPARATOR:
-          state->items = g_list_delete_link (state->items, state->items);
-          state->start_offset += old_num_chars;
-          /* A line-separate is just a forced break.  Set wrapped, so we do justification */
-          wrapped = TRUE;
-          goto done;
-
-        default:
-          break;
-        }
-    }
-
- done:
-  pango_layout_line_postprocess (line, state, wrapped);
-  DEBUG1 ("line %d done. remaining %d", state->line_of_par, state->remaining_width);
-  add_line (line, state);
-  state->line_of_par++;
-  state->line_start_index += line->length;
-  state->line_start_offset = state->start_offset;
-}
-
-static void
-get_items_log_attrs (const char    *text,
-                     int            start,
-                     int            length,
-                     GList         *items,
-                     PangoAttrList *attrs,
-                     PangoLogAttr  *log_attrs,
-                     int            log_attrs_len)
-{
-  int offset = 0;
-  GList *l;
-
-  pango_default_break (text + start, length, log_attrs, log_attrs_len);
-
-  for (l = items; l; l = l->next)
-    {
-      PangoItem *item = l->data;
-      g_assert (item->offset <= start + length);
-      g_assert (item->length <= (start + length) - item->offset);
-
-      pango_tailor_break (text + item->offset,
-                          item->length,
-                          &item->analysis,
-                          -1,
-                          log_attrs + offset,
-                          item->num_chars + 1);
-
-      offset += item->num_chars;
-    }
-
-  if (attrs && items)
-    {
-      PangoItem *item = items->data;
-      pango_attr_break (text + start, length, attrs, item->offset, log_attrs, log_attrs_len);
-    }
-}
-
-static PangoAttrList *
-pango_layout_get_effective_attributes (PangoLayout *layout)
-{
-  PangoAttrList *attrs;
-
-  if (layout->attrs)
-    attrs = pango_attr_list_copy (layout->attrs);
-  else
-    attrs = NULL;
-
-  if (layout->font_desc)
-    {
-      PangoAttribute *attr = pango_attr_font_desc_new (layout->font_desc);
-
-      if (!attrs)
-        attrs = pango_attr_list_new ();
-
-      pango_attr_list_insert_before (attrs, attr);
-    }
-
-  if (layout->single_paragraph)
-    {
-      PangoAttribute *attr = pango_attr_show_new (PANGO_SHOW_LINE_BREAKS);
-
-      if (!attrs)
-        attrs = pango_attr_list_new ();
-
-      pango_attr_list_insert_before (attrs, attr);
-    }
-
-  return attrs;
-}
-
-static gboolean
-affects_itemization (PangoAttribute *attr,
-                     gpointer        data)
-{
-  switch ((int)attr->klass->type)
-    {
-    /* These affect font selection */
-    case PANGO_ATTR_LANGUAGE:
-    case PANGO_ATTR_FAMILY:
-    case PANGO_ATTR_STYLE:
-    case PANGO_ATTR_WEIGHT:
-    case PANGO_ATTR_VARIANT:
-    case PANGO_ATTR_STRETCH:
-    case PANGO_ATTR_SIZE:
-    case PANGO_ATTR_FONT_DESC:
-    case PANGO_ATTR_SCALE:
-    case PANGO_ATTR_FALLBACK:
-    case PANGO_ATTR_ABSOLUTE_SIZE:
-    case PANGO_ATTR_GRAVITY:
-    case PANGO_ATTR_GRAVITY_HINT:
-    case PANGO_ATTR_FONT_SCALE:
-    /* These need to be constant across runs */
-    case PANGO_ATTR_LETTER_SPACING:
-    case PANGO_ATTR_SHAPE:
-    case PANGO_ATTR_RISE:
-    case PANGO_ATTR_BASELINE_SHIFT:
-    case PANGO_ATTR_LINE_HEIGHT:
-    case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
-    case PANGO_ATTR_TEXT_TRANSFORM:
-      return TRUE;
-    default:
-      return FALSE;
-    }
-}
-
-static gboolean
-affects_break_or_shape (PangoAttribute *attr,
-                        gpointer        data)
-{
-  switch ((int)attr->klass->type)
-    {
-    /* Affects breaks */
-    case PANGO_ATTR_ALLOW_BREAKS:
-    case PANGO_ATTR_WORD:
-    case PANGO_ATTR_SENTENCE:
-    /* Affects shaping */
-    case PANGO_ATTR_INSERT_HYPHENS:
-    case PANGO_ATTR_FONT_FEATURES:
-    case PANGO_ATTR_SHOW:
-      return TRUE;
-    default:
-      return FALSE;
-    }
-}
-
-static void
-apply_attributes_to_items (GList         *items,
-                           PangoAttrList *attrs)
-{
-  GList *l;
-  PangoAttrIterator iter;
-
-  if (!attrs)
-    return;
-
-  _pango_attr_list_get_iterator (attrs, &iter);
-
-  for (l = items; l; l = l->next)
-    {
-      PangoItem *item = l->data;
-      pango_item_apply_attrs (item, &iter);
-    }
-
-  _pango_attr_iterator_destroy (&iter);
-}
-
-static void
-apply_attributes_to_runs (PangoLayout   *layout,
-                          PangoAttrList *attrs)
-{
-  GSList *ll;
-
-  if (!attrs)
-    return;
-
-  for (ll = layout->lines; ll; ll = ll->next)
-    {
-      PangoLayoutLine *line = ll->data;
-      GSList *old_runs = g_slist_reverse (line->runs);
-      GSList *rl;
-
-      line->runs = NULL;
-      for (rl = old_runs; rl; rl = rl->next)
-        {
-          PangoGlyphItem *glyph_item = rl->data;
-          GSList *new_runs;
-
-          new_runs = pango_glyph_item_apply_attrs (glyph_item,
-                                                   layout->text,
-                                                   attrs);
-
-          line->runs = g_slist_concat (new_runs, line->runs);
-        }
-
-      g_slist_free (old_runs);
-    }
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-static void
-pango_layout_check_lines (PangoLayout *layout)
-{
-  const char *start;
-  gboolean done = FALSE;
-  int start_offset;
-  PangoAttrList *attrs;
-  PangoAttrList *itemize_attrs;
-  PangoAttrList *shape_attrs;
-  PangoAttrIterator iter;
-  PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL;
-  PangoDirection base_dir = PANGO_DIRECTION_NEUTRAL;
-  ParaBreakState state;
-  gboolean need_log_attrs;
-
-  check_context_changed (layout);
-
-  if (G_LIKELY (layout->lines))
-    return;
-
-  /* For simplicity, we make sure at this point that layout->text
-   * is non-NULL even if it is zero length
-   */
-  if (G_UNLIKELY (!layout->text))
-    pango_layout_set_text (layout, NULL, 0);
-
-  attrs = pango_layout_get_effective_attributes (layout);
-  if (attrs)
-    {
-      shape_attrs = pango_attr_list_filter (attrs, affects_break_or_shape, NULL);
-      itemize_attrs = pango_attr_list_filter (attrs, affects_itemization, NULL);
-
-      if (itemize_attrs)
-        _pango_attr_list_get_iterator (itemize_attrs, &iter);
-    }
-  else
-    {
-      shape_attrs = NULL;
-      itemize_attrs = NULL;
-    }
-
-  if (!layout->log_attrs)
-    {
-      layout->log_attrs = g_new0 (PangoLogAttr, layout->n_chars + 1);
-      need_log_attrs = TRUE;
-    }
-  else
-    {
-      need_log_attrs = FALSE;
-    }
-
-  start_offset = 0;
-  start = layout->text;
-
-  /* Find the first strong direction of the text */
-  if (layout->auto_dir)
-    {
-      prev_base_dir = pango_find_base_dir (layout->text, layout->length);
-      if (prev_base_dir == PANGO_DIRECTION_NEUTRAL)
-        prev_base_dir = pango_context_get_base_dir (layout->context);
-    }
-  else
-    base_dir = pango_context_get_base_dir (layout->context);
-
-  /* these are only used if layout->height >= 0 */
-  state.remaining_height = layout->height;
-  state.line_height = -1;
-  if (layout->height >= 0)
-    {
-      PangoRectangle logical = { 0, };
-      int height = 0;
-      pango_layout_get_empty_extents_and_height_at_index (layout, 0, &logical, TRUE, &height);
-      state.line_height = layout->line_spacing == 0.0 ? logical.height : layout->line_spacing * height;
-    }
-
-  state.log_widths = NULL;
-  state.num_log_widths = 0;
-  state.baseline_shifts = NULL;
-
-  DEBUG1 ("START layout");
-  do
-    {
-      int delim_len;
-      const char *end;
-      int delimiter_index, next_para_index;
-
-      if (layout->single_paragraph)
-        {
-          delimiter_index = layout->length;
-          next_para_index = layout->length;
-        }
-      else
-        {
-          pango_find_paragraph_boundary (start,
-                                         (layout->text + layout->length) - start,
-                                         &delimiter_index,
-                                         &next_para_index);
-        }
-
-      g_assert (next_para_index >= delimiter_index);
-
-      if (layout->auto_dir)
-        {
-          base_dir = pango_find_base_dir (start, delimiter_index);
-
-          /* Propagate the base direction for neutral paragraphs */
-          if (base_dir == PANGO_DIRECTION_NEUTRAL)
-            base_dir = prev_base_dir;
-          else
-            prev_base_dir = base_dir;
-        }
-
-      end = start + delimiter_index;
-
-      delim_len = next_para_index - delimiter_index;
-
-      if (end == (layout->text + layout->length))
-        done = TRUE;
-
-      g_assert (end <= (layout->text + layout->length));
-      g_assert (start <= (layout->text + layout->length));
-      g_assert (delim_len < 4); /* PS is 3 bytes */
-      g_assert (delim_len >= 0);
-
-      state.attrs = itemize_attrs;
-      state.items = pango_itemize_with_font (layout->context,
-                                             base_dir,
-                                             layout->text,
-                                             start - layout->text,
-                                             end - start,
-                                             itemize_attrs,
-                                             itemize_attrs ? &iter : NULL,
-                                             NULL);
-
-      apply_attributes_to_items (state.items, shape_attrs);
-
-      if (need_log_attrs)
-        get_items_log_attrs (layout->text,
-                             start - layout->text,
-                             delimiter_index + delim_len,
-                             state.items,
-                             shape_attrs,
-                             layout->log_attrs + start_offset,
-                             layout->n_chars + 1 - start_offset);
-
-      state.items = pango_itemize_post_process_items (layout->context,
-                                                      layout->text,
-                                                      layout->log_attrs + start_offset,
-                                                      state.items);
-
-      state.base_dir = base_dir;
-      state.line_of_par = 1;
-      state.start_offset = start_offset;
-      state.line_start_offset = start_offset;
-      state.line_start_index = start - layout->text;
-
-      state.glyphs = NULL;
-
-      /* for deterministic bug hunting's sake set everything! */
-      state.line_width = -1;
-      state.remaining_width = -1;
-      state.log_widths_offset = 0;
-
-      state.hyphen_width = -1;
-
-      if (state.items)
-        {
-          while (state.items)
-            process_line (layout, &state);
-        }
-      else
-        {
-          PangoLayoutLine *empty_line;
-
-          empty_line = pango_layout_line_new (layout);
-          empty_line->start_index = state.line_start_index;
-          empty_line->is_paragraph_start = TRUE;
-          line_set_resolved_dir (empty_line, base_dir);
-
-          add_line (empty_line, &state);
-        }
-
-      if (layout->height >= 0 && state.remaining_height < state.line_height)
-        done = TRUE;
-
-      if (!done)
-        start_offset += pango_utf8_strlen (start, (end - start) + delim_len);
-
-      start = end + delim_len;
-    }
-  while (!done);
-
-  g_free (state.log_widths);
-  g_list_free_full (state.baseline_shifts, g_free);
-
-  apply_attributes_to_runs (layout, attrs);
-  layout->lines = g_slist_reverse (layout->lines);
-
-  if (itemize_attrs)
-    {
-      pango_attr_list_unref (itemize_attrs);
-      _pango_attr_iterator_destroy (&iter);
-    }
-
-  pango_attr_list_unref (shape_attrs);
-  pango_attr_list_unref (attrs);
-
-  int w, h;
-  pango_layout_get_size (layout, &w, &h);
-  DEBUG1 ("DONE %d %d", w, h);
-}
-
-#pragma GCC diagnostic pop
-
-/**
- * pango_layout_line_ref:
- * @line: (nullable): a `PangoLayoutLine`
- *
- * Increase the reference count of a `PangoLayoutLine` by one.
- *
- * Return value: the line passed in.
- *
- * Since: 1.10
- */
-PangoLayoutLine *
-pango_layout_line_ref (PangoLayoutLine *line)
-{
-  PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
-
-  if (line == NULL)
-    return NULL;
-
-  g_atomic_int_inc ((int *) &private->ref_count);
-
-  return line;
-}
-
-/**
- * pango_layout_line_unref:
- * @line: a `PangoLayoutLine`
- *
- * Decrease the reference count of a `PangoLayoutLine` by one.
- *
- * If the result is zero, the line and all associated memory
- * will be freed.
- */
-void
-pango_layout_line_unref (PangoLayoutLine *line)
-{
-  PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
-
-  if (line == NULL)
-    return;
-
-  g_return_if_fail (private->ref_count > 0);
-
-  if (g_atomic_int_dec_and_test ((int *) &private->ref_count))
-    {
-      g_slist_foreach (line->runs, (GFunc)free_run, GINT_TO_POINTER (1));
-      g_slist_free (line->runs);
-      g_slice_free (PangoLayoutLinePrivate, private);
-    }
-}
-
-G_DEFINE_BOXED_TYPE (PangoLayoutLine, pango_layout_line,
-                     pango_layout_line_ref,
-                     pango_layout_line_unref);
-
-/**
- * pango_layout_line_get_start_index:
- * @line: a `PangoLayoutLine`
- *
- * Returns the start index of the line, as byte index
- * into the text of the layout.
- *
- * Returns: the start index of the line
- *
- * Since: 1.50
- */
-int
-pango_layout_line_get_start_index (PangoLayoutLine *line)
-{
-  return line->start_index;
-}
-
-/**
- * pango_layout_line_get_length:
- * @line: a `PangoLayoutLine`
- *
- * Returns the length of the line, in bytes.
- *
- * Returns: the length of the line
- *
- * Since: 1.50
- */
-int
-pango_layout_line_get_length (PangoLayoutLine *line)
-{
-  return line->length;
-}
-
-/**
- * pango_layout_line_is_paragraph_start:
- * @line: a `PangoLayoutLine`
- *
- * Returns whether this is the first line of the paragraph.
- *
- * Returns: %TRUE if this is the first line
- *
- * Since: 1.50
- */
-gboolean
-pango_layout_line_is_paragraph_start (PangoLayoutLine *line)
-{
-  return line->is_paragraph_start;
-}
-
-/**
- * pango_layout_line_get_resolved_direction:
- * @line: a `PangoLayoutLine`
- *
- * Returns the resolved direction of the line.
- *
- * Returns: the resolved direction of the line
- *
- * Since: 1.50
- */
-PangoDirection
-pango_layout_line_get_resolved_direction (PangoLayoutLine *line)
-{
-  return (PangoDirection) line->resolved_dir;
-}
-
-/**
- * pango_layout_line_x_to_index:
- * @line: a `PangoLayoutLine`
- * @x_pos: the X offset (in Pango units) from the left edge of the line.
- * @index_: (out): location to store calculated byte index for the grapheme
- *   in which the user clicked
- * @trailing: (out): location to store an integer indicating where in the
- *   grapheme the user clicked. It will either be zero, or the number of
- *   characters in the grapheme. 0 represents the leading edge of the grapheme.
- *
- * Converts from x offset to the byte index of the corresponding character
- * within the text of the layout.
- *
- * If @x_pos is outside the line, @index_ and @trailing will point to the very
- * first or very last position in the line. This determination is based on the
- * resolved direction of the paragraph; for example, if the resolved direction
- * is right-to-left, then an X position to the right of the line (after it)
- * results in 0 being stored in @index_ and @trailing. An X position to the
- * left of the line results in @index_ pointing to the (logical) last grapheme
- * in the line and @trailing being set to the number of characters in that
- * grapheme. The reverse is true for a left-to-right line.
- *
- * Return value: %FALSE if @x_pos was outside the line, %TRUE if inside
- */
-gboolean
-pango_layout_line_x_to_index (PangoLayoutLine *line,
-                              int              x_pos,
-                              int             *index,
-                              int             *trailing)
-{
-  GSList *tmp_list;
-  gint start_pos = 0;
-  gint first_index = 0; /* line->start_index */
-  gint first_offset;
-  gint last_index;      /* start of last grapheme in line */
-  gint last_offset;
-  gint end_index;       /* end iterator for line */
-  gint end_offset;      /* end iterator for line */
-  PangoLayout *layout;
-  gint last_trailing;
-  gboolean suppress_last_trailing;
-
-  g_return_val_if_fail (LINE_IS_VALID (line), FALSE);
-
-  layout = line->layout;
-
-  /* Find the last index in the line
-   */
-  first_index = line->start_index;
-
-  if (line->length == 0)
-    {
-      if (index)
-        *index = first_index;
-      if (trailing)
-        *trailing = 0;
-
-      return FALSE;
-    }
-
-  g_assert (line->length > 0);
-
-  first_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
-
-  end_index = first_index + line->length;
-  end_offset = first_offset + g_utf8_pointer_to_offset (layout->text + first_index, layout->text + 
end_index);
-
-  last_index = end_index;
-  last_offset = end_offset;
-  last_trailing = 0;
-  do
-    {
-      last_index = g_utf8_prev_char (layout->text + last_index) - layout->text;
-      last_offset--;
-      last_trailing++;
-    }
-  while (last_offset > first_offset && !layout->log_attrs[last_offset].is_cursor_position);
-
-  /* This is a HACK. If a program only keeps track of cursor (etc)
-   * indices and not the trailing flag, then the trailing index of the
-   * last character on a wrapped line is identical to the leading
-   * index of the next line. So, we fake it and set the trailing flag
-   * to zero.
-   *
-   * That is, if the text is "now is the time", and is broken between
-   * 'now' and 'is'
-   *
-   * Then when the cursor is actually at:
-   *
-   * n|o|w| |i|s|
-   *              ^
-   * we lie and say it is at:
-   *
-   * n|o|w| |i|s|
-   *            ^
-   *
-   * So the cursor won't appear on the next line before 'the'.
-   *
-   * Actually, any program keeping cursor
-   * positions with wrapped lines should distinguish leading and
-   * trailing cursors.
-   */
-  tmp_list = layout->lines;
-  while (tmp_list->data != line)
-    tmp_list = tmp_list->next;
-
-  if (tmp_list->next &&
-      line->start_index + line->length == ((PangoLayoutLine *)tmp_list->next->data)->start_index)
-    suppress_last_trailing = TRUE;
-  else
-    suppress_last_trailing = FALSE;
-
-  if (x_pos < 0)
-    {
-      /* pick the leftmost char */
-      if (index)
-        *index = (line->resolved_dir == PANGO_DIRECTION_LTR) ? first_index : last_index;
-      /* and its leftmost edge */
-      if (trailing)
-        *trailing = (line->resolved_dir == PANGO_DIRECTION_LTR || suppress_last_trailing) ? 0 : 
last_trailing;
-
-      return FALSE;
-    }
-
-  tmp_list = line->runs;
-  while (tmp_list)
-    {
-      PangoLayoutRun *run = tmp_list->data;
-      int logical_width;
-
-      logical_width = pango_glyph_string_get_width (run->glyphs);
-
-      if (x_pos >= start_pos && x_pos < start_pos + logical_width)
-        {
-          int offset;
-          gboolean char_trailing;
-          int grapheme_start_index;
-          int grapheme_start_offset;
-          int grapheme_end_offset;
-          int pos;
-          int char_index;
-
-          pango_glyph_string_x_to_index (run->glyphs,
-                                         layout->text + run->item->offset, run->item->length,
-                                         &run->item->analysis,
-                                         x_pos - start_pos,
-                                         &pos, &char_trailing);
-
-          char_index = run->item->offset + pos;
-
-          /* Convert from characters to graphemes */
-
-          offset = g_utf8_pointer_to_offset (layout->text, layout->text + char_index);
-
-          grapheme_start_offset = offset;
-          grapheme_start_index = char_index;
-          while (grapheme_start_offset > first_offset &&
-                 !layout->log_attrs[grapheme_start_offset].is_cursor_position)
-            {
-              grapheme_start_index = g_utf8_prev_char (layout->text + grapheme_start_index) - layout->text;
-              grapheme_start_offset--;
-            }
-
-          grapheme_end_offset = offset;
-          do
-            {
-              grapheme_end_offset++;
-            }
-          while (grapheme_end_offset < end_offset &&
-                 !layout->log_attrs[grapheme_end_offset].is_cursor_position);
-
-          if (index)
-            *index = grapheme_start_index;
-
-          if (trailing)
-            {
-              if ((grapheme_end_offset == end_offset && suppress_last_trailing) ||
-                  offset + char_trailing <= (grapheme_start_offset + grapheme_end_offset) / 2)
-                *trailing = 0;
-              else
-                *trailing = grapheme_end_offset - grapheme_start_offset;
-            }
-
-          return TRUE;
-        }
-
-      start_pos += logical_width;
-      tmp_list = tmp_list->next;
-    }
-
-  /* pick the rightmost char */
-  if (index)
-    *index = (line->resolved_dir == PANGO_DIRECTION_LTR) ? last_index : first_index;
-
-  /* and its rightmost edge */
-  if (trailing)
-    *trailing = (line->resolved_dir == PANGO_DIRECTION_LTR && !suppress_last_trailing) ? last_trailing : 0;
-
-  return FALSE;
-}
-
-static int
-pango_layout_line_get_width (PangoLayoutLine *line)
-{
-  int width = 0;
-  GSList *tmp_list = line->runs;
-
-  while (tmp_list)
-    {
-      PangoLayoutRun *run = tmp_list->data;
-
-      width += pango_glyph_string_get_width (run->glyphs);
-
-      tmp_list = tmp_list->next;
-    }
-
-  return width;
-}
-
-/**
- * pango_layout_line_get_x_ranges:
- * @line: a `PangoLayoutLine`
- * @start_index: Start byte index of the logical range. If this value
- *   is less than the start index for the line, then the first range
- *   will extend all the way to the leading edge of the layout. Otherwise,
- *   it will start at the leading edge of the first character.
- * @end_index: Ending byte index of the logical range. If this value is
- *   greater than the end index for the line, then the last range will
- *   extend all the way to the trailing edge of the layout. Otherwise,
- *   it will end at the trailing edge of the last character.
- * @ranges: (out) (array length=n_ranges) (transfer full): location to
- *   store a pointer to an array of ranges. The array will be of length
- *   `2*n_ranges`, with each range starting at `(*ranges)[2*n]` and of
- *   width `(*ranges)[2*n + 1] - (*ranges)[2*n]`. This array must be freed
- *   with g_free(). The coordinates are relative to the layout and are in
- *   Pango units.
- * @n_ranges: The number of ranges stored in @ranges
- *
- * Gets a list of visual ranges corresponding to a given logical range.
- *
- * This list is not necessarily minimal - there may be consecutive
- * ranges which are adjacent. The ranges will be sorted from left to
- * right. The ranges are with respect to the left edge of the entire
- * layout, not with respect to the line.
- */
-void
-pango_layout_line_get_x_ranges (PangoLayoutLine  *line,
-                                int               start_index,
-                                int               end_index,
-                                int             **ranges,
-                                int              *n_ranges)
-{
-  gint line_start_index = 0;
-  GSList *tmp_list;
-  int range_count = 0;
-  int accumulated_width = 0;
-  int x_offset;
-  int width, line_width;
-  PangoAlignment alignment;
-
-  g_return_if_fail (line != NULL);
-  g_return_if_fail (line->layout != NULL);
-  g_return_if_fail (start_index <= end_index);
-
-  alignment = get_alignment (line->layout, line);
-
-  width = line->layout->width;
-  if (width == -1 && alignment != PANGO_ALIGN_LEFT)
-    {
-      PangoRectangle logical_rect;
-      pango_layout_get_extents (line->layout, NULL, &logical_rect);
-      width = logical_rect.width;
-    }
-
-  /* FIXME: The computations here could be optimized, by moving the
-   * computations of the x_offset after we go through and figure
-   * out where each range is.
-   */
-
-  {
-    PangoRectangle logical_rect;
-    pango_layout_line_get_extents (line, NULL, &logical_rect);
-    line_width = logical_rect.width;
-  }
-
-  get_x_offset (line->layout, line, width, line_width, &x_offset);
-
-  line_start_index = line->start_index;
-
-  /* Allocate the maximum possible size */
-  if (ranges)
-    *ranges = g_new (int, 2 * (2 + g_slist_length (line->runs)));
-
-  if (x_offset > 0 &&
-      ((line->resolved_dir == PANGO_DIRECTION_LTR && start_index < line_start_index) ||
-       (line->resolved_dir == PANGO_DIRECTION_RTL && end_index > line_start_index + line->length)))
-    {
-      if (ranges)
-        {
-          (*ranges)[2*range_count] = 0;
-          (*ranges)[2*range_count + 1] = x_offset;
-        }
-
-      range_count ++;
-    }
-
-  tmp_list = line->runs;
-  while (tmp_list)
-    {
-      PangoLayoutRun *run = (PangoLayoutRun *)tmp_list->data;
-
-      if ((start_index < run->item->offset + run->item->length &&
-           end_index > run->item->offset))
-        {
-          if (ranges)
-            {
-              int run_start_index = MAX (start_index, run->item->offset);
-              int run_end_index = MIN (end_index, run->item->offset + run->item->length);
-              int run_start_x, run_end_x;
-              int attr_offset;
-
-              g_assert (run_end_index > 0);
-
-              /* Back the end_index off one since we want to find the trailing edge of the preceding 
character */
-
-              run_end_index = g_utf8_prev_char (line->layout->text + run_end_index) - line->layout->text;
-
-              attr_offset = run->item->char_offset;
-
-              pango_glyph_string_index_to_x_full (run->glyphs,
-                                                  line->layout->text + run->item->offset,
-                                                  run->item->length,
-                                                  &run->item->analysis,
-                                                  line->layout->log_attrs + attr_offset,
-                                                  run_start_index - run->item->offset, FALSE,
-                                                  &run_start_x);
-              pango_glyph_string_index_to_x_full (run->glyphs,
-                                                  line->layout->text + run->item->offset,
-                                                  run->item->length,
-                                                  &run->item->analysis,
-                                                  line->layout->log_attrs + attr_offset,
-                                                  run_end_index - run->item->offset, TRUE,
-                                                  &run_end_x);
-
-              (*ranges)[2*range_count] = x_offset + accumulated_width + MIN (run_start_x, run_end_x);
-              (*ranges)[2*range_count + 1] = x_offset + accumulated_width + MAX (run_start_x, run_end_x);
-            }
-
-          range_count++;
-        }
-
-      if (tmp_list->next)
-        accumulated_width += pango_glyph_string_get_width (run->glyphs);
-
-      tmp_list = tmp_list->next;
-    }
-
-  if (x_offset + line_width < line->layout->width &&
-      ((line->resolved_dir == PANGO_DIRECTION_LTR && end_index > line_start_index + line->length) ||
-       (line->resolved_dir == PANGO_DIRECTION_RTL && start_index < line_start_index)))
-    {
-      if (ranges)
-        {
-          (*ranges)[2*range_count] = x_offset + line_width;
-          (*ranges)[2*range_count + 1] = line->layout->width;
-        }
-
-      range_count ++;
-    }
-
-  if (n_ranges)
-    *n_ranges = range_count;
-}
-
-static void
-pango_layout_get_empty_extents_and_height_at_index (PangoLayout    *layout,
-                                                    int             index,
-                                                    PangoRectangle *logical_rect,
-                                                    gboolean        apply_line_height,
-                                                    int             *height)
-{
-  if (logical_rect)
-    {
-      PangoFont *font;
-      PangoFontDescription *font_desc = NULL;
-      gboolean free_font_desc = FALSE;
-      double line_height_factor = 0.0;
-      int absolute_line_height = 0;
-
-      font_desc = pango_context_get_font_description (layout->context);
-
-      if (layout->font_desc)
-        {
-          font_desc = pango_font_description_copy_static (font_desc);
-          pango_font_description_merge (font_desc, layout->font_desc, TRUE);
-          free_font_desc = TRUE;
-        }
-
-      /* Find the font description for this line
-       */
-      if (layout->attrs)
-        {
-          PangoAttrIterator iter;
-          int start, end;
-
-          _pango_attr_list_get_iterator (layout->attrs, &iter);
-
-          do
-            {
-              pango_attr_iterator_range (&iter, &start, &end);
-
-              if (start <= index && index < end)
-                {
-                  PangoAttribute *attr;
-
-                  if (!free_font_desc)
-                    {
-                      font_desc = pango_font_description_copy_static (font_desc);
-                      free_font_desc = TRUE;
-                    }
-
-                  pango_attr_iterator_get_font (&iter, font_desc, NULL, NULL);
-
-                  attr = pango_attr_iterator_get (&iter, PANGO_ATTR_LINE_HEIGHT);
-                  if (attr)
-                    line_height_factor = ((PangoAttrFloat *)attr)->value;
-
-                  attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ABSOLUTE_LINE_HEIGHT);
-                  if (attr)
-                    absolute_line_height = ((PangoAttrInt *)attr)->value;
-
-                  break;
-                }
-
-            }
-          while (pango_attr_iterator_next (&iter));
-
-          _pango_attr_iterator_destroy (&iter);
-        }
-
-      font = pango_context_load_font (layout->context, font_desc);
-      if (font)
-        {
-          PangoFontMetrics *metrics;
-
-          metrics = pango_font_get_metrics (font,
-                                            pango_context_get_language (layout->context));
-
-          if (metrics)
-            {
-              logical_rect->y = - pango_font_metrics_get_ascent (metrics);
-              logical_rect->height = - logical_rect->y + pango_font_metrics_get_descent (metrics);
-              if (height)
-                *height = pango_font_metrics_get_height (metrics);
-
-              pango_font_metrics_unref (metrics);
-
-              if (apply_line_height &&
-                  (absolute_line_height != 0 || line_height_factor != 0.0))
-                {
-                  int line_height, leading;
-
-                  line_height = MAX (absolute_line_height, ceilf (line_height_factor * 
logical_rect->height));
-
-                  leading = line_height - logical_rect->height;
-                  logical_rect->y -= leading / 2;
-                  logical_rect->height += leading;
-                }
-            }
-          else
-            {
-              logical_rect->y = 0;
-              logical_rect->height = 0;
-            }
-          g_object_unref (font);
-        }
-      else
-        {
-          logical_rect->y = 0;
-          logical_rect->height = 0;
-        }
-
-      if (free_font_desc)
-        pango_font_description_free (font_desc);
-
-      logical_rect->x = 0;
-      logical_rect->width = 0;
-    }
-}
-
-void pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
-                                              PangoRectangle *run_ink,
-                                              PangoRectangle *run_logical,
-                                              PangoRectangle *line_logical,
-                                              int            *height);
-
-void
-pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
-                                         PangoRectangle *run_ink,
-                                         PangoRectangle *run_logical,
-                                         PangoRectangle *line_logical,
-                                         int            *height)
-{
-  PangoRectangle logical;
-  ItemProperties properties;
-  PangoFontMetrics *metrics = NULL;
-  gboolean has_underline;
-  gboolean has_overline;
-  int y_offset;
-
-  if (G_UNLIKELY (!run_ink && !run_logical && !line_logical && !height))
-    return;
-
-  pango_item_get_properties (run->item, &properties);
-
-  has_underline = properties.uline_single || properties.uline_double ||
-                  properties.uline_low || properties.uline_error;
-  has_overline = properties.oline_single;
-
-  if (!run_logical && (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE))
-    run_logical = &logical;
-
-  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,
-                              properties.shape_logical_rect,
-                              run_ink, run_logical);
-  else
-    pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
-                                run_ink, run_logical);
-
-  if (run_ink && (has_underline || has_overline || properties.strikethrough))
-    {
-      int underline_thickness;
-      int underline_position;
-      int strikethrough_thickness;
-      int strikethrough_position;
-      int new_pos;
-
-      if (!metrics)
-        metrics = pango_font_get_metrics (run->item->analysis.font,
-                                          run->item->analysis.language);
-
-      underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
-      underline_position = pango_font_metrics_get_underline_position (metrics);
-      strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
-      strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
-
-      /* the underline/strikethrough takes x,width of logical_rect.  reflect
-       * that into ink_rect.
-       */
-      new_pos = MIN (run_ink->x, run_logical->x);
-      run_ink->width = MAX (run_ink->x + run_ink->width, run_logical->x + run_logical->width) - new_pos;
-      run_ink->x = new_pos;
-
-      /* We should better handle the case of height==0 in the following cases.
-       * If run_ink->height == 0, we should adjust run_ink->y appropriately.
-       */
-
-      if (properties.strikethrough)
-        {
-          if (run_ink->height == 0)
-            {
-              run_ink->height = strikethrough_thickness;
-              run_ink->y = -strikethrough_position;
-            }
-        }
-
-      if (properties.oline_single)
-        {
-          run_ink->y -= underline_thickness;
-          run_ink->height += underline_thickness;
-        }
-
-      if (properties.uline_low)
-        run_ink->height += 2 * underline_thickness;
-      if (properties.uline_single)
-        run_ink->height = MAX (run_ink->height,
-                               underline_thickness - underline_position - run_ink->y);
-      if (properties.uline_double)
-        run_ink->height = MAX (run_ink->height,
-                                 3 * underline_thickness - underline_position - run_ink->y);
-      if (properties.uline_error)
-        run_ink->height = MAX (run_ink->height,
-                               3 * underline_thickness - underline_position - run_ink->y);
-    }
-
-  if (height)
-    {
-      if (pango_analysis_get_size_font (&run->item->analysis))
-        {
-          PangoFontMetrics *height_metrics;
-
-          height_metrics = pango_font_get_metrics (pango_analysis_get_size_font (&run->item->analysis),
-                                                   run->item->analysis.language);
-
-          *height = pango_font_metrics_get_height (height_metrics);
-
-          pango_font_metrics_unref (height_metrics);
-        }
-      else
-        {
-          if (!metrics)
-            metrics = pango_font_get_metrics (run->item->analysis.font,
-                                              run->item->analysis.language);
-
-          *height = pango_font_metrics_get_height (metrics);
-        }
-    }
-
-  y_offset = run->y_offset;
-
-  if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
-    {
-      gboolean is_hinted = (run_logical->y & run_logical->height & (PANGO_SCALE - 1)) == 0;
-      int adjustment = run_logical->y + run_logical->height / 2;
-
-      if (is_hinted)
-        adjustment = PANGO_UNITS_ROUND (adjustment);
-
-      y_offset += adjustment;
-    }
-
-  if (run_ink)
-    run_ink->y -= y_offset;
-
-  if (run_logical)
-    run_logical->y -= y_offset;
-
-  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);
-}
-
-static void
-pango_layout_line_get_extents_and_height (PangoLayoutLine *line,
-                                          PangoRectangle  *ink_rect,
-                                          PangoRectangle  *logical_rect,
-                                          int             *height)
-{
-  PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line;
-  GSList *tmp_list;
-  int x_pos = 0;
-  gboolean caching = FALSE;
-
-  g_return_if_fail (LINE_IS_VALID (line));
-
-  if (G_UNLIKELY (!ink_rect && !logical_rect && !height))
-    return;
-
-  switch (private->cache_status)
-    {
-    case CACHED:
-      if (ink_rect)
-        *ink_rect = private->ink_rect;
-      if (logical_rect)
-        *logical_rect = private->logical_rect;
-      if (height)
-        *height = private->height;
-      return;
-
-    case NOT_CACHED:
-      caching = TRUE;
-      if (!ink_rect)
-        ink_rect = &private->ink_rect;
-      if (!logical_rect)
-        logical_rect = &private->logical_rect;
-      if (!height)
-        height = &private->height;
-      break;
-
-    case LEAKED:
-    default:
-      break;
-    }
-
-  if (ink_rect)
-    {
-      ink_rect->x = 0;
-      ink_rect->y = 0;
-      ink_rect->width = 0;
-      ink_rect->height = 0;
-    }
-
-  if (logical_rect)
-    {
-      logical_rect->x = 0;
-      logical_rect->y = 0;
-      logical_rect->width = 0;
-      logical_rect->height = 0;
-    }
-
-  if (height)
-    *height = 0;
-
-  tmp_list = line->runs;
-  while (tmp_list)
-    {
-      PangoLayoutRun *run = tmp_list->data;
-      int new_pos;
-      PangoRectangle run_ink;
-      PangoRectangle run_logical;
-      int run_height;
-
-      pango_layout_run_get_extents_and_height (run,
-                                               ink_rect ? &run_ink : NULL,
-                                               NULL,
-                                               &run_logical,
-                                               height ? &run_height : NULL);
-
-      if (ink_rect)
-        {
-          if (ink_rect->width == 0 || ink_rect->height == 0)
-            {
-              *ink_rect = run_ink;
-              ink_rect->x += x_pos;
-            }
-          else if (run_ink.width != 0 && run_ink.height != 0)
-            {
-              new_pos = MIN (ink_rect->x, x_pos + run_ink.x);
-              ink_rect->width = MAX (ink_rect->x + ink_rect->width,
-                                     x_pos + run_ink.x + run_ink.width) - new_pos;
-              ink_rect->x = new_pos;
-
-              new_pos = MIN (ink_rect->y, run_ink.y);
-              ink_rect->height = MAX (ink_rect->y + ink_rect->height,
-                                      run_ink.y + run_ink.height) - new_pos;
-              ink_rect->y = new_pos;
-            }
-        }
-
-      if (logical_rect)
-        {
-          new_pos = MIN (logical_rect->x, x_pos + run_logical.x);
-          logical_rect->width = MAX (logical_rect->x + logical_rect->width,
-                                     x_pos + run_logical.x + run_logical.width) - new_pos;
-          logical_rect->x = new_pos;
-
-          new_pos = MIN (logical_rect->y, run_logical.y);
-          logical_rect->height = MAX (logical_rect->y + logical_rect->height,
-                                      run_logical.y + run_logical.height) - new_pos;
-          logical_rect->y = new_pos;
-        }
-
-      if (height)
-        *height = MAX (*height, abs (run_height));
-
-      x_pos += run_logical.width;
-      tmp_list = tmp_list->next;
-    }
-
-  if (!line->runs)
-    {
-      PangoRectangle r, *rect;
-
-      rect = logical_rect ? logical_rect : &r;
-      pango_layout_get_empty_extents_and_height_at_index (line->layout, line->start_index, rect, TRUE, 
height);
-    }
-
-  if (caching)
-    {
-      if (&private->ink_rect != ink_rect)
-        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;
-    }
-}
-
-/**
- * pango_layout_line_get_extents:
- * @line: a `PangoLayoutLine`
- * @ink_rect: (out) (optional): rectangle used to store the extents of
- *   the glyph string as drawn
- * @logical_rect: (out) (optional): rectangle used to store the logical
- *   extents of the glyph string
- *
- * Computes the logical and ink extents of a layout line.
- *
- * See [method Pango Font.get_glyph_extents] for details
- * about the interpretation of the rectangles.
- */
-void
-pango_layout_line_get_extents (PangoLayoutLine *line,
-                               PangoRectangle  *ink_rect,
-                               PangoRectangle  *logical_rect)
-{
-  pango_layout_line_get_extents_and_height (line, ink_rect, logical_rect, NULL);
-}
-
-/**
- * pango_layout_line_get_height:
- * @line: a `PangoLayoutLine`
- * @height: (out) (optional): return location for the line height
- *
- * Computes the height of the line, as the maximum of the heights
- * of fonts used in this line.
- *
- * Note that the actual baseline-to-baseline distance between lines
- * of text is influenced by other factors, such as
- * [method@Pango.Layout.set_spacing] and
- * [method@Pango.Layout.set_line_spacing].
- *
- * Since: 1.44
- */
-void
-pango_layout_line_get_height (PangoLayoutLine *line,
-                              int             *height)
-{
-  pango_layout_line_get_extents_and_height (line, NULL, NULL, height);
-}
-
-static PangoLayoutLine *
-pango_layout_line_new (PangoLayout *layout)
-{
-  PangoLayoutLinePrivate *private = g_slice_new (PangoLayoutLinePrivate);
-
-  private->ref_count = 1;
-  private->line.layout = layout;
-  private->line.runs = NULL;
-  private->line.length = 0;
-  private->cache_status = NOT_CACHED;
-
-  /* Note that we leave start_index, resolved_dir, and is_paragraph_start
-   *  uninitialized */
-
-  return (PangoLayoutLine *) private;
-}
-
-/**
- * pango_layout_line_get_pixel_extents:
- * @layout_line: a `PangoLayoutLine`
- * @ink_rect: (out) (optional): rectangle used to store the extents of
- *   the glyph string as drawn
- * @logical_rect: (out) (optional): rectangle used to store the logical
- *   extents of the glyph string
- *
- * Computes the logical and ink extents of @layout_line in device units.
- *
- * This function just calls [method@Pango.LayoutLine.get_extents] followed by
- * two [func@extents_to_pixels] calls, rounding @ink_rect and @logical_rect
- * such that the rounded rectangles fully contain the unrounded one (that is,
- * passes them as first argument to [func@extents_to_pixels]).
- */
-void
-pango_layout_line_get_pixel_extents (PangoLayoutLine *layout_line,
-                                     PangoRectangle  *ink_rect,
-                                     PangoRectangle  *logical_rect)
-{
-  g_return_if_fail (LINE_IS_VALID (layout_line));
-
-  pango_layout_line_get_extents (layout_line, ink_rect, logical_rect);
-  pango_extents_to_pixels (ink_rect, NULL);
-  pango_extents_to_pixels (logical_rect, NULL);
-}
-
-/*
- * NB: This implement the exact same algorithm as
- *     reorder-items.c:pango_reorder_items().
- */
-static GSList *
-reorder_runs_recurse (GSList *items,
-                      int     n_items)
-{
-  GSList *tmp_list, *level_start_node;
-  int i, level_start_i;
-  int min_level = G_MAXINT;
-  GSList *result = NULL;
-
-  if (n_items == 0)
-    return NULL;
-
-  tmp_list = items;
-  for (i=0; i<n_items; i++)
-    {
-      PangoLayoutRun *run = tmp_list->data;
-
-      min_level = MIN (min_level, run->item->analysis.level);
-
-      tmp_list = tmp_list->next;
-    }
-
-  level_start_i = 0;
-  level_start_node = items;
-  tmp_list = items;
-  for (i=0; i<n_items; i++)
-    {
-      PangoLayoutRun *run = tmp_list->data;
-
-      if (run->item->analysis.level == min_level)
-        {
-          if (min_level % 2)
-            {
-              if (i > level_start_i)
-                result = g_slist_concat (reorder_runs_recurse (level_start_node, i - level_start_i), result);
-              result = g_slist_prepend (result, run);
-            }
-          else
-            {
-              if (i > level_start_i)
-                result = g_slist_concat (result, reorder_runs_recurse (level_start_node, i - level_start_i));
-              result = g_slist_append (result, run);
-            }
-
-          level_start_i = i + 1;
-          level_start_node = tmp_list->next;
-        }
-
-      tmp_list = tmp_list->next;
-    }
-
-  if (min_level % 2)
-    {
-      if (i > level_start_i)
-        result = g_slist_concat (reorder_runs_recurse (level_start_node, i - level_start_i), result);
-    }
-  else
-    {
-      if (i > level_start_i)
-        result = g_slist_concat (result, reorder_runs_recurse (level_start_node, i - level_start_i));
-    }
-
-  return result;
-}
-
-static void
-pango_layout_line_reorder (PangoLayoutLine *line)
-{
-  GSList *logical_runs = line->runs;
-  GSList *tmp_list;
-  gboolean all_even, all_odd;
-  guint8 level_or = 0, level_and = 1;
-  int length = 0;
-
-  /* Check if all items are in the same direction, in that case, the
-   * line does not need modification and we can avoid the expensive
-   * reorder runs recurse procedure.
+  /**
+   * PangoLayout:attributes: (attributes org.gtk.Property.get=pango_layout_get_attributes 
org.gtk.Property.set=pango_layout_set_attributes)
+   *
+   * The attributes of the `PangoLayout`.
+   *
+   * Attributes can affect how the text is formatted.
    */
-  for (tmp_list = logical_runs; tmp_list != NULL; tmp_list = tmp_list->next)
-    {
-      PangoLayoutRun *run = tmp_list->data;
-
-      level_or |= run->item->analysis.level;
-      level_and &= run->item->analysis.level;
+  props[PROP_ATTRIBUTES] = g_param_spec_boxed ("attributes", "attributes", "attributes",
+                                               PANGO_TYPE_ATTR_LIST,
+                                               G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-      length++;
-    }
-
-  /* If none of the levels had the LSB set, all numbers were even. */
-  all_even = (level_or & 0x1) == 0;
-
-  /* If all of the levels had the LSB set, all numbers were odd. */
-  all_odd = (level_and & 0x1) == 1;
+  /**
+   * PangoLayout:font-description: (attributes org.gtk.Property.get=pango_layout_get_font_description 
org.gtk.Property.set=pango_layout_set_font_description)
+   *
+   * The font description of the `PangoLayout`.
+   */
+  props[PROP_FONT_DESCRIPTION] = g_param_spec_boxed ("font-description", "font-description", 
"font-description",
+                                                     PANGO_TYPE_FONT_DESCRIPTION,
+                                                     G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  if (!all_even && !all_odd)
-    {
-      line->runs = reorder_runs_recurse (logical_runs, length);
-      g_slist_free (logical_runs);
-    }
-  else if (all_odd)
-      line->runs = g_slist_reverse (logical_runs);
-}
+  /**
+   * PangoLayout:line-spacing: (attributes org.gtk.Property.get=pango_layout_get_line_spacing 
org.gtk.Property.set=pango_layout_set_line_spacing)
+   *
+   * The line spacing factor of the `PangoLayout`.
+   */
+  props[PROP_LINE_SPACING] = g_param_spec_float ("line-spacing", "line-spacing", "line-spacing",
+                                                 0., G_MAXFLOAT, 0.,
+                                                 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-static int
-get_item_letter_spacing (PangoItem *item)
-{
-  ItemProperties properties;
+  /**
+   * PangoLayout:width: (attributes org.gtk.Property.get=pango_layout_get_width 
org.gtk.Property.set=pango_layout_set_width)
+   *
+   * The width to which the text of `PangoLayout` will be broken.
+   *
+   * The width is specified in Pango units, with -1 meaning unlimited.
+   *
+   * The default value is -1.
+   */
+  props[PROP_WIDTH] = g_param_spec_int ("width", "width", "width",
+                                        -1, G_MAXINT, -1,
+                                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  pango_item_get_properties (item, &properties);
+  /**
+   * PangoLayout:height: (attributes org.gtk.Property.get=pango_layout_get_height 
org.gtk.Property.set=pango_layout_set_height)
+   *
+   * The height to which the `PangoLayout` will be ellipsized.
+   *
+   * If @height is positive, it will be the maximum height of the
+   * layout. Only lines would be shown that would fit, and if there
+   * is any text omitted, an ellipsis added. At least one line is
+   * included in each paragraph regardless of how small the height
+   * value is. A value of zero will render exactly one line for the
+   * entire layout.
+   *
+   * If @height is negative, it will be the (negative of) maximum
+   * number of lines per paragraph. That is, the total number of lines
+   * shown may well be more than this value if the layout contains
+   * multiple paragraphs of text.
+   *
+   * The default value of -1 means that the first line of each
+   * paragraph is ellipsized.
+   *
+   * Height setting only has effect if a positive width is set on the
+   * layout and its ellipsization mode is not `PANGO_ELLIPSIZE_NONE`.
+   * The behavior is undefined if a height other than -1 is set and
+   * ellipsization mode is set to `PANGO_ELLIPSIZE_NONE`.
+   *
+   * The default value is -1.
+   */
+  props[PROP_HEIGHT] = g_param_spec_int ("height", "height", "height",
+                                         -G_MAXINT, G_MAXINT, -1,
+                                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  return properties.letter_spacing;
-}
+  /**
+   * PangoLayout:tabs: (attributes org.gtk.Property.get=pango_layout_get_tabs 
org.gtk.Property.set=pango_layout_set_tabs)
+   *
+   * The tabs to use when formatting the text of `PangoLayout`.
+   *
+   * `PangoLayout` will place content at the next tab position
+   * whenever it meets a Tab character (U+0009).
+   */
+  props[PROP_TABS] = g_param_spec_boxed ("tabs", "tabs", "tabs",
+                                         PANGO_TYPE_TAB_ARRAY,
+                                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-static void
-pad_glyphstring_right (PangoGlyphString *glyphs,
-                       ParaBreakState   *state,
-                       int               adjustment)
-{
-  int glyph = glyphs->num_glyphs - 1;
+  /**
+   * PangoLayout:single-paragraph: (attributes org.gtk.Property.get=pango_layout_get_single_paragraph 
org.gtk.Property.set=pango_layout_set_single_paragraph)
+   *
+   * Whether to treat newlines and similar characters as paragraph
+   * separators or not. If this property is `TRUE`, all text is kept
+   * in a single paragraph, and paragraph separator characters are
+   * displayed with a glyph.
+   *
+   * This is useful to allow editing of newlines on a single text line.
+   *
+   * The default value is `FALSE`.
+   */
+  props[PROP_SINGLE_PARAGRAPH] = g_param_spec_boolean ("single-paragraph", "single-paragraph", 
"single-paragraph",
+                                                       FALSE,
+                                                       G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  while (glyph >= 0 && glyphs->glyphs[glyph].geometry.width == 0)
-    glyph--;
+  /**
+   * PangoLayout:wrap: (attributes org.gtk.Property.get=pango_layout_get_wrap 
org.gtk.Property.set=pango_layout_set_wrap)
+   *
+   * The wrap mode of this `PangoLayout.
+   *
+   * The wrap mode influences how Pango chooses line breaks
+   * when text needs to be wrapped.
+   *
+   * The default value is `PANGO_WRAP_WORD`.
+   */
+  props[PROP_WRAP] = g_param_spec_enum ("wrap", "wrap", "wrap",
+                                        PANGO_TYPE_WRAP_MODE,
+                                        PANGO_WRAP_WORD,
+                                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  if (glyph < 0)
-    return;
+  /**
+   * PangoLayout:indent: (attributes org.gtk.Property.get=pango_layout_get_indent 
org.gtk.Property.set=pango_layout_set_indent)
+   *
+   * The indent of this `PangoLayout.
+   *
+   * The indent is specified in Pango units.
+   *
+   * A negative value of @indent will produce a hanging indentation.
+   * That is, the first line will have the full width, and subsequent
+   * lines will be indented by the absolute value of @indent.
+   *
+   * The default value is 0.
+   */
+  props[PROP_INDENT] = g_param_spec_int ("indent", "indent", "indent",
+                                         G_MININT, G_MAXINT, 0,
+                                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  state->remaining_width -= adjustment;
-  glyphs->glyphs[glyph].geometry.width += adjustment;
-  if (glyphs->glyphs[glyph].geometry.width < 0)
-    {
-      state->remaining_width += glyphs->glyphs[glyph].geometry.width;
-      glyphs->glyphs[glyph].geometry.width = 0;
-    }
-}
+  /**
+   * PangoLayout:alignment: (attributes org.gtk.Property.get=pango_layout_get_alignment 
org.gtk.Property.set=pango_layout_set_alignment)
+   *
+   * The alignment mode of this `PangoLayout.
+   *
+   * The default value is `PANGO_ALIGNMENT_LEFT`.
+   */
+  props[PROP_ALIGNMENT] = g_param_spec_enum ("alignment", "alignment", "alignment",
+                                             PANGO_TYPE_ALIGNMENT,
+                                             PANGO_ALIGN_LEFT,
+                                             G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-static void
-pad_glyphstring_left (PangoGlyphString *glyphs,
-                      ParaBreakState   *state,
-                      int               adjustment)
-{
-  int glyph = 0;
+  /**
+   * PangoLayout:ellipsize: (attributes org.gtk.Property.get=pango_layout_get_ellipsize 
org.gtk.Property.set=pango_layout_set_ellipsize)
+   *
+   * The ellipsization mode of this `PangoLayout.
+   *
+   * The default value is `PANGO_ELLIPSIZE_NONE`.
+   */
+  props[PROP_ELLIPSIZE] = g_param_spec_enum ("ellipsize", "ellipsize", "ellipsize",
+                                             PANGO_TYPE_ELLIPSIZE_MODE,
+                                             PANGO_ELLIPSIZE_NONE,
+                                             G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  while (glyph < glyphs->num_glyphs && glyphs->glyphs[glyph].geometry.width == 0)
-    glyph++;
+  /**
+   * PangoLayout:auto-dir: (attributes org.gtk.Property.get=pango_layout_get_auto_dir 
org.gtk.Property.set=pango_layout_set_auto_dir)
+   *
+   * Whether this `PangoLayout` determines the
+   * base direction from the content.
+   *
+   * The default value is `TRUE`.
+   */
+  props[PROP_AUTO_DIR] = g_param_spec_boolean ("auto-dir", "auto-dir", "auto-dir",
+                                               TRUE,
+                                               G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
-  if (glyph == glyphs->num_glyphs)
-    return;
+  /**
+   * PangoLayout:lines: (attributes org.gtk.Property.get=pango_layout_get_lines)
+   *
+   * The `PangoLines` object holding the formatted lines.
+   */
+  props[PROP_LINES] = g_param_spec_object ("lines", "lines", "lines",
+                                           PANGO_TYPE_LINES,
+                                           G_PARAM_READABLE);
 
-  state->remaining_width -= adjustment;
-  glyphs->glyphs[glyph].geometry.width += adjustment;
-  glyphs->glyphs[glyph].geometry.x_offset += adjustment;
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, props);
 }
 
-static gboolean
-is_tab_run (PangoLayout    *layout,
-            PangoLayoutRun *run)
-{
-  return (layout->text[run->item->offset] == '\t');
-}
+/*  }}} */
+/* {{{ Utilities */
 
 static void
-add_missing_hyphen (PangoLayoutLine *line,
-                    ParaBreakState  *state,
-                    PangoLayoutRun  *run)
-{
-  PangoLayout *layout = line->layout;
-  PangoItem *item = run->item;
-  int line_chars;
-
-  line_chars = 0;
-  for (GSList *l = line->runs; l; l = l->next)
-    {
-      PangoLayoutRun *r = l->data;
-
-      if (r)
-        line_chars += r->item->num_chars;
-    }
-
-  if (layout->log_attrs[state->line_start_offset + line_chars].break_inserts_hyphen &&
-      !(item->analysis.flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN))
-    {
-      int width;
-      int start_offset;
-
-      DEBUG1("add a missing hyphen");
-      /* The last run fit onto the line without breaking it, but it still needs a hyphen */
-
-      width = pango_glyph_string_get_width (run->glyphs);
+layout_changed (PangoLayout *layout)
+{
+  layout->serial++;
+  if (layout->serial == 0)
+    layout->serial++;
 
-      /* Ugly, shape_run uses state->start_offset, so temporarily rewind things
-       * to the state before the run was inserted. Otherwise, we end up passing
-       * the wrong log attrs to the shaping machinery.
-       */
-      start_offset = state->start_offset;
-      state->start_offset = state->line_start_offset + line_chars - item->num_chars;
+  g_clear_object (&layout->lines);
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_LINES]);
+}
 
-      pango_glyph_string_free (run->glyphs);
-      item->analysis.flags |= PANGO_ANALYSIS_FLAG_NEED_HYPHEN;
-      run->glyphs = shape_run (line, state, item);
+static void
+check_context_changed (PangoLayout *layout)
+{
+  guint old_serial = layout->context_serial;
 
-      state->start_offset = start_offset;
+  layout->context_serial = pango_context_get_serial (layout->context);
 
-      state->remaining_width += pango_glyph_string_get_width (run->glyphs) - width;
-    }
+  if (old_serial != layout->context_serial)
+    pango_layout_context_changed (layout);
 }
 
-static void
-zero_line_final_space (PangoLayoutLine *line,
-                       ParaBreakState  *state,
-                       PangoLayoutRun  *run)
+static PangoAttrList *
+ensure_attrs (PangoLayout   *layout,
+              PangoAttrList *attrs)
 {
-  PangoLayout *layout = line->layout;
-  PangoItem *item = run->item;
-  PangoGlyphString *glyphs;
-  int glyph;
+  if (attrs)
+    return attrs;
+  else if (layout->attrs)
+    return pango_attr_list_copy (layout->attrs);
+  else
+    return pango_attr_list_new ();
+}
 
-  glyphs = run->glyphs;
-  glyph = item->analysis.level % 2 ? 0 : glyphs->num_glyphs - 1;
+static PangoAttrList *
+get_effective_attributes (PangoLayout *layout)
+{
+  PangoAttrList *attrs = NULL;
 
-  if (glyphs->glyphs[glyph].glyph == PANGO_GET_UNKNOWN_GLYPH (0x2028))
+  if (layout->font_desc)
     {
-      DEBUG1 ("zero final space: visible space");
-      return; /* this LS is visible */
+      attrs = ensure_attrs (layout, attrs);
+      pango_attr_list_insert_before (attrs,
+                                     pango_attr_font_desc_new (layout->font_desc));
     }
 
-  /* if the final char of line forms a cluster, and it's
-   * a whitespace char, zero its glyph's width as it's been wrapped
-   */
-  if (glyphs->num_glyphs < 1 || state->start_offset == 0 ||
-      !layout->log_attrs[state->start_offset - 1].is_white)
+  if (layout->line_spacing != 0.0)
     {
-      DEBUG1 ("zero final space: not whitespace");
-      return;
+      attrs = ensure_attrs (layout, attrs);
+      pango_attr_list_insert_before (attrs,
+                                     pango_attr_line_height_new (layout->line_spacing));
     }
 
-  if (glyphs->num_glyphs >= 2 &&
-      glyphs->log_clusters[glyph] == glyphs->log_clusters[glyph + (item->analysis.level % 2 ? 1 : -1)])
+  if (layout->single_paragraph)
     {
-
-      DEBUG1 ("zero final space: its a cluster");
-      return;
+      attrs = ensure_attrs (layout, attrs);
+      pango_attr_list_insert_before (attrs,
+                                     pango_attr_paragraph_new ());
     }
 
-  DEBUG1 ("zero line final space: collapsing the space");
-  glyphs->glyphs[glyph].geometry.width = 0;
-  glyphs->glyphs[glyph].glyph = PANGO_GLYPH_EMPTY;
+  if (attrs)
+    return attrs;
+
+  return pango_attr_list_ref (layout->attrs);
 }
 
-/* When doing shaping, we add the letter spacing value for a
- * run after every grapheme in the run. This produces ugly
- * asymmetrical results, so what this routine is redistributes
- * that space to the beginning and the end of the run.
- *
- * We also trim the letter spacing from runs adjacent to
- * tabs and from the outside runs of the lines so that things
- * line up properly. The line breaking and tab positioning
- * were computed without this trimming so they are no longer
- * exactly correct, but this won't be very noticeable in most
- * cases.
- */
-static void
-adjust_line_letter_spacing (PangoLayoutLine *line,
-                            ParaBreakState  *state)
+static gboolean
+ends_with_paragraph_separator (PangoLayout *layout)
 {
-  PangoLayout *layout = line->layout;
-  gboolean reversed;
-  PangoLayoutRun *last_run;
-  int tab_adjustment;
-  GSList *l;
-
-  /* If we have tab stops and the resolved direction of the
-   * line is RTL, then we need to walk through the line
-   * in reverse direction to figure out the corrections for
-   * tab stops.
-   */
-  reversed = FALSE;
-  if (line->resolved_dir == PANGO_DIRECTION_RTL)
-    {
-      for (l = line->runs; l; l = l->next)
-        if (is_tab_run (layout, l->data))
-          {
-            line->runs = g_slist_reverse (line->runs);
-            reversed = TRUE;
-            break;
-          }
-    }
-
-  /* Walk over the runs in the line, redistributing letter
-   * spacing from the end of the run to the start of the
-   * run and trimming letter spacing from the ends of the
-   * runs adjacent to the ends of the line or tab stops.
-   *
-   * We accumulate a correction factor from this trimming
-   * which we add onto the next tab stop space to keep the
-   * things properly aligned.
-   */
-  last_run = NULL;
-  tab_adjustment = 0;
-  for (l = line->runs; l; l = l->next)
-    {
-      PangoLayoutRun *run = l->data;
-      PangoLayoutRun *next_run = l->next ? l->next->data : NULL;
-
-      if (is_tab_run (layout, run))
-        {
-          pad_glyphstring_right (run->glyphs, state, tab_adjustment);
-          tab_adjustment = 0;
-        }
-      else
-        {
-          PangoLayoutRun *visual_next_run = reversed ? last_run : next_run;
-          PangoLayoutRun *visual_last_run = reversed ? next_run : last_run;
-          int run_spacing = get_item_letter_spacing (run->item);
-          int space_left, space_right;
-
-          distribute_letter_spacing (run_spacing, &space_left, &space_right);
-
-          if (run->glyphs->glyphs[0].geometry.width == 0)
-            {
-              /* we've zeroed this space glyph at the end of line, now remove
-               * the letter spacing added to its adjacent glyph */
-              pad_glyphstring_left (run->glyphs, state, - space_left);
-            }
-          else if (!visual_last_run || is_tab_run (layout, visual_last_run))
-            {
-              pad_glyphstring_left (run->glyphs, state, - space_left);
-              tab_adjustment += space_left;
-            }
-
-          if (run->glyphs->glyphs[run->glyphs->num_glyphs - 1].geometry.width == 0)
-            {
-              /* we've zeroed this space glyph at the end of line, now remove
-               * the letter spacing added to its adjacent glyph */
-              pad_glyphstring_right (run->glyphs, state, - space_right);
-            }
-          else if (!visual_next_run || is_tab_run (layout, visual_next_run))
-            {
-              pad_glyphstring_right (run->glyphs, state, - space_right);
-              tab_adjustment += space_right;
-            }
-        }
-
-      last_run = run;
-    }
+  if (layout->single_paragraph)
+    return FALSE;
 
-  if (reversed)
-    line->runs = g_slist_reverse (line->runs);
+  return g_str_has_suffix (layout->text, "\n") ||
+         g_str_has_suffix (layout->text, "\r") ||
+         g_str_has_suffix (layout->text, "\r\n") ||
+         g_str_has_suffix (layout->text, "
");
 }
 
 static void
-justify_clusters (PangoLayoutLine *line,
-                  ParaBreakState  *state)
+ensure_lines (PangoLayout *layout)
 {
-  const gchar *text = line->layout->text;
-  const PangoLogAttr *log_attrs = line->layout->log_attrs;
-
-  int total_remaining_width, total_gaps = 0;
-  int added_so_far, gaps_so_far;
-  gboolean is_hinted;
-  GSList *run_iter;
-  enum {
-    MEASURE,
-    ADJUST
-  } mode;
-
-  total_remaining_width = state->remaining_width;
-  if (total_remaining_width <= 0)
+  PangoLineBreaker *breaker;
+  PangoAttrList *attrs;
+  int x, y, width;
+  int line_no;
+
+  check_context_changed (layout);
+
+  if (layout->lines)
     return;
 
-  /* hint to full pixel if total remaining width was so */
-  is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0;
+  breaker = pango_line_breaker_new (layout->context);
 
-  for (mode = MEASURE; mode <= ADJUST; mode++)
-    {
-      gboolean leftedge = TRUE;
-      PangoGlyphString *rightmost_glyphs = NULL;
-      int rightmost_space = 0;
-      int residual = 0;
+  pango_line_breaker_set_tabs (breaker, layout->tabs);
+  pango_line_breaker_set_base_dir (breaker,
+                                   layout->auto_dir
+                                     ? PANGO_DIRECTION_NEUTRAL
+                                     : pango_context_get_base_dir (layout->context));
 
-      added_so_far = 0;
-      gaps_so_far = 0;
+  attrs = get_effective_attributes (layout);
+  pango_line_breaker_add_text (breaker, layout->text ? layout->text : "", -1, attrs);
+  if (attrs)
+    pango_attr_list_unref (attrs);
 
-      for (run_iter = line->runs; run_iter; run_iter = run_iter->next)
-        {
-          PangoLayoutRun *run = run_iter->data;
-          PangoGlyphString *glyphs = run->glyphs;
-          PangoGlyphItemIter cluster_iter;
-          gboolean have_cluster;
-          int dir;
-          int offset;
-
-          dir = run->item->analysis.level % 2 == 0 ? +1 : -1;
-
-          offset = run->item->char_offset;
-
-          for (have_cluster = dir > 0 ?
-                 pango_glyph_item_iter_init_start (&cluster_iter, run, text) :
-                 pango_glyph_item_iter_init_end   (&cluster_iter, run, text);
-               have_cluster;
-               have_cluster = dir > 0 ?
-                 pango_glyph_item_iter_next_cluster (&cluster_iter) :
-                 pango_glyph_item_iter_prev_cluster (&cluster_iter))
-            {
-              int i;
-              int width = 0;
-
-              /* don't expand in the middle of graphemes */
-              if (!log_attrs[offset + cluster_iter.start_char].is_cursor_position)
-                continue;
-
-              for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir)
-                width += glyphs->glyphs[i].geometry.width;
-
-              /* also don't expand zero-width clusters. */
-              if (width == 0)
-                continue;
-
-              gaps_so_far++;
-
-              if (mode == ADJUST)
-                {
-                  int leftmost, rightmost;
-                  int adjustment, space_left, space_right;
-
-                  adjustment = total_remaining_width / total_gaps + residual;
-                  if (is_hinted)
-                  {
-                    int old_adjustment = adjustment;
-                    adjustment = PANGO_UNITS_ROUND (adjustment);
-                    residual = old_adjustment - adjustment;
-                  }
-                  /* distribute to before/after */
-                  distribute_letter_spacing (adjustment, &space_left, &space_right);
-
-                  if (cluster_iter.start_glyph < cluster_iter.end_glyph)
-                  {
-                    /* LTR */
-                    leftmost  = cluster_iter.start_glyph;
-                    rightmost = cluster_iter.end_glyph - 1;
-                  }
-                  else
-                  {
-                    /* RTL */
-                    leftmost  = cluster_iter.end_glyph + 1;
-                    rightmost = cluster_iter.start_glyph;
-                  }
-                  /* Don't add to left-side of left-most glyph of left-most non-zero run. */
-                  if (leftedge)
-                    leftedge = FALSE;
-                  else
-                  {
-                    glyphs->glyphs[leftmost].geometry.width    += space_left ;
-                    glyphs->glyphs[leftmost].geometry.x_offset += space_left ;
-                    added_so_far += space_left;
-                  }
-                  /* Don't add to right-side of right-most glyph of right-most non-zero run. */
-                  {
-                    /* Save so we can undo later. */
-                    rightmost_glyphs = glyphs;
-                    rightmost_space = space_right;
-
-                    glyphs->glyphs[rightmost].geometry.width  += space_right;
-                    added_so_far += space_right;
-                  }
-                }
-            }
-        }
+  layout->lines = pango_lines_new ();
 
-      if (mode == MEASURE)
-        {
-          total_gaps = gaps_so_far - 1;
+  x = y = 0;
+  line_no = 0;
+  while (pango_line_breaker_has_line (breaker))
+    {
+      PangoLine *line;
+      PangoRectangle ext;
+      int offset;
+      PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_NONE;
 
-          if (total_gaps == 0)
-            {
-              /* a single cluster, can't really justify it */
-              return;
-            }
+      if ((line_no == 0) == (layout->indent > 0))
+        {
+          x = abs (layout->indent);
+          width = layout->width - x;
         }
-      else /* mode == ADJUST */
+      else
         {
-          if (rightmost_glyphs)
-           {
-             rightmost_glyphs->glyphs[rightmost_glyphs->num_glyphs - 1].geometry.width -= rightmost_space;
-             added_so_far -= rightmost_space;
-           }
+          x = 0;
+          width = layout->width;
         }
-    }
 
-  state->remaining_width -= added_so_far;
-}
-
-static void
-justify_words (PangoLayoutLine *line,
-               ParaBreakState  *state)
-{
-  const gchar *text = line->layout->text;
-  const PangoLogAttr *log_attrs = line->layout->log_attrs;
-
-  int total_remaining_width, total_space_width = 0;
-  int added_so_far, spaces_so_far;
-  gboolean is_hinted;
-  GSList *run_iter;
-  enum {
-    MEASURE,
-    ADJUST
-  } mode;
-
-  total_remaining_width = state->remaining_width;
-  if (total_remaining_width <= 0)
-    return;
-
-  /* hint to full pixel if total remaining width was so */
-  is_hinted = (total_remaining_width & (PANGO_SCALE - 1)) == 0;
+      if (layout->height < 0 && line_no + 1 == - layout->height)
+        ellipsize = layout->ellipsize;
 
-  for (mode = MEASURE; mode <= ADJUST; mode++)
-    {
-      added_so_far = 0;
-      spaces_so_far = 0;
+retry:
+      line = pango_line_breaker_next_line (breaker, x, width, layout->wrap, ellipsize);
+      pango_line_get_extents (line, NULL, &ext);
 
-      for (run_iter = line->runs; run_iter; run_iter = run_iter->next)
+      if (layout->height >= 0 && y + 2 * ext.height >= layout->height &&
+          ellipsize != layout->ellipsize)
         {
-          PangoLayoutRun *run = run_iter->data;
-          PangoGlyphString *glyphs = run->glyphs;
-          PangoGlyphItemIter cluster_iter;
-          gboolean have_cluster;
-          int offset;
-
-          offset = run->item->char_offset;
-
-          for (have_cluster = pango_glyph_item_iter_init_start (&cluster_iter, run, text);
-               have_cluster;
-               have_cluster = pango_glyph_item_iter_next_cluster (&cluster_iter))
+          if (pango_line_breaker_undo_line (breaker, line))
             {
-              int i;
-              int dir;
-
-              if (!log_attrs[offset + cluster_iter.start_char].is_expandable_space)
-                continue;
-
-              dir = (cluster_iter.start_glyph < cluster_iter.end_glyph) ? 1 : -1;
-              for (i = cluster_iter.start_glyph; i != cluster_iter.end_glyph; i += dir)
-                {
-                  int glyph_width = glyphs->glyphs[i].geometry.width;
-
-                  if (glyph_width == 0)
-                    continue;
-
-                  spaces_so_far += glyph_width;
-
-                  if (mode == ADJUST)
-                    {
-                      int adjustment;
-
-                      adjustment = ((guint64) spaces_so_far * total_remaining_width) / total_space_width - 
added_so_far;
-                      if (is_hinted)
-                        adjustment = PANGO_UNITS_ROUND (adjustment);
-
-                      glyphs->glyphs[i].geometry.width += adjustment;
-                      added_so_far += adjustment;
-                    }
-                }
+              g_clear_pointer (&line, pango_line_free);
+              ellipsize = layout->ellipsize;
+              goto retry;
             }
         }
 
-      if (mode == MEASURE)
+      /* Handle alignment and justification */
+      offset = 0;
+      switch (layout->alignment)
         {
-          total_space_width = spaces_so_far;
-
-          if (total_space_width == 0)
-            {
-              justify_clusters (line, state);
-              return;
-            }
+        case PANGO_ALIGN_LEFT:
+          break;
+        case PANGO_ALIGN_CENTER:
+          if (ext.width < width)
+            offset = (width - ext.width) / 2;
+          break;
+        case PANGO_ALIGN_RIGHT:
+          if (ext.width < width)
+            offset = width - ext.width;
+          break;
+        case PANGO_ALIGN_JUSTIFY:
+          if (!pango_line_is_paragraph_end (line))
+            line = pango_line_justify (line, width);
+          break;
+        case PANGO_ALIGN_JUSTIFY_ALL:
+          line = pango_line_justify (line, width);
+          break;
+        default: g_assert_not_reached ();
         }
-    }
-
-  state->remaining_width -= added_so_far;
-}
-
-typedef struct {
-  PangoAttribute *attr;
-  int x_offset;
-  int y_offset;
-} BaselineItem;
-
-static void
-collect_baseline_shift (ParaBreakState *state,
-                        PangoItem      *item,
-                        PangoItem      *prev,
-                        int            *start_x_offset,
-                        int            *start_y_offset,
-                        int            *end_x_offset,
-                        int            *end_y_offset)
-{
-  *start_x_offset = 0;
-  *start_y_offset = 0;
-  *end_x_offset = 0;
-  *end_y_offset = 0;
-
-  for (GSList *l = item->analysis.extra_attrs; l; l = l->next)
-    {
-      PangoAttribute *attr = l->data;
-
-      if (attr->klass->type == PANGO_ATTR_RISE)
-        {
-          int value = ((PangoAttrInt *)attr)->value;
 
-          *start_y_offset += value;
-          *end_y_offset -= value;
-        }
-      else if (attr->klass->type == PANGO_ATTR_BASELINE_SHIFT)
-        {
-          if (attr->start_index == item->offset)
-            {
-              BaselineItem *entry;
-              int value;
-
-              entry = g_new0 (BaselineItem, 1);
-              entry->attr = attr;
-              state->baseline_shifts = g_list_prepend (state->baseline_shifts, entry);
-
-              value = ((PangoAttrInt *)attr)->value;
-
-              if (value > 1024 || value < -1024)
-                {
-                  entry->y_offset = value;
-                  /* FIXME: compute an x_offset from value to italic angle */
-                }
-              else
-                {
-                  int superscript_x_offset = 0;
-                  int superscript_y_offset = 0;
-                  int subscript_x_offset = 0;
-                  int subscript_y_offset = 0;
-
-
-                  if (prev && prev->analysis.font)
-                    {
-                      hb_font_t *hb_font = pango_font_get_hb_font (prev->analysis.font);
-                      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET, 
&superscript_y_offset);
-                      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET, 
&superscript_x_offset);
-                      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET, 
&subscript_y_offset);
-                      hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET, 
&subscript_x_offset);
-                    }
-
-                  if (superscript_y_offset == 0)
-                    superscript_y_offset = 5000;
-                  if (subscript_y_offset == 0)
-                    subscript_y_offset = 5000;
-
-                  switch (value)
-                    {
-                    case PANGO_BASELINE_SHIFT_NONE:
-                      entry->x_offset = 0;
-                      entry->y_offset = 0;
-                      break;
-                    case PANGO_BASELINE_SHIFT_SUPERSCRIPT:
-                      entry->x_offset = superscript_x_offset;
-                      entry->y_offset = superscript_y_offset;
-                      break;
-                    case PANGO_BASELINE_SHIFT_SUBSCRIPT:
-                      entry->x_offset = subscript_x_offset;
-                      entry->y_offset = -subscript_y_offset;
-                      break;
-                    default:
-                      g_assert_not_reached ();
-                    }
-                }
-
-              *start_x_offset += entry->x_offset;
-              *start_y_offset += entry->y_offset;
-            }
+      pango_lines_add_line (layout->lines, line, x + offset, y - ext.y);
 
-          if (attr->end_index == item->offset + item->length)
-            {
-              GList *t;
-
-              for (t = state->baseline_shifts; t; t = t->next)
-                {
-                  BaselineItem *entry = t->data;
-
-                  if (attr->start_index == entry->attr->start_index &&
-                      attr->end_index == entry->attr->end_index &&
-                      ((PangoAttrInt *)attr)->value == ((PangoAttrInt *)entry->attr)->value)
-                    {
-                      *end_x_offset -= entry->x_offset;
-                      *end_y_offset -= entry->y_offset;
-                    }
-
-                  state->baseline_shifts = g_list_remove (state->baseline_shifts, entry);
-                  g_free (entry);
-                  break;
-                }
-              if (t == NULL)
-                g_warning ("Baseline attributes mismatch\n");
-            }
-        }
+      y += ext.height;
+      line_no++;
     }
-}
 
-static void
-apply_baseline_shift (PangoLayoutLine *line,
-                       ParaBreakState  *state)
-{
-  int y_offset = 0;
-  PangoItem *prev = NULL;
-  hb_position_t baseline_adjustment = 0;
-#if HB_VERSION_ATLEAST(4,0,0)
-  hb_ot_layout_baseline_tag_t baseline_tag = 0;
-  hb_position_t baseline;
-  hb_position_t run_baseline;
-#endif
-
-  for (GSList *l = line->runs; l; l = l->next)
+  /* Append an empty line if we end with a newline.
+   * And always provide at least one line
+   */
+  if (pango_lines_get_line_count (layout->lines) == 0 ||
+      ends_with_paragraph_separator (layout))
     {
-      PangoLayoutRun *run = l->data;
-      PangoItem *item = run->item;
-      int start_x_offset, end_x_offset;
-      int start_y_offset, end_y_offset;
-#if HB_VERSION_ATLEAST(4,0,0)
-      hb_font_t *hb_font;
-      hb_script_t script;
-      hb_language_t language;
-      hb_direction_t direction;
-      hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
-      hb_tag_t lang_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
-      unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
-      unsigned int lang_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
-#endif
-
-      if (item->analysis.font == NULL)
-        continue;
-
-#if HB_VERSION_ATLEAST(4,0,0)
-      hb_font = pango_font_get_hb_font (item->analysis.font);
-
-      script = (hb_script_t) g_unicode_script_to_iso15924 (item->analysis.script);
-      language = hb_language_from_string (pango_language_to_string (item->analysis.language), -1);
-      hb_ot_tags_from_script_and_language (script, language,
-                                           &script_count, script_tags,
-                                           &lang_count, lang_tags);
-
-      if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
-        direction = HB_DIRECTION_TTB;
-      else
-        direction = HB_DIRECTION_LTR;
+      LineData *data;
+      int start_index;
+      int start_offset;
+      int offset;
+      PangoLine *line;
+      PangoRectangle ext;
 
-      if (baseline_tag == 0)
+      if (pango_lines_get_line_count (layout->lines) > 0)
         {
-          if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
-            baseline_tag = HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL;
-          else
-            baseline_tag = hb_ot_layout_get_horizontal_baseline_tag_for_script (script);
-          hb_ot_layout_get_baseline_with_fallback (hb_font,
-                                                   baseline_tag,
-                                                   direction,
-                                                   script_tags[script_count - 1],
-                                                   lang_count ? lang_tags[lang_count - 1] : HB_TAG_NONE,
-                                                   &run_baseline);
-          baseline = run_baseline;
+          PangoLine *last;
+
+          last = pango_lines_get_line (layout->lines,
+                                       pango_lines_get_line_count (layout->lines) - 1,
+                                       NULL, NULL);
+          data = line_data_ref (last->data);
+          start_index = data->length;
+          start_offset = last->data->n_chars;
+          offset = MAX (layout->indent, 0);
         }
       else
         {
-          hb_ot_layout_get_baseline_with_fallback (hb_font,
-                                                   baseline_tag,
-                                                   direction,
-                                                   script_tags[script_count - 1],
-                                                   lang_count ? lang_tags[lang_count - 1] : HB_TAG_NONE,
-                                                   &run_baseline);
+          data = line_data_new ();
+          data->text = g_strdup ("");
+          data->length = 0;
+          data->attrs = get_effective_attributes (layout);
+          data->log_attrs = g_new0 (PangoLogAttr, 1);
+          data->log_attrs[0].is_cursor_position = TRUE;
+          start_index = 0;
+          start_offset = 0;
+          offset = 0;
         }
 
-      /* Don't do baseline adjustment in vertical, since the renderer
-       * is still doing its own baseline shifting there
-       */
-      if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
-        baseline_adjustment = 0;
-      else
-        baseline_adjustment = baseline - run_baseline;
-#endif
-
-      collect_baseline_shift (state, item, prev, &start_x_offset, &start_y_offset, &end_x_offset, 
&end_y_offset);
-
-      y_offset += start_y_offset + baseline_adjustment;
+      line = pango_line_new (layout->context, data);
+      line->starts_paragraph = TRUE;
+      line->ends_paragraph = TRUE;
+      line->start_index = start_index;
+      line->length = 0;
+      line->start_offset = start_offset;
+      line->n_chars = 0;
 
-      run->y_offset = y_offset;
-      run->start_x_offset = start_x_offset;
-      run->end_x_offset = end_x_offset;
+      pango_line_get_extents (line, NULL, &ext);
 
-      y_offset += end_y_offset - baseline_adjustment;
+      pango_lines_add_line (layout->lines, line, x + offset, y - ext.y);
 
-      prev = item;
+      line_data_unref (data);
     }
-}
-
-static void
-pango_layout_line_postprocess (PangoLayoutLine *line,
-                               ParaBreakState  *state,
-                               gboolean         wrapped)
-{
-  gboolean ellipsized = FALSE;
-  
-  DEBUG1 ("postprocessing line, %s", wrapped ? "wrapped" : "not wrapped");
-
-  add_missing_hyphen (line, state, line->runs->data);
-  DEBUG ("after hyphen addition", line, state);
-
-  /* Truncate the logical-final whitespace in the line if we broke the line at it */
-  if (wrapped)
-    zero_line_final_space (line, state, line->runs->data);
-
-  DEBUG ("after removing final space", line, state);
-
-  /* Reverse the runs */
-  line->runs = g_slist_reverse (line->runs);
-
-  apply_baseline_shift (line, state);
-
-  /* Ellipsize the line if necessary */
-  if (G_UNLIKELY (state->line_width >= 0 &&
-                  should_ellipsize_current_line (line->layout, state)))
-    {
-      PangoShapeFlags shape_flags = PANGO_SHAPE_NONE;
-
-      if (pango_context_get_round_glyph_positions (line->layout->context))
-        shape_flags |= PANGO_SHAPE_ROUND_POSITIONS;
 
-      ellipsized = _pango_layout_line_ellipsize (line, state->attrs, shape_flags, state->line_width);
-    }
+  g_object_unref (breaker);
+}
 
-  /* Now convert logical to visual order */
-  pango_layout_line_reorder (line);
+/* }}} */
+/* {{{ Public API */
 
-  DEBUG ("after reordering", line, state);
+/**
+ * pango_layout_new:
+ * @context: a `PangoContext`
+ *
+ * Creates a new `PangoLayout` with attribute initialized to
+ * default values for a particular `PangoContext`
+ *
+ * Return value: a newly allocated `PangoLayout`
+ */
+PangoLayout *
+pango_layout_new (PangoContext *context)
+{
+  g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
 
-  /* Fixup letter spacing between runs */
-  adjust_line_letter_spacing (line, state);
+  return g_object_new (PANGO_TYPE_LAYOUT, "context", context, NULL);
+}
 
-  DEBUG ("after letter spacing", line, state);
+/**
+ * pango_layout_copy:
+ * @layout: a `PangoLayout`
+ *
+ * Creates a deep copy-by-value of the layout.
+ *
+ * The attribute list, tab array, and text from the original layout
+ * are all copied by value.
+ *
+ * Return value: (transfer full): the newly allocated `PangoLayout`
+ */
+PangoLayout *
+pango_layout_copy (PangoLayout *layout)
+{
+  PangoLayout *copy;
 
-  /* Distribute extra space between words if justifying and line was wrapped */
-  if (line->layout->justify && (wrapped || ellipsized || line->layout->justify_last_line))
-    {
-      /* if we ellipsized, we don't have remaining_width set */
-      if (state->remaining_width < 0)
-        state->remaining_width = state->line_width - pango_layout_line_get_width (line);
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-      justify_words (line, state);
-    }
+  copy = pango_layout_new (layout->context);
 
-  DEBUG ("after justification", line, state);
+  copy->text = g_strdup (layout->text);
+  copy->length = layout->length;
+  if (layout->attrs)
+    copy->attrs = pango_attr_list_copy (layout->attrs);
+  if (layout->font_desc)
+    copy->font_desc = pango_font_description_copy (layout->font_desc);
+  copy->line_spacing = layout->line_spacing;
+  copy->width = layout->width;
+  copy->height = layout->height;
+  if (layout->tabs)
+    copy->tabs = pango_tab_array_copy (layout->tabs);
+  copy->single_paragraph = layout->single_paragraph;
+  copy->wrap = layout->wrap;
+  copy->indent = layout->indent;
+  copy->serial = layout->serial;
+  copy->context_serial = layout->context_serial;
+  copy->alignment = layout->alignment;
+  copy->ellipsize = layout->ellipsize;
+  copy->auto_dir = layout->auto_dir;
 
-  line->layout->is_wrapped |= wrapped;
-  line->layout->is_ellipsized |= ellipsized;
+  return copy;
 }
 
-static int
-next_cluster_start (PangoGlyphString *gs,
-                    int               cluster_start)
+/**
+ * pango_layout_get_serial:
+ * @layout: a `PangoLayout`
+ *
+ * Returns the current serial number of the layout.
+ *
+ * The serial number is initialized to an small number larger than zero
+ * when a new layout is created and is increased whenever the layout is
+ * changed using any of the setter functions, or the `PangoContext` it
+ * uses has changed.
+ *
+ * The serial may wrap, but will never have the value 0. Since it can
+ * wrap, never compare it with "less than", always use "not equals".
+ *
+ * This can be used to automatically detect changes to a `PangoLayout`,
+ * and is useful for example to decide whether a layout needs redrawing.
+ *
+ * Return value: The current serial number of @layout
+ */
+guint
+pango_layout_get_serial (PangoLayout *layout)
 {
-  int i;
-
-  i = cluster_start + 1;
-  while (i < gs->num_glyphs)
-    {
-      if (gs->glyphs[i].attr.is_cluster_start)
-        return i;
-
-      i++;
-    }
+  check_context_changed (layout);
 
-  return gs->num_glyphs;
+  return layout->serial;
 }
 
-static int
-cluster_width (PangoGlyphString *gs,
-               int               cluster_start)
+/**
+ * pango_layout_context_changed:
+ * @layout: a `PangoLayout`
+ *
+ * Forces recomputation of any state in the `PangoLayout` that
+ * might depend on the layout's context.
+ *
+ * This function should be called if you make changes to the
+ * context subsequent to creating the layout.
+ */
+void
+pango_layout_context_changed (PangoLayout *layout)
 {
-  int i;
-  int width;
-
-  width = gs->glyphs[cluster_start].geometry.width;
-  i = cluster_start + 1;
-  while (i < gs->num_glyphs)
-    {
-      if (gs->glyphs[i].attr.is_cluster_start)
-        break;
-
-      width += gs->glyphs[i].geometry.width;
-      i++;
-    }
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  return width;
+  layout_changed (layout);
 }
 
-static inline void
-offset_y (PangoLayoutIter *iter,
-          int             *y)
-{
-  *y += iter->line_extents[iter->line_index].baseline;
-}
+/* {{{ Property getters and setters */
 
-/* Sets up the iter for the start of a new cluster. cluster_start_index
- * is the byte index of the cluster start relative to the run.
+/**
+ * pango_layout_get_context:
+ * @layout: a `PangoLayout`
+ *
+ * Retrieves the `PangoContext` used for this layout.
+ *
+ * Return value: (transfer none): the `PangoContext` for the layout
  */
-static void
-update_cluster (PangoLayoutIter *iter,
-                int              cluster_start_index)
+PangoContext *
+pango_layout_get_context (PangoLayout *layout)
 {
-  char             *cluster_text;
-  PangoGlyphString *gs;
-  int               cluster_length;
-
-  iter->character_position = 0;
-
-  gs = iter->run->glyphs;
-  iter->cluster_width = cluster_width (gs, iter->cluster_start);
-  iter->next_cluster_glyph = next_cluster_start (gs, iter->cluster_start);
-
-  if (iter->ltr)
-    {
-      /* For LTR text, finding the length of the cluster is easy
-       * since logical and visual runs are in the same direction.
-       */
-      if (iter->next_cluster_glyph < gs->num_glyphs)
-        cluster_length = gs->log_clusters[iter->next_cluster_glyph] - cluster_start_index;
-      else
-        cluster_length = iter->run->item->length - cluster_start_index;
-    }
-  else
-    {
-      /* For RTL text, we have to scan backwards to find the previous
-       * visual cluster which is the next logical cluster.
-       */
-      int i = iter->cluster_start;
-      while (i > 0 && gs->log_clusters[i - 1] == cluster_start_index)
-        i--;
-
-      if (i == 0)
-        cluster_length = iter->run->item->length - cluster_start_index;
-      else
-        cluster_length = gs->log_clusters[i - 1] - cluster_start_index;
-    }
-
-  cluster_text = iter->layout->text + iter->run->item->offset + cluster_start_index;
-  iter->cluster_num_chars = pango_utf8_strlen (cluster_text, cluster_length);
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-  if (iter->ltr)
-    iter->index = cluster_text - iter->layout->text;
-  else
-    iter->index = g_utf8_prev_char (cluster_text + cluster_length) - iter->layout->text;
+  return layout->context;
 }
 
-static void
-update_run (PangoLayoutIter *iter,
-            int              run_start_index)
-{
-  const Extents *line_ext = &iter->line_extents[iter->line_index];
-
-  /* Note that in iter_new() the iter->run_width
-   * is garbage but we don't use it since we're on the first run of
-   * a line.
-   */
-  if (iter->run_list_link == iter->line->runs)
-    iter->run_x = line_ext->logical_rect.x;
-  else
-    {
-      iter->run_x += iter->end_x_offset + iter->run_width;
-      if (iter->run)
-        iter->run_x += iter->run->start_x_offset;
-    }
-
-  if (iter->run)
-    {
-      iter->run_width = pango_glyph_string_get_width (iter->run->glyphs);
-      iter->end_x_offset = iter->run->end_x_offset;
-    }
-  else
-    {
-      /* The empty run at the end of a line */
-      iter->run_width = 0;
-      iter->end_x_offset = 0;
-    }
+/**
+ * pango_layout_set_text:
+ * @layout: a `PangoLayout`
+ * @text: the text
+ * @length: maximum length of @text, in bytes. -1 indicates that
+ *   the string is nul-terminated
+ *
+ * Sets the text of the layout.
+ */
+void
+pango_layout_set_text (PangoLayout *layout,
+                       const char  *text,
+                       int          length)
+{
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  if (iter->run)
-    iter->ltr = (iter->run->item->analysis.level % 2) == 0;
-  else
-    iter->ltr = TRUE;
+  if (length < 0)
+    length = strlen (text);
 
-  iter->cluster_start = 0;
-  iter->cluster_x = iter->run_x;
+  g_free (layout->text);
+  layout->text = g_strndup (text, length);
+  layout->length = length;
 
-  if (iter->run)
-    {
-      update_cluster (iter, iter->run->glyphs->log_clusters[0]);
-    }
-  else
-    {
-      iter->cluster_width = 0;
-      iter->character_position = 0;
-      iter->cluster_num_chars = 0;
-      iter->index = run_start_index;
-    }
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_TEXT]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_copy:
- * @iter: (nullable): a `PangoLayoutIter`
+ * pango_layout_get_text:
+ * @layout: a `PangoLayout`
  *
- * Copies a `PangoLayoutIter`.
+ * Gets the text in the layout.
  *
- * Return value: (nullable): the newly allocated `PangoLayoutIter`
+ * The returned text should not be freed or modified.
  *
- * Since: 1.20
+ * Return value: (transfer none): the text in the @layout
  */
-PangoLayoutIter *
-pango_layout_iter_copy (PangoLayoutIter *iter)
+const char *
+pango_layout_get_text (PangoLayout *layout)
 {
-  PangoLayoutIter *new;
-
-  if (iter == NULL)
-    return NULL;
-
-  new = g_slice_new (PangoLayoutIter);
-
-  new->layout = g_object_ref (iter->layout);
-  new->line_list_link = iter->line_list_link;
-  new->line = iter->line;
-  pango_layout_line_ref (new->line);
-
-  new->run_list_link = iter->run_list_link;
-  new->run = iter->run;
-  new->index = iter->index;
-
-  new->line_extents = NULL;
-  if (iter->line_extents != NULL)
-    {
-      new->line_extents = g_memdup2 (iter->line_extents,
-                                     iter->layout->line_count * sizeof (Extents));
-
-    }
-  new->line_index = iter->line_index;
-
-  new->run_x = iter->run_x;
-  new->run_width = iter->run_width;
-  new->ltr = iter->ltr;
-
-  new->cluster_x = iter->cluster_x;
-  new->cluster_width = iter->cluster_width;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-  new->cluster_start = iter->cluster_start;
-  new->next_cluster_glyph = iter->next_cluster_glyph;
+  return layout->text;
+}
 
-  new->cluster_num_chars = iter->cluster_num_chars;
-  new->character_position = iter->character_position;
+/**
+ * pango_layout_set_attributes:
+ * @layout: a `PangoLayout`
+ * @attrs: (nullable) (transfer none): a `PangoAttrList`
+ *
+ * Sets the attributes for a layout object.
+ *
+ * References @attrs, so the caller can unref its reference.
+ */
+void
+pango_layout_set_attributes (PangoLayout   *layout,
+                             PangoAttrList *attrs)
+{
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  new->layout_width = iter->layout_width;
+  g_clear_pointer (&layout->attrs, pango_attr_list_unref);
+  layout->attrs = attrs;
+  if (layout->attrs)
+    pango_attr_list_ref (layout->attrs);
 
-  return new;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_ATTRIBUTES]);
+  layout_changed (layout);
 }
 
-G_DEFINE_BOXED_TYPE (PangoLayoutIter, pango_layout_iter,
-                     pango_layout_iter_copy,
-                     pango_layout_iter_free);
-
 /**
- * pango_layout_get_iter:
+ * pango_layout_get_attributes:
  * @layout: a `PangoLayout`
  *
- * Returns an iterator to iterate over the visual extents of the layout.
+ * Gets the attribute list for the layout, if any.
  *
- * Return value: the new `PangoLayoutIter`
+ * Return value: (transfer none) (nullable): a `PangoAttrList`
  */
-PangoLayoutIter*
-pango_layout_get_iter (PangoLayout *layout)
+PangoAttrList *
+pango_layout_get_attributes (PangoLayout *layout)
 {
-  PangoLayoutIter *iter;
-
   g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-  iter = g_slice_new (PangoLayoutIter);
-
-  _pango_layout_get_iter (layout, iter);
-
-  return iter;
+  return layout->attrs;
 }
 
+/**
+ * pango_layout_set_font_description:
+ * @layout: a `PangoLayout`
+ * @desc: (nullable): the new `PangoFontDescription`
+ *
+ * Sets the default font description for the layout.
+ *
+ * If no font description is set on the layout, the
+ * font description from the layout's context is used.
+ *
+ * This method is a shorthand for adding a font-desc attribute.
+ */
 void
-_pango_layout_get_iter (PangoLayout    *layout,
-                        PangoLayoutIter*iter)
+pango_layout_set_font_description (PangoLayout                *layout,
+                                   const PangoFontDescription *desc)
 {
-  int run_start_index;
-
   g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  iter->layout = g_object_ref (layout);
-
-  pango_layout_check_lines (layout);
-
-  iter->line_list_link = layout->lines;
-  iter->line = iter->line_list_link->data;
-  pango_layout_line_ref (iter->line);
-
-  run_start_index = iter->line->start_index;
-  iter->run_list_link = iter->line->runs;
-
-  if (iter->run_list_link)
+  if (desc != layout->font_desc &&
+      (!desc || !layout->font_desc || !pango_font_description_equal (desc, layout->font_desc)))
     {
-      iter->run = iter->run_list_link->data;
-      run_start_index = iter->run->item->offset;
-    }
-  else
-    iter->run = NULL;
-
-  iter->line_extents = NULL;
+      if (layout->font_desc)
+        pango_font_description_free (layout->font_desc);
 
-  if (layout->width == -1)
-    {
-      PangoRectangle logical_rect;
+      layout->font_desc = desc ? pango_font_description_copy (desc) : NULL;
 
-      pango_layout_get_extents_internal (layout,
-                                         NULL,
-                                         &logical_rect,
-                                         &iter->line_extents);
-      iter->layout_width = logical_rect.width;
-    }
-  else
-    {
-      pango_layout_get_extents_internal (layout,
-                                         NULL,
-                                         NULL,
-                                         &iter->line_extents);
-      iter->layout_width = layout->width;
+      g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_FONT_DESCRIPTION]);
+      layout_changed (layout);
     }
-  iter->line_index = 0;
-
-  update_run (iter, run_start_index);
 }
 
-void
-_pango_layout_iter_destroy (PangoLayoutIter *iter)
+/**
+ * pango_layout_get_font_description:
+ * @layout: a `PangoLayout`
+ *
+ * Gets the font description for the layout, if any.
+ *
+ * Return value: (transfer none) (nullable): a pointer to the
+ *   layout's font description, or %NULL if the font description
+ *   from the layout's context is inherited.
+ *
+ * Since: 1.8
+ */
+const PangoFontDescription *
+pango_layout_get_font_description (PangoLayout *layout)
 {
-  if (iter == NULL)
-    return;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-  g_free (iter->line_extents);
-  pango_layout_line_unref (iter->line);
-  g_object_unref (iter->layout);
+  return layout->font_desc;
 }
 
 /**
- * pango_layout_iter_free:
- * @iter: (nullable): a `PangoLayoutIter`, may be %NULL
+ * pango_layout_set_line_spacing:
+ * @layout: a `PangoLayout`
+ * @line_spacing: the new line spacing factor
+ *
+ * Sets a factor for line spacing.
  *
- * Frees an iterator that's no longer in use.
- **/
+ * Typical values are: 0, 1, 1.5, 2. The default values is 0.
+ *
+ * If @line_spacing 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).
+ *
+ * This method is a shorthand for adding a line-height attribute.
+ */
 void
-pango_layout_iter_free (PangoLayoutIter *iter)
+pango_layout_set_line_spacing (PangoLayout *layout,
+                               float        line_spacing)
 {
-  if (iter == NULL)
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+  if (layout->line_spacing == line_spacing)
     return;
 
-  _pango_layout_iter_destroy (iter);
-  g_slice_free (PangoLayoutIter, iter);
+  layout->line_spacing = line_spacing;
+
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_LINE_SPACING]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_get_index:
- * @iter: a `PangoLayoutIter`
- *
- * Gets the current byte index.
+ * pango_layout_get_line_spacing:
+ * @layout: a `PangoLayout`
  *
- * Note that iterating forward by char moves in visual order,
- * not logical order, so indexes may not be sequential. Also,
- * the index may be equal to the length of the text in the
- * layout, if on the %NULL run (see [method@Pango.LayoutIter.get_run]).
+ * Gets the line spacing factor of @layout.
  *
- * Return value: current byte index
+ * See [method@Pango.Layout.set_line_spacing].
  */
-int
-pango_layout_iter_get_index (PangoLayoutIter *iter)
+float
+pango_layout_get_line_spacing (PangoLayout *layout)
 {
-  if (ITER_IS_INVALID (iter))
-    return 0;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0.0);
 
-  return iter->index;
+  return layout->line_spacing;
 }
 
 /**
- * pango_layout_iter_get_run:
- * @iter: a `PangoLayoutIter`
- *
- * Gets the current run.
- *
- * When iterating by run, at the end of each line, there's a position
- * with a %NULL run, so this function can return %NULL. The %NULL run
- * at the end of each line ensures that all lines have at least one run,
- * even lines consisting of only a newline.
+ * pango_layout_set_width:
+ * @layout: a `PangoLayout`.
+ * @width: the desired width in Pango units, or -1 to indicate that no
+ *   wrapping or ellipsization should be performed.
  *
- * Use the faster [method@Pango.LayoutIter.get_run_readonly] if you do not
- * plan to modify the contents of the run (glyphs, glyph widths, etc.).
+ * Sets the width to which the lines of the layout should
+ * be wrapped or ellipsized.
  *
- * Return value: (transfer none) (nullable): the current run
+ * The default value is -1: no width set.
  */
-PangoLayoutRun*
-pango_layout_iter_get_run (PangoLayoutIter *iter)
+void
+pango_layout_set_width (PangoLayout *layout,
+                        int          width)
 {
-  if (ITER_IS_INVALID (iter))
-    return NULL;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  pango_layout_line_leaked (iter->line);
+  if (width < -1)
+    width = -1;
+
+  if (layout->width == width)
+    return;
+
+  layout->width = width;
 
-  return iter->run;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_WIDTH]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_get_run_readonly:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_get_width:
+ * @layout: a `PangoLayout`
  *
- * Gets the current run for read-only access.
+ * Gets the width to which the lines of the layout should wrap.
  *
- * When iterating by run, at the end of each line, there's a position
- * with a %NULL run, so this function can return %NULL. The %NULL run
- * at the end of each line ensures that all lines have at least one run,
- * even lines consisting of only a newline.
+ * Return value: the width in Pango units, or -1 if no width set.
+ */
+int
+pango_layout_get_width (PangoLayout *layout)
+{
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), -1);
+
+  return layout->width;
+}
+
+/**
+ * pango_layout_set_height:
+ * @layout: a `PangoLayout`.
+ * @height: the desired height
  *
- * This is a faster alternative to [method@Pango.LayoutIter.get_run],
- * but the user is not expected to modify the contents of the run (glyphs,
- * glyph widths, etc.).
+ * Sets the height to which the `PangoLayout` should be ellipsized at.
  *
- * Return value: (transfer none) (nullable): the current run, that
- *   should not be modified
+ * There are two different behaviors, based on whether @height is positive
+ * or negative.
  *
- * Since: 1.16
+ * See [property@Pango.Layout:height] for details.
  */
-PangoLayoutRun*
-pango_layout_iter_get_run_readonly (PangoLayoutIter *iter)
+void
+pango_layout_set_height (PangoLayout *layout,
+                         int          height)
 {
-  if (ITER_IS_INVALID (iter))
-    return NULL;
-
-  pango_layout_line_leaked (iter->line);
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  return iter->run;
-}
+  if (layout->height == height)
+    return;
 
-/* an inline-able version for local use */
-static PangoLayoutLine*
-_pango_layout_iter_get_line (PangoLayoutIter *iter)
-{
-  return iter->line;
-}
+  layout->height = height;
 
-static PangoLayoutRun *
-_pango_layout_iter_get_run (PangoLayoutIter *iter)
-{
-  return iter->run;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_HEIGHT]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_get_line:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_get_height:
+ * @layout: a `PangoLayout`
  *
- * Gets the current line.
+ * Gets the height to which the lines of the layout should ellipsize.
  *
- * Use the faster [method@Pango.LayoutIter.get_line_readonly] if
- * you do not plan to modify the contents of the line (glyphs,
- * glyph widths, etc.).
+ * See [property@Pango.Layout:height] for details.
  *
- * Return value: (transfer none): the current line
+ * Return value: the height
  */
-PangoLayoutLine*
-pango_layout_iter_get_line (PangoLayoutIter *iter)
+int
+pango_layout_get_height (PangoLayout *layout)
 {
-  if (ITER_IS_INVALID (iter))
-    return NULL;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), -1);
 
-  pango_layout_line_leaked (iter->line);
-
-  return iter->line;
+  return layout->height;
 }
 
 /**
- * pango_layout_iter_get_line_readonly:
- * @iter: a `PangoLayoutIter`
- *
- * Gets the current line for read-only access.
+ * pango_layout_set_tabs:
+ * @layout: a `PangoLayout`
+ * @tabs: (nullable): a `PangoTabArray`
  *
- * This is a faster alternative to [method@Pango.LayoutIter.get_line],
- * but the user is not expected to modify the contents of the line
- * (glyphs, glyph widths, etc.).
+ * Sets the tabs to use for the layout, overriding the
+ * default tabs.
  *
- * Return value: (transfer none): the current line, that should not be
- *   modified
+ * Setting the tabs to `NULL` reinstates the default
+ * tabs.
  *
- * Since: 1.16
+ * See [method@Pango.LineBreaker.set_tabs] for details.
  */
-PangoLayoutLine*
-pango_layout_iter_get_line_readonly (PangoLayoutIter *iter)
+void
+pango_layout_set_tabs (PangoLayout   *layout,
+                       PangoTabArray *tabs)
 {
-  if (ITER_IS_INVALID (iter))
-    return NULL;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+  if (layout->tabs == tabs)
+    return;
 
-  return iter->line;
+  g_clear_pointer (&layout->tabs, pango_tab_array_free);
+  if (tabs)
+    layout->tabs = pango_tab_array_copy (tabs);
+
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_TABS]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_at_last_line:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_get_tabs:
+ * @layout: a `PangoLayout`
  *
- * Determines whether @iter is on the last line of the layout.
+ * Gets the current `PangoTabArray` used by this layout.
+ *
+ * If no `PangoTabArray` has been set, then the default tabs are
+ * in use and %NULL is returned. Default tabs are every 8 spaces.
  *
- * Return value: %TRUE if @iter is on the last line
+ * Return value: (transfer none) (nullable): the tabs for this layout
  */
-gboolean
-pango_layout_iter_at_last_line (PangoLayoutIter *iter)
+PangoTabArray *
+pango_layout_get_tabs (PangoLayout *layout)
 {
-  if (ITER_IS_INVALID (iter))
-    return FALSE;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-  return iter->line_index == iter->layout->line_count - 1;
+  return layout->tabs;
 }
 
 /**
- * pango_layout_iter_get_layout:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_set_single_paragraph:
+ * @layout: a `PangoLayout`
+ * @single_paragraph: the new setting
+ *
+ * Sets the single paragraph mode of the layout.
  *
- * Gets the layout associated with a `PangoLayoutIter`.
+ * If @single_paragraph is `TRUE`, do not treat newlines and similar
+ * characters as paragraph separators; instead, keep all text in a
+ * single paragraph, and display a glyph for paragraph separator
+ * characters.
  *
- * Return value: (transfer none): the layout associated with @iter
+ * Used when you want to allow editing of newlines on a single text line.
  *
- * Since: 1.20
+ * The default value is %FALSE.
  */
-PangoLayout*
-pango_layout_iter_get_layout (PangoLayoutIter *iter)
+void
+pango_layout_set_single_paragraph (PangoLayout *layout,
+                                   gboolean     single_paragraph)
 {
-  /* check is redundant as it simply checks that iter->layout is not NULL */
-  if (ITER_IS_INVALID (iter))
-    return NULL;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  return iter->layout;
-}
+  if (layout->single_paragraph == single_paragraph)
+    return;
 
-static gboolean
-line_is_terminated (PangoLayoutIter *iter)
-{
-  /* There is a real terminator at the end of each paragraph other
-   * than the last.
-   */
-  if (iter->line_list_link->next)
-    {
-      PangoLayoutLine *next_line = iter->line_list_link->next->data;
-      if (next_line->is_paragraph_start)
-        return TRUE;
-    }
+  layout->single_paragraph = single_paragraph;
 
-  return FALSE;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_SINGLE_PARAGRAPH]);
+  layout_changed (layout);
 }
 
-/* Moves to the next non-empty line. If @include_terminators
- * is set, a line with just an explicit paragraph separator
- * is considered non-empty.
+/**
+ * pango_layout_get_single_paragraph:
+ * @layout: a `PangoLayout`
+ *
+ * Obtains whether this layout is in single paragraph mode.
+ *
+ * See [method@Pango.Layout.set_single_paragraph].
+ *
+ * Return value: `TRUE` if the layout does not break paragraphs
+ *   at paragraph separator characters, %FALSE otherwise
  */
-static gboolean
-next_nonempty_line (PangoLayoutIter *iter,
-                    gboolean         include_terminators)
+gboolean
+pango_layout_get_single_paragraph (PangoLayout *layout)
 {
-  gboolean result;
-
-  while (TRUE)
-    {
-      result = pango_layout_iter_next_line (iter);
-      if (!result)
-        break;
-
-      if (iter->line->runs)
-        break;
-
-      if (include_terminators && line_is_terminated (iter))
-        break;
-    }
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
 
-  return result;
+  return layout->single_paragraph;
 }
 
-/* Moves to the next non-empty run. If @include_terminators
- * is set, the trailing run at the end of a line with an explicit
- * paragraph separator is considered non-empty.
+/**
+ * pango_layout_set_wrap:
+ * @layout: a `PangoLayout`
+ * @wrap: the wrap mode
+ *
+ * Sets the wrap mode.
+ *
+ * The wrap mode only has effect if a width is set on the layout
+ * with [method@Pango.Layout.set_width]. To turn off wrapping,
+ * set the width to -1.
+ *
+ * The default value is %PANGO_WRAP_WORD.
  */
-static gboolean
-next_nonempty_run (PangoLayoutIter *iter,
-                    gboolean         include_terminators)
+void
+pango_layout_set_wrap (PangoLayout   *layout,
+                       PangoWrapMode  wrap)
 {
-  gboolean result;
-
-  while (TRUE)
-    {
-      result = pango_layout_iter_next_run (iter);
-      if (!result)
-        break;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-      if (iter->run)
-        break;
+  if (layout->wrap == wrap)
+    return;
 
-      if (include_terminators && line_is_terminated (iter))
-        break;
-    }
+  layout->wrap = wrap;
 
-  return result;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_WRAP]);
+  layout_changed (layout);
 }
 
-/* Like pango_layout_next_cluster(), but if @include_terminators
- * is set, includes the fake runs/clusters for empty lines.
- * (But not positions introduced by line wrapping).
+/**
+ * pango_layout_get_wrap:
+ * @layout: a `PangoLayout`
+ *
+ * Gets the wrap mode for the layout.
+ *
+ * Return value: active wrap mode.
  */
-static gboolean
-next_cluster_internal (PangoLayoutIter *iter,
-                       gboolean         include_terminators)
+PangoWrapMode
+pango_layout_get_wrap (PangoLayout *layout)
 {
-  PangoGlyphString *gs;
-  int               next_start;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), PANGO_WRAP_WORD);
 
-  if (ITER_IS_INVALID (iter))
-    return FALSE;
-
-  if (iter->run == NULL)
-    return next_nonempty_line (iter, include_terminators);
-
-  gs = iter->run->glyphs;
-
-  next_start = iter->next_cluster_glyph;
-  if (next_start == gs->num_glyphs)
-    {
-      return next_nonempty_run (iter, include_terminators);
-    }
-  else
-    {
-      iter->cluster_start = next_start;
-      iter->cluster_x += iter->cluster_width;
-      update_cluster(iter, gs->log_clusters[iter->cluster_start]);
-
-      return TRUE;
-    }
+  return layout->wrap;
 }
 
 /**
- * pango_layout_iter_next_char:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_set_indent:
+ * @layout: a `PangoLayout`
+ * @indent: the amount by which to indent
  *
- * Moves @iter forward to the next character in visual order.
+ * Sets the width in Pango units to indent each paragraph.
  *
- * If @iter was already at the end of the layout, returns %FALSE.
+ * A negative value of @indent will produce a hanging indentation.
+ * That is, the first line will have the full width, and subsequent
+ * lines will be indented by the absolute value of @indent.
  *
- * Return value: whether motion was possible
+ * The default value is 0.
  */
-gboolean
-pango_layout_iter_next_char (PangoLayoutIter *iter)
+void
+pango_layout_set_indent (PangoLayout *layout,
+                         int          indent)
 {
-  const char *text;
-
-  if (ITER_IS_INVALID (iter))
-    return FALSE;
-
-  if (iter->run == NULL)
-    {
-      /* We need to fake an iterator position in the middle of a \r\n line terminator */
-      if (line_is_terminated (iter) &&
-          strncmp (iter->layout->text + iter->line->start_index + iter->line->length, "\r\n", 2) == 0 &&
-          iter->character_position == 0)
-        {
-          iter->character_position++;
-          return TRUE;
-        }
-
-      return next_nonempty_line (iter, TRUE);
-    }
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  iter->character_position++;
-  if (iter->character_position >= iter->cluster_num_chars)
-    return next_cluster_internal (iter, TRUE);
+  if (layout->indent == indent)
+    return;
 
-  text = iter->layout->text;
-  if (iter->ltr)
-    iter->index = g_utf8_next_char (text + iter->index) - text;
-  else
-    iter->index = g_utf8_prev_char (text + iter->index) - text;
+  layout->indent = indent;
 
-  return TRUE;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_INDENT]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_next_cluster:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_get_indent:
+ * @layout: a `PangoLayout`
  *
- * Moves @iter forward to the next cluster in visual order.
+ * Gets the paragraph indent width in Pango units.
  *
- * If @iter was already at the end of the layout, returns %FALSE.
+ * A negative value indicates a hanging indentation.
  *
- * Return value: whether motion was possible
+ * Return value: the indent in Pango units
  */
-gboolean
-pango_layout_iter_next_cluster (PangoLayoutIter *iter)
+int
+pango_layout_get_indent (PangoLayout *layout)
 {
-  return next_cluster_internal (iter, FALSE);
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
+
+  return layout->indent;
 }
 
 /**
- * pango_layout_iter_next_run:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_set_alignment:
+ * @layout: a `PangoLayout`
+ * @alignment: the alignment
  *
- * Moves @iter forward to the next run in visual order.
+ * Sets the alignment for the layout.
  *
- * If @iter was already at the end of the layout, returns %FALSE.
+ * The alignment determines how short lines are
+ * positioned within the available horizontal space.
  *
- * Return value: whether motion was possible
+ * The default alignment is `PANGO_ALIGN_LEFT`.
  */
-gboolean
-pango_layout_iter_next_run (PangoLayoutIter *iter)
+void
+pango_layout_set_alignment (PangoLayout    *layout,
+                            PangoAlignment  alignment)
 {
-  int next_run_start; /* byte index */
-  GSList *next_link;
-
-  if (ITER_IS_INVALID (iter))
-    return FALSE;
-
-  if (iter->run == NULL)
-    return pango_layout_iter_next_line (iter);
-
-  next_link = iter->run_list_link->next;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  if (next_link == NULL)
-    {
-      /* Moving on to the zero-width "virtual run" at the end of each
-       * line
-       */
-      next_run_start = iter->run->item->offset + iter->run->item->length;
-      iter->run = NULL;
-      iter->run_list_link = NULL;
-    }
-  else
-    {
-      iter->run_list_link = next_link;
-      iter->run = iter->run_list_link->data;
-      next_run_start = iter->run->item->offset;
-    }
+  if (layout->alignment == alignment)
+    return;
 
-  update_run (iter, next_run_start);
+  layout->alignment = alignment;
 
-  return TRUE;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_ALIGNMENT]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_next_line:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_get_alignment:
+ * @layout: a `PangoLayout`
  *
- * Moves @iter forward to the start of the next line.
+ * Gets the alignment for the layout.
  *
- * If @iter is already on the last line, returns %FALSE.
+ * The alignment determines how short lines are
+ * positioned within the available horizontal space.
  *
- * Return value: whether motion was possible
+ * Return value: the alignment
  */
-gboolean
-pango_layout_iter_next_line (PangoLayoutIter *iter)
+PangoAlignment
+pango_layout_get_alignment (PangoLayout *layout)
 {
-  GSList *next_link;
-
-  if (ITER_IS_INVALID (iter))
-    return FALSE;
-
-  next_link = iter->line_list_link->next;
-
-  if (next_link == NULL)
-    return FALSE;
-
-  iter->line_list_link = next_link;
-
-  pango_layout_line_unref (iter->line);
-
-  iter->line = iter->line_list_link->data;
-
-  pango_layout_line_ref (iter->line);
-
-  iter->run_list_link = iter->line->runs;
-
-  if (iter->run_list_link)
-    iter->run = iter->run_list_link->data;
-  else
-    iter->run = NULL;
-
-  iter->line_index ++;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), PANGO_ALIGN_LEFT);
 
-  update_run (iter, iter->line->start_index);
-
-  return TRUE;
+  return layout->alignment;
 }
 
 /**
- * pango_layout_iter_get_char_extents:
- * @iter: a `PangoLayoutIter`
- * @logical_rect: (out caller-allocates): rectangle to fill with
- *   logical extents
+ * pango_layout_set_ellipsize:
+ * @layout: a `PangoLayout`
+ * @ellipsize: the new ellipsization mode for @layout
  *
- * Gets the extents of the current character, in layout coordinates.
+ * Sets the type of ellipsization to use for this layout.
  *
- * Layout coordinates have the origin at the top left of the entire layout.
+ * Depending on the ellipsization mode @ellipsize text is removed
+ * from the start, middle, or end of text so they fit within the
+ * width of layout set with [method@Pango.Layout.set_width].
  *
- * Only logical extents can sensibly be obtained for characters;
- * ink extents make sense only down to the level of clusters.
+ * The default value is `PANGO_ELLIPSIZE_NONE`.
  */
 void
-pango_layout_iter_get_char_extents (PangoLayoutIter *iter,
-                                    PangoRectangle  *logical_rect)
+pango_layout_set_ellipsize (PangoLayout        *layout,
+                            PangoEllipsizeMode  ellipsize)
 {
-  PangoRectangle cluster_rect;
-  int            x0, x1;
-
-  if (ITER_IS_INVALID (iter))
-    return;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  if (logical_rect == NULL)
+  if (layout->ellipsize == ellipsize)
     return;
 
-  pango_layout_iter_get_cluster_extents (iter, NULL, &cluster_rect);
-
-  if (iter->run == NULL)
-    {
-      /* When on the NULL run, cluster, char, and run all have the
-       * same extents
-       */
-      *logical_rect = cluster_rect;
-      return;
-    }
+  layout->ellipsize = ellipsize;
 
-  if (iter->cluster_num_chars)
-  {
-    x0 = (iter->character_position * cluster_rect.width) / iter->cluster_num_chars;
-    x1 = ((iter->character_position + 1) * cluster_rect.width) / iter->cluster_num_chars;
-  }
-  else
-  {
-    x0 = x1 = 0;
-  }
-
-  logical_rect->width = x1 - x0;
-  logical_rect->height = cluster_rect.height;
-  logical_rect->y = cluster_rect.y;
-  logical_rect->x = cluster_rect.x + x0;
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_ELLIPSIZE]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_get_cluster_extents:
- * @iter: a `PangoLayoutIter`
- * @ink_rect: (out) (optional): rectangle to fill with ink extents
- * @logical_rect: (out) (optional): rectangle to fill with logical extents
+ * pango_layout_get_ellipsize:
+ * @layout: a `PangoLayout`
  *
- * Gets the extents of the current cluster, in layout coordinates.
+ * Gets the type of ellipsization being performed for @layout.
+ *
+ * See [method@Pango.Layout.set_ellipsize].
  *
- * Layout coordinates have the origin at the top left of the entire layout.
+ * Return value: the current ellipsization mode for @layout
  */
-void
-pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter,
-                                       PangoRectangle  *ink_rect,
-                                       PangoRectangle  *logical_rect)
+PangoEllipsizeMode
+pango_layout_get_ellipsize (PangoLayout *layout)
 {
-  if (ITER_IS_INVALID (iter))
-    return;
-
-  if (iter->run == NULL)
-    {
-      /* When on the NULL run, cluster, char, and run all have the
-       * same extents
-       */
-      pango_layout_iter_get_run_extents (iter, ink_rect, logical_rect);
-      return;
-    }
-
-  pango_glyph_string_extents_range (iter->run->glyphs,
-                                    iter->cluster_start,
-                                    iter->next_cluster_glyph,
-                                    iter->run->item->analysis.font,
-                                    ink_rect,
-                                    logical_rect);
-
-  if (ink_rect)
-    {
-      ink_rect->x += iter->cluster_x + iter->run->start_x_offset;
-      ink_rect->y -= iter->run->y_offset;
-      offset_y (iter, &ink_rect->y);
-    }
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), PANGO_ELLIPSIZE_NONE);
 
-  if (logical_rect)
-    {
-      g_assert (logical_rect->width == iter->cluster_width);
-      logical_rect->x += iter->cluster_x + iter->run->start_x_offset;
-      logical_rect->y -= iter->run->y_offset;
-      offset_y (iter, &logical_rect->y);
-    }
+  return layout->ellipsize;
 }
 
 /**
- * pango_layout_iter_get_run_extents:
- * @iter: a `PangoLayoutIter`
- * @ink_rect: (out) (optional): rectangle to fill with ink extents
- * @logical_rect: (out) (optional): rectangle to fill with logical extents
+ * pango_layout_set_auto_dir:
+ * @layout: a `PangoLayout`
+ * @auto_dir: if %TRUE, compute the bidirectional base direction
+ *   from the layout's contents
+ *
+ * Sets whether to calculate the base direction
+ * for the layout according to its contents.
+ *
+ * When this flag is on (the default), then paragraphs in
+ * @layout that begin with strong right-to-left characters
+ * (Arabic and Hebrew principally), will have right-to-left
+ * layout, paragraphs with letters from other scripts will
+ * have left-to-right layout. Paragraphs with only neutral
+ * characters get their direction from the surrounding
+ * paragraphs.
  *
- * Gets the extents of the current run in layout coordinates.
+ * When `FALSE`, the choice between left-to-right and right-to-left
+ * layout is done according to the base direction of the layout's
+ * `PangoContext`. (See [method@Pango.Context.set_base_dir]).
  *
- * Layout coordinates have the origin at the top left of the entire layout.
+ * When the auto-computed direction of a paragraph differs
+ * from the base direction of the context, the interpretation
+ * of `PANGO_ALIGN_LEFT` and `PANGO_ALIGN_RIGHT` are swapped.
  */
 void
-pango_layout_iter_get_run_extents (PangoLayoutIter *iter,
-                                   PangoRectangle  *ink_rect,
-                                   PangoRectangle  *logical_rect)
+pango_layout_set_auto_dir (PangoLayout *layout,
+                           gboolean     auto_dir)
 {
-  if (G_UNLIKELY (!ink_rect && !logical_rect))
-    return;
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
-  if (ITER_IS_INVALID (iter))
+  if (auto_dir == layout->auto_dir)
     return;
 
-  if (iter->run)
-    {
-      pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL, NULL);
-
-      if (ink_rect)
-        {
-          offset_y (iter, &ink_rect->y);
-          ink_rect->x += iter->run_x;
-        }
-
-      if (logical_rect)
-        {
-          offset_y (iter, &logical_rect->y);
-          logical_rect->x += iter->run_x;
-        }
-    }
-  else
-    {
-      if (iter->line->runs)
-        {
-          /* The empty run at the end of a non-empty line */
-          PangoLayoutRun *run = g_slist_last (iter->line->runs)->data;
-          pango_layout_run_get_extents_and_height (run, ink_rect, logical_rect, NULL, NULL);
-        }
-      else
-        {
-          PangoRectangle r;
-
-          pango_layout_get_empty_extents_and_height_at_index (iter->layout, 0, &r, FALSE, NULL);
-
-          if (ink_rect)
-            *ink_rect = r;
+  layout->auto_dir = auto_dir;
 
-          if (logical_rect)
-            *logical_rect = r;
-        }
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_AUTO_DIR]);
+  layout_changed (layout);
+}
 
-      if (ink_rect)
-        {
-          offset_y (iter, &ink_rect->y);
-          ink_rect->x = iter->run_x;
-          ink_rect->width = 0;
-        }
+/**
+ * pango_layout_get_auto_dir:
+ * @layout: a `PangoLayout`
+ *
+ * Gets whether to calculate the base direction for the layout
+ * according to its contents.
+ *
+ * See [method@Pango.Layout.set_auto_dir].
+ *
+ * Return value: `TRUE` if the bidirectional base direction
+ *   is computed from the layout's contents, `FALSE` otherwise
+ */
+gboolean
+pango_layout_get_auto_dir (PangoLayout *layout)
+{
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), TRUE);
 
-      if (logical_rect)
-        {
-          offset_y (iter, &logical_rect->y);
-          logical_rect->x = iter->run_x;
-          logical_rect->width = 0;
-        }
-    }
+  return layout->auto_dir;
 }
 
+/* }}} */
+/* {{{ Miscellaneous */
+
 /**
- * pango_layout_iter_get_line_extents:
- * @iter: a `PangoLayoutIter`
- * @ink_rect: (out) (optional): rectangle to fill with ink extents
- * @logical_rect: (out) (optional): rectangle to fill with logical extents
+ * pango_layout_set_markup:
+ * @layout: a `PangoLayout`
+ * @markup: marked-up text
+ * @length: length of @markup in bytes, or -1 if it is `NUL`-terminated
+ *
+ * Sets the layout text and attribute list from marked-up text.
  *
- * Obtains the extents of the current line.
+ * See [Pango Markup](pango_markup.html)).
  *
- * Extents are in layout coordinates (origin is the top-left corner
- * of the entire `PangoLayout`). Thus the extents returned by this
- * function will be the same width/height but not at the same x/y
- * as the extents returned from [method@Pango.LayoutLine.get_extents].
+ * Replaces the current text and attributes.
  */
 void
-pango_layout_iter_get_line_extents (PangoLayoutIter *iter,
-                                    PangoRectangle  *ink_rect,
-                                    PangoRectangle  *logical_rect)
+pango_layout_set_markup (PangoLayout  *layout,
+                         const char   *markup,
+                         int           length)
 {
-  const Extents *ext;
-
-  if (ITER_IS_INVALID (iter))
-    return;
+  PangoAttrList *attrs;
+  char *text;
+  GError *error = NULL;
 
-  ext = &iter->line_extents[iter->line_index];
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+  g_return_if_fail (markup != NULL);
 
-  if (ink_rect)
+  if (!pango_parse_markup (markup, length, 0, &attrs, &text, NULL, &error))
     {
-      get_line_extents_layout_coords (iter->layout, iter->line,
-                                      iter->layout_width,
-                                      ext->logical_rect.y,
-                                      NULL,
-                                      ink_rect,
-                                      NULL);
+      g_warning ("pango_layout_set_markup_with_accel: %s", error->message);
+      g_error_free (error);
+      return;
     }
 
-  if (logical_rect)
-    *logical_rect = ext->logical_rect;
+  g_free (layout->text);
+  layout->text = text;
+  layout->length = strlen (text);
+
+  g_clear_pointer (&layout->attrs, pango_attr_list_unref);
+  layout->attrs = attrs;
+
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_TEXT]);
+  g_object_notify_by_pspec (G_OBJECT (layout), props[PROP_ATTRIBUTES]);
+  layout_changed (layout);
 }
 
 /**
- * pango_layout_iter_get_line_yrange:
- * @iter: a `PangoLayoutIter`
- * @y0_: (out) (optional): start of line
- * @y1_: (out) (optional): end of line
- *
- * Divides the vertical space in the `PangoLayout` being iterated over
- * between the lines in the layout, and returns the space belonging to
- * the current line.
+ * pango_layout_get_character_count:
+ * @layout: a `PangoLayout`
  *
- * A line's range includes the line's logical extents. plus half of the
- * spacing above and below the line, if [method@Pango.Layout.set_spacing]
- * has been called to set layout spacing. The Y positions are in layout
- * coordinates (origin at top left of the entire layout).
+ * Returns the number of Unicode characters in the
+ * the text of the layout.
  *
- * Note: Since 1.44, Pango uses line heights for placing lines, and there
- * may be gaps between the ranges returned by this function.
+ * Return value: the number of Unicode characters in @layout
  */
-void
-pango_layout_iter_get_line_yrange (PangoLayoutIter *iter,
-                                   int             *y0,
-                                   int             *y1)
+int
+pango_layout_get_character_count (PangoLayout *layout)
 {
-  const Extents *ext;
-  int half_spacing;
+  PangoLine *line;
 
-  if (ITER_IS_INVALID (iter))
-    return;
-
-  ext = &iter->line_extents[iter->line_index];
-
-  half_spacing = iter->layout->spacing / 2;
-
-  /* Note that if layout->spacing is odd, the remainder spacing goes
-   * above the line (this is pretty arbitrary of course)
-   */
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
 
-  if (y0)
-    {
-      /* No spacing above the first line */
+  ensure_lines (layout);
 
-      if (iter->line_index == 0)
-        *y0 = ext->logical_rect.y;
-      else
-        *y0 = ext->logical_rect.y - (iter->layout->spacing - half_spacing);
-    }
+  line = pango_lines_get_line (layout->lines, 0, NULL, NULL);
 
-  if (y1)
-    {
-      /* No spacing below the last line */
-      if (iter->line_index == iter->layout->line_count - 1)
-        *y1 = ext->logical_rect.y + ext->logical_rect.height;
-      else
-        *y1 = ext->logical_rect.y + ext->logical_rect.height + half_spacing;
-    }
+  return line->data->n_chars;
 }
 
+/* }}} */
+/* {{{ Output getters */
+
 /**
- * pango_layout_iter_get_baseline:
- * @iter: a `PangoLayoutIter`
+ * pango_layout_get_lines:
+ * @layout: a `PangoLayout`
  *
- * Gets the Y position of the current line's baseline, in layout
- * coordinates.
+ * Gets the lines of the @layout.
  *
- * Layout coordinates have the origin at the top left of the entire layout.
+ * The returned object will become invalid when any
+ * property of @layout is changed. Take a reference
+ * to keep it.
  *
- * Return value: baseline of current line
+ * Return value: (transfer none): a `PangoLines` object
+ *   with the lines of @layout
  */
-int
-pango_layout_iter_get_baseline (PangoLayoutIter *iter)
+PangoLines *
+pango_layout_get_lines (PangoLayout *layout)
 {
-  if (ITER_IS_INVALID (iter))
-    return 0;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
 
-  return iter->line_extents[iter->line_index].baseline;
+  ensure_lines (layout);
+
+  return layout->lines;
 }
 
 /**
- * pango_layout_iter_get_run_baseline:
- * @iter: a `PangoLayoutIter`
- * 
- * Gets the Y position of the current run's baseline, in layout
- * coordinates.
+ * pango_layout_get_log_attrs:
+ * @layout: a `PangoLayout`
+ * @n_attrs: (out): return location for the length of the array
  *
- * Layout coordinates have the origin at the top left of the entire layout.
+ * Gets the `PangoLogAttr` array for the content
+ * of @layout.
  *
- * The run baseline can be different from the line baseline, for
- * example due to superscript or subscript positioning.
+ * The returned array becomes invalid when
+ * any properties of @layout change. Make a
+ * copy if you want to keep it.
  *
- * Since: 1.50
+ * Returns: (transfer none): the `PangoLogAttr` array
  */
-int
-pango_layout_iter_get_run_baseline (PangoLayoutIter *iter)
+const PangoLogAttr *
+pango_layout_get_log_attrs (PangoLayout *layout,
+                            int         *n_attrs)
 {
-  if (ITER_IS_INVALID (iter))
-    return 0;
+  PangoLine *line;
 
-  if (!iter->run)
-    return iter->line_extents[iter->line_index].baseline;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+  ensure_lines (layout);
+
+  line = pango_lines_get_line (layout->lines, 0, NULL, NULL);
+
+  if (n_attrs)
+    *n_attrs = line->data->n_chars + 1;
 
-  return iter->line_extents[iter->line_index].baseline - iter->run->y_offset;
+  return line->data->log_attrs;
 }
 
 /**
- * pango_layout_iter_get_layout_extents:
- * @iter: a `PangoLayoutIter`
- * @ink_rect: (out) (optional): rectangle to fill with ink extents
- * @logical_rect: (out) (optional): rectangle to fill with logical extents
+ * pango_layout_get_iter:
+ * @layout: a `PangoLayout`
+ *
+ * Returns an iterator to iterate over the visual extents
+ * of the layout.
  *
- * Obtains the extents of the `PangoLayout` being iterated over.
+ * This is a convenience wrapper for [method@Pango.Lines.get_iter].
+ *
+ * Returns: the new `PangoLineIter`
  */
-void
-pango_layout_iter_get_layout_extents (PangoLayoutIter *iter,
-                                      PangoRectangle  *ink_rect,
-                                      PangoRectangle  *logical_rect)
+PangoLineIter *
+pango_layout_get_iter (PangoLayout *layout)
 {
-  if (ITER_IS_INVALID (iter))
-    return;
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+  ensure_lines (layout);
 
-  pango_layout_get_extents (iter->layout, ink_rect, logical_rect);
+  return pango_lines_get_iter (layout->lines);
 }
+
+/* }}} */
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-layout.h b/pango/pango-layout.h
index 45152848..0c3e7c02 100644
--- a/pango/pango-layout.h
+++ b/pango/pango-layout.h
@@ -1,322 +1,162 @@
-/* Pango
- * pango-layout.h: High-level layout driver
- *
- * Copyright (C) 2000 Red Hat Software
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __PANGO_LAYOUT_H__
-#define __PANGO_LAYOUT_H__
+#pragma once
 
+#include <glib-object.h>
 #include <pango/pango-types.h>
 #include <pango/pango-attributes.h>
-#include <pango/pango-context.h>
-#include <pango/pango-glyph-item.h>
+#include <pango/pango-lines.h>
 #include <pango/pango-tabs.h>
 
 G_BEGIN_DECLS
 
-typedef struct _PangoLayout      PangoLayout;
-typedef struct _PangoLayoutClass PangoLayoutClass;
-typedef struct _PangoLayoutLine  PangoLayoutLine;
-
-/**
- * PangoLayoutRun:
- *
- * A `PangoLayoutRun` represents a single run within a `PangoLayoutLine`.
- *
- * It is simply an alternate name for [struct@Pango.GlyphItem].
- * See the [struct@Pango.GlyphItem] docs for details on the fields.
- */
-typedef PangoGlyphItem PangoLayoutRun;
-
-/**
- * PangoLayoutLine:
- * @layout: (nullable): the layout this line belongs to, might be %NULL
- * @start_index: start of line as byte index into layout->text
- * @length: length of line in bytes
- * @runs: (nullable) (element-type Pango.LayoutRun): list of runs in the
- *   line, from left to right
- * @is_paragraph_start: #TRUE if this is the first line of the paragraph
- * @resolved_dir: #Resolved PangoDirection of line
- *
- * A `PangoLayoutLine` represents one of the lines resulting from laying
- * out a paragraph via `PangoLayout`.
- *
- * `PangoLayoutLine` structures are obtained by calling
- * [method@Pango.Layout.get_line] and are only valid until the text,
- * attributes, or settings of the parent `PangoLayout` are modified.
- */
-struct _PangoLayoutLine
-{
-  PangoLayout *layout;
-  gint         start_index;     /* start of line as byte index into layout->text */
-  gint         length;         /* length of line in bytes */
-  GSList      *runs;
-  guint        is_paragraph_start : 1;  /* TRUE if this is the first line of the paragraph */
-  guint        resolved_dir : 3;  /* Resolved PangoDirection of line */
-};
-
-#define PANGO_TYPE_LAYOUT              (pango_layout_get_type ())
-#define PANGO_LAYOUT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_LAYOUT, 
PangoLayout))
-#define PANGO_LAYOUT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_LAYOUT, 
PangoLayoutClass))
-#define PANGO_IS_LAYOUT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_LAYOUT))
-#define PANGO_IS_LAYOUT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_LAYOUT))
-#define PANGO_LAYOUT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_LAYOUT, 
PangoLayoutClass))
-
-/* The PangoLayout and PangoLayoutClass structs are private; if you
- * need to create a subclass of these, file a bug.
- */
+#define PANGO_TYPE_LAYOUT pango_layout_get_type ()
 
 PANGO_AVAILABLE_IN_ALL
-GType        pango_layout_get_type       (void) G_GNUC_CONST;
+G_DECLARE_FINAL_TYPE (PangoLayout, pango_layout, PANGO, LAYOUT, GObject);
+
 PANGO_AVAILABLE_IN_ALL
-PangoLayout *pango_layout_new            (PangoContext   *context);
+PangoLayout *           pango_layout_new            (PangoContext                 *context);
+
 PANGO_AVAILABLE_IN_ALL
-PangoLayout *pango_layout_copy           (PangoLayout    *src);
+PangoLayout *           pango_layout_copy           (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-PangoContext  *pango_layout_get_context    (PangoLayout    *layout);
+guint                   pango_layout_get_serial     (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_attributes (PangoLayout    *layout,
-                                           PangoAttrList  *attrs);
+PangoContext *          pango_layout_get_context    (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-PangoAttrList *pango_layout_get_attributes (PangoLayout    *layout);
+void                    pango_layout_context_changed (PangoLayout                 *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_text       (PangoLayout    *layout,
-                                           const char     *text,
-                                           int             length);
+void                    pango_layout_set_text       (PangoLayout                  *layout,
+                                                     const char                   *text,
+                                                     int                           length);
 PANGO_AVAILABLE_IN_ALL
-const char    *pango_layout_get_text       (PangoLayout    *layout);
-
-PANGO_AVAILABLE_IN_1_30
-gint           pango_layout_get_character_count (PangoLayout *layout);
+const char *            pango_layout_get_text       (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_markup     (PangoLayout    *layout,
-                                           const char     *markup,
-                                           int             length);
+void                    pango_layout_set_markup     (PangoLayout                  *layout,
+                                                     const char                   *markup,
+                                                     int                           length);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_markup_with_accel (PangoLayout    *layout,
-                                                  const char     *markup,
-                                                  int             length,
-                                                  gunichar        accel_marker,
-                                                  gunichar       *accel_char);
+int                     pango_layout_get_character_count
+                                                    (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_font_description (PangoLayout                *layout,
-                                                 const PangoFontDescription *desc);
-
-PANGO_AVAILABLE_IN_1_8
-const PangoFontDescription *pango_layout_get_font_description (PangoLayout *layout);
+void                    pango_layout_set_attributes (PangoLayout                  *layout,
+                                                     PangoAttrList                *attrs);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_width            (PangoLayout                *layout,
-                                                 int                         width);
-PANGO_AVAILABLE_IN_ALL
-int            pango_layout_get_width            (PangoLayout                *layout);
-PANGO_AVAILABLE_IN_1_20
-void           pango_layout_set_height           (PangoLayout                *layout,
-                                                 int                         height);
-PANGO_AVAILABLE_IN_1_20
-int            pango_layout_get_height           (PangoLayout                *layout);
-PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_wrap             (PangoLayout                *layout,
-                                                 PangoWrapMode               wrap);
-PANGO_AVAILABLE_IN_ALL
-PangoWrapMode  pango_layout_get_wrap             (PangoLayout                *layout);
-PANGO_AVAILABLE_IN_1_16
-gboolean       pango_layout_is_wrapped           (PangoLayout                *layout);
+PangoAttrList *         pango_layout_get_attributes (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_indent           (PangoLayout                *layout,
-                                                 int                         indent);
+void                    pango_layout_set_font_description
+                                                    (PangoLayout                  *layout,
+                                                     const PangoFontDescription   *desc);
+
 PANGO_AVAILABLE_IN_ALL
-int            pango_layout_get_indent           (PangoLayout                *layout);
+const PangoFontDescription *
+                        pango_layout_get_font_description
+                                                    (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_spacing          (PangoLayout                *layout,
-                                                 int                         spacing);
+void                    pango_layout_set_line_spacing
+                                                    (PangoLayout                  *layout,
+                                                     float                         line_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                       factor);
-PANGO_AVAILABLE_IN_1_44
-float          pango_layout_get_line_spacing     (PangoLayout                *layout);
+float                   pango_layout_get_line_spacing
+                                                    (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_justify          (PangoLayout                *layout,
-                                                  gboolean                    justify);
+void                    pango_layout_set_width      (PangoLayout                  *layout,
+                                                     int                           width);
+
 PANGO_AVAILABLE_IN_ALL
-gboolean       pango_layout_get_justify          (PangoLayout                *layout);
-PANGO_AVAILABLE_IN_1_50
-void           pango_layout_set_justify_last_line (PangoLayout                *layout,
-                                                   gboolean                    justify);
-PANGO_AVAILABLE_IN_1_50
-gboolean       pango_layout_get_justify_last_line (PangoLayout                *layout);
-PANGO_AVAILABLE_IN_1_4
-void           pango_layout_set_auto_dir         (PangoLayout                *layout,
-                                                 gboolean                    auto_dir);
-PANGO_AVAILABLE_IN_1_4
-gboolean       pango_layout_get_auto_dir         (PangoLayout                *layout);
+int                     pango_layout_get_width      (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_alignment        (PangoLayout                *layout,
-                                                 PangoAlignment              alignment);
+void                    pango_layout_set_height     (PangoLayout                  *layout,
+                                                     int                           height);
+
 PANGO_AVAILABLE_IN_ALL
-PangoAlignment pango_layout_get_alignment        (PangoLayout                *layout);
+int                     pango_layout_get_height     (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_tabs             (PangoLayout                *layout,
-                                                 PangoTabArray              *tabs);
+void                    pango_layout_set_tabs       (PangoLayout                  *layout,
+                                                     PangoTabArray                *tabs);
+
 PANGO_AVAILABLE_IN_ALL
-PangoTabArray* pango_layout_get_tabs             (PangoLayout                *layout);
+PangoTabArray *         pango_layout_get_tabs       (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void           pango_layout_set_single_paragraph_mode (PangoLayout                *layout,
-                                                      gboolean                    setting);
+void                    pango_layout_set_single_paragraph
+                                                    (PangoLayout                  *layout,
+                                                     gboolean                      single_paragraph);
 PANGO_AVAILABLE_IN_ALL
-gboolean       pango_layout_get_single_paragraph_mode (PangoLayout                *layout);
-
-PANGO_AVAILABLE_IN_1_6
-void               pango_layout_set_ellipsize (PangoLayout        *layout,
-                                              PangoEllipsizeMode  ellipsize);
-PANGO_AVAILABLE_IN_1_6
-PangoEllipsizeMode pango_layout_get_ellipsize (PangoLayout        *layout);
-PANGO_AVAILABLE_IN_1_16
-gboolean           pango_layout_is_ellipsized (PangoLayout        *layout);
-
-PANGO_AVAILABLE_IN_1_16
-int      pango_layout_get_unknown_glyphs_count (PangoLayout    *layout);
-
-PANGO_AVAILABLE_IN_1_46
-PangoDirection pango_layout_get_direction (PangoLayout *layout,
-                                           int          index);
+gboolean                pango_layout_get_single_paragraph
+                                                    (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_context_changed (PangoLayout    *layout);
-PANGO_AVAILABLE_IN_1_32
-guint    pango_layout_get_serial      (PangoLayout    *layout);
+void                    pango_layout_set_wrap       (PangoLayout                  *layout,
+                                                     PangoWrapMode                 wrap);
 
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_get_log_attrs (PangoLayout    *layout,
-                                    PangoLogAttr  **attrs,
-                                    gint           *n_attrs);
-
-PANGO_AVAILABLE_IN_1_30
-const PangoLogAttr *pango_layout_get_log_attrs_readonly (PangoLayout *layout,
-                                                        gint        *n_attrs);
+PangoWrapMode           pango_layout_get_wrap       (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_index_to_pos         (PangoLayout    *layout,
-                                           int             index_,
-                                           PangoRectangle *pos);
-PANGO_AVAILABLE_IN_ALL
-void     pango_layout_index_to_line_x      (PangoLayout    *layout,
-                                           int             index_,
-                                           gboolean        trailing,
-                                           int            *line,
-                                           int            *x_pos);
-PANGO_AVAILABLE_IN_ALL
-void     pango_layout_get_cursor_pos       (PangoLayout    *layout,
-                                           int             index_,
-                                           PangoRectangle *strong_pos,
-                                           PangoRectangle *weak_pos);
+void                    pango_layout_set_indent     (PangoLayout                  *layout,
+                                                     int                           indent);
 
-PANGO_AVAILABLE_IN_1_50
-void     pango_layout_get_caret_pos        (PangoLayout    *layout,
-                                            int             index_,
-                                            PangoRectangle *strong_pos,
-                                            PangoRectangle *weak_pos);
+PANGO_AVAILABLE_IN_ALL
+int                     pango_layout_get_indent     (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_move_cursor_visually (PangoLayout    *layout,
-                                           gboolean        strong,
-                                           int             old_index,
-                                           int             old_trailing,
-                                           int             direction,
-                                           int            *new_index,
-                                           int            *new_trailing);
+void                    pango_layout_set_alignment  (PangoLayout                  *layout,
+                                                     PangoAlignment                alignment);
+
 PANGO_AVAILABLE_IN_ALL
-gboolean pango_layout_xy_to_index          (PangoLayout    *layout,
-                                           int             x,
-                                           int             y,
-                                           int            *index_,
-                                           int            *trailing);
+PangoAlignment          pango_layout_get_alignment  (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_get_extents          (PangoLayout    *layout,
-                                           PangoRectangle *ink_rect,
-                                           PangoRectangle *logical_rect);
+void                    pango_layout_set_ellipsize  (PangoLayout                  *layout,
+                                                     PangoEllipsizeMode            ellipsize);
+
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_get_pixel_extents    (PangoLayout    *layout,
-                                           PangoRectangle *ink_rect,
-                                           PangoRectangle *logical_rect);
+PangoEllipsizeMode      pango_layout_get_ellipsize  (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_get_size             (PangoLayout    *layout,
-                                           int            *width,
-                                           int            *height);
+void                    pango_layout_set_auto_dir   (PangoLayout                  *layout,
+                                                     gboolean                      auto_dir);
+
 PANGO_AVAILABLE_IN_ALL
-void     pango_layout_get_pixel_size       (PangoLayout    *layout,
-                                           int            *width,
-                                           int            *height);
-PANGO_AVAILABLE_IN_1_22
-int      pango_layout_get_baseline         (PangoLayout    *layout);
+gboolean                pango_layout_get_auto_dir   (PangoLayout                  *layout);
 
 PANGO_AVAILABLE_IN_ALL
-int              pango_layout_get_line_count       (PangoLayout    *layout);
+PangoLines *            pango_layout_get_lines      (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-PangoLayoutLine *pango_layout_get_line             (PangoLayout    *layout,
-                                                   int             line);
-PANGO_AVAILABLE_IN_1_16
-PangoLayoutLine *pango_layout_get_line_readonly    (PangoLayout    *layout,
-                                                   int             line);
+PangoLineIter *         pango_layout_get_iter       (PangoLayout                  *layout);
+
 PANGO_AVAILABLE_IN_ALL
-GSList *         pango_layout_get_lines            (PangoLayout    *layout);
-PANGO_AVAILABLE_IN_1_16
-GSList *         pango_layout_get_lines_readonly   (PangoLayout    *layout);
+const PangoLogAttr *    pango_layout_get_log_attrs  (PangoLayout                  *layout,
+                                                     int                          *n_attrs);
 
-/**
- * PangoLayoutSerializeFlags:
- * @PANGO_LAYOUT_SERIALIZE_DEFAULT: Default behavior
- * @PANGO_LAYOUT_SERIALIZE_CONTEXT: Include context information
- * @PANGO_LAYOUT_SERIALIZE_OUTPUT: Include information about the formatted output
- *
- * Flags that influence the behavior of [method@Pango.Layout.serialize].
- *
- * New members may be added to this enumeration over time.
- *
- * Since: 1.50
- */
 typedef enum {
   PANGO_LAYOUT_SERIALIZE_DEFAULT = 0,
   PANGO_LAYOUT_SERIALIZE_CONTEXT = 1 << 0,
   PANGO_LAYOUT_SERIALIZE_OUTPUT = 1 << 1,
 } PangoLayoutSerializeFlags;
 
-PANGO_AVAILABLE_IN_1_50
-GBytes *        pango_layout_serialize             (PangoLayout                *layout,
-                                                    PangoLayoutSerializeFlags   flags);
-
-PANGO_AVAILABLE_IN_1_50
-gboolean        pango_layout_write_to_file         (PangoLayout                 *layout,
-                                                    PangoLayoutSerializeFlags   flags,
+PANGO_AVAILABLE_IN_ALL
+GBytes *                pango_layout_serialize      (PangoLayout                  *layout,
+                                                     PangoLayoutSerializeFlags     flags);
 
-                                                    const char                  *filename,
-                                                    GError                     **error);
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_layout_write_to_file  (PangoLayout                  *layout,
+                                                     const char                   *filename);
 
 #define PANGO_LAYOUT_DESERIALIZE_ERROR (pango_layout_deserialize_error_quark ())
 
@@ -329,8 +169,6 @@ gboolean        pango_layout_write_to_file         (PangoLayout
  *   not found
  *
  * Errors that can be returned by [func@Pango.Layout.deserialize].
- *
- * Since: 1.50
  */
 typedef enum {
   PANGO_LAYOUT_DESERIALIZE_INVALID,
@@ -338,155 +176,18 @@ typedef enum {
   PANGO_LAYOUT_DESERIALIZE_MISSING_VALUE,
 } PangoLayoutDeserializeError;
 
-PANGO_AVAILABLE_IN_1_50
-GQuark          pango_layout_deserialize_error_quark (void);
-
-/**
- * PangoLayoutDeserializeFlags:
- * @PANGO_LAYOUT_DESERIALIZE_DEFAULT: Default behavior
- * @PANGO_LAYOUT_DESERIALIZE_CONTEXT: Apply context information
- *   from the serialization to the `PangoContext`
- *
- * Flags that influence the behavior of [func@Pango.Layout.deserialize].
- *
- * New members may be added to this enumeration over time.
- *
- * Since: 1.50
- */
 typedef enum {
   PANGO_LAYOUT_DESERIALIZE_DEFAULT = 0,
   PANGO_LAYOUT_DESERIALIZE_CONTEXT = 1 << 0,
 } PangoLayoutDeserializeFlags;
 
-PANGO_AVAILABLE_IN_1_50
-PangoLayout *   pango_layout_deserialize           (PangoContext                 *context,
-                                                    GBytes                       *bytes,
-                                                    PangoLayoutDeserializeFlags   flags,
-                                                    GError                      **error);
-
-
-#define PANGO_TYPE_LAYOUT_LINE (pango_layout_line_get_type ())
-
-PANGO_AVAILABLE_IN_ALL
-GType    pango_layout_line_get_type     (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_1_10
-PangoLayoutLine *pango_layout_line_ref   (PangoLayoutLine *line);
-PANGO_AVAILABLE_IN_ALL
-void             pango_layout_line_unref (PangoLayoutLine *line);
-
-PANGO_AVAILABLE_IN_1_50
-int      pango_layout_line_get_start_index (PangoLayoutLine *line);
-PANGO_AVAILABLE_IN_1_50
-int      pango_layout_line_get_length      (PangoLayoutLine *line);
-PANGO_AVAILABLE_IN_1_50
-gboolean pango_layout_line_is_paragraph_start (PangoLayoutLine *line);
-PANGO_AVAILABLE_IN_1_50
-PangoDirection pango_layout_line_get_resolved_direction (PangoLayoutLine *line);
-
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_layout_line_x_to_index   (PangoLayoutLine  *line,
-                                        int               x_pos,
-                                        int              *index_,
-                                        int              *trailing);
-PANGO_AVAILABLE_IN_ALL
-void     pango_layout_line_index_to_x   (PangoLayoutLine  *line,
-                                        int               index_,
-                                        gboolean          trailing,
-                                        int              *x_pos);
-PANGO_AVAILABLE_IN_ALL
-void     pango_layout_line_get_x_ranges (PangoLayoutLine  *line,
-                                        int               start_index,
-                                        int               end_index,
-                                        int             **ranges,
-                                        int              *n_ranges);
-PANGO_AVAILABLE_IN_ALL
-void     pango_layout_line_get_extents  (PangoLayoutLine  *line,
-                                        PangoRectangle   *ink_rect,
-                                        PangoRectangle   *logical_rect);
-PANGO_AVAILABLE_IN_1_44
-void     pango_layout_line_get_height   (PangoLayoutLine  *line,
-                                        int              *height);
-
-PANGO_AVAILABLE_IN_ALL
-void     pango_layout_line_get_pixel_extents (PangoLayoutLine *layout_line,
-                                             PangoRectangle  *ink_rect,
-                                             PangoRectangle  *logical_rect);
-
-typedef struct _PangoLayoutIter PangoLayoutIter;
-
-#define PANGO_TYPE_LAYOUT_ITER         (pango_layout_iter_get_type ())
-
-PANGO_AVAILABLE_IN_ALL
-GType            pango_layout_iter_get_type (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_ALL
-PangoLayoutIter *pango_layout_get_iter  (PangoLayout     *layout);
-PANGO_AVAILABLE_IN_1_20
-PangoLayoutIter *pango_layout_iter_copy (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_ALL
-void             pango_layout_iter_free (PangoLayoutIter *iter);
-
-PANGO_AVAILABLE_IN_ALL
-int              pango_layout_iter_get_index  (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_ALL
-PangoLayoutRun  *pango_layout_iter_get_run    (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_1_16
-PangoLayoutRun  *pango_layout_iter_get_run_readonly   (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_ALL
-PangoLayoutLine *pango_layout_iter_get_line   (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_1_16
-PangoLayoutLine *pango_layout_iter_get_line_readonly  (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_ALL
-gboolean         pango_layout_iter_at_last_line (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_1_20
-PangoLayout     *pango_layout_iter_get_layout (PangoLayoutIter *iter);
-
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_layout_iter_next_char    (PangoLayoutIter *iter);
 PANGO_AVAILABLE_IN_ALL
-gboolean pango_layout_iter_next_cluster (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_layout_iter_next_run     (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_layout_iter_next_line    (PangoLayoutIter *iter);
+GQuark                  pango_layout_deserialize_error_quark (void);
 
 PANGO_AVAILABLE_IN_ALL
-void pango_layout_iter_get_char_extents    (PangoLayoutIter *iter,
-                                           PangoRectangle  *logical_rect);
-PANGO_AVAILABLE_IN_ALL
-void pango_layout_iter_get_cluster_extents (PangoLayoutIter *iter,
-                                           PangoRectangle  *ink_rect,
-                                           PangoRectangle  *logical_rect);
-PANGO_AVAILABLE_IN_ALL
-void pango_layout_iter_get_run_extents     (PangoLayoutIter *iter,
-                                           PangoRectangle  *ink_rect,
-                                           PangoRectangle  *logical_rect);
-PANGO_AVAILABLE_IN_ALL
-void pango_layout_iter_get_line_extents    (PangoLayoutIter *iter,
-                                           PangoRectangle  *ink_rect,
-                                           PangoRectangle  *logical_rect);
-/* All the yranges meet, unlike the logical_rect's (i.e. the yranges
- * assign between-line spacing to the nearest line)
- */
-PANGO_AVAILABLE_IN_ALL
-void pango_layout_iter_get_line_yrange     (PangoLayoutIter *iter,
-                                           int             *y0_,
-                                           int             *y1_);
-PANGO_AVAILABLE_IN_ALL
-void pango_layout_iter_get_layout_extents  (PangoLayoutIter *iter,
-                                           PangoRectangle  *ink_rect,
-                                           PangoRectangle  *logical_rect);
-PANGO_AVAILABLE_IN_ALL
-int  pango_layout_iter_get_baseline        (PangoLayoutIter *iter);
-PANGO_AVAILABLE_IN_1_50
-int  pango_layout_iter_get_run_baseline    (PangoLayoutIter *iter);
-
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayout, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayoutIter, pango_layout_iter_free)
+PangoLayout *           pango_layout_deserialize    (PangoContext                 *context,
+                                                     GBytes                       *bytes,
+                                                     PangoLayoutDeserializeFlags   flags,
+                                                     GError                      **error);
 
 G_END_DECLS
-
-#endif /* __PANGO_LAYOUT_H__ */
-
diff --git a/pango/pango-line-breaker.c b/pango/pango-line-breaker.c
index cb9e8429..df68fe9f 100644
--- a/pango/pango-line-breaker.c
+++ b/pango/pango-line-breaker.c
@@ -25,26 +25,15 @@
  * A `PangoLineBreaker` breaks text into lines.
  *
  * To use a `PangoLineBreaker`, you must call [method@Pango.LineBreaker.add_text]
- * to provide text that you want to break into lines, plus possibly attributes
+ * to provide text that you want to break into lines, plus possibly attribute
  * to influence the formatting.
  *
  * Then you can call [method@Pango.LineBreaker.next_line] repeatedly to obtain
- * `PangoLine` objects for the text, one by one. The parameters that are
- * passed to `pango_line_breaker_next_line`, as well as properties of the
- * `PangoLineBreaker` can be changed from call to call. For example, you can
- * pass `PANGO_ELLIPSIZE_END` to consume the remaining text with a single,
- * ellipsized line once you have produced enough lines to fill your desired
- * height.
+ * `PangoLine` objects for the text, one by one.
  *
- * A convenient way to keep track of the lines that are produced by `PangoLineBreaker`
- * is to add them to a [class@Pango.Lines] object, together with positioning
- * information. Before doing so, you can tweak the line or its offset, for
- * example to implement alignment and justification (for the latter, see
- * [method Pango Line.justify]).
- *
- * `PangoLineBreaker` is meant to enable use cases like flowing text around
- * images, shaped paragraphs or multi-column layout. For simple formatting
- * needs, [class@Pango.Layout] is probably more convenient to use.
+ * `PangoLineBreaker` is meant to enable use cases like flowing text around images,
+ * or shaped paragraphs. For simple formatting needs, [class@Pango.Layout]
+ * is probably more convenient to use.
  */
 
 typedef struct _LastTabState LastTabState;
@@ -610,8 +599,8 @@ pad_glyphstring_left (PangoLineBreaker *self,
 }
 
 static gboolean
-is_tab_run (PangoLine      *line,
-            PangoGlyphItem *run)
+is_tab_run (PangoLine       *line,
+            PangoGlyphItem  *run)
 {
   return line->data->text[run->item->offset] == '\t';
 }
@@ -2529,18 +2518,15 @@ pango_line_breaker_has_line (PangoLineBreaker *self)
  * Gets the next line.
  *
  * The `PangoLineBreaker` will use as much of its unprocessed text
- * as will fit into @width. If @width is -1, then all remaining
- * text will be included in the returned line. If @ellipsize is not
- * `PANGO_ELLIPSIZE_NONE`, then all unprocessed text will be made
- * to fit by ellipsizing.
+ * as will fit into @width. The @x position is used to determine
+ * where tabs are located are.
  *
- * The @x position is used to determine where tabs are located,
- * so when using tabs, it is important to draw the line at the
- * same X position that was passed here.
+ * If @ellipsize is not `PANGO_ELLIPSIZE_NONE`, then all unprocessed
+ * text will be made to fit by ellipsizing.
  *
- * Note that the line is not positioned - the leftmost point of its
- * baseline is at 0, 0. See [class@Pango.Lines] for a way to hold
- * a list of positioned `PangoLine` objects.
+ * Note that the line is not positioned - the leftmost point of its baseline
+ * is at 0, 0. See [class@Pango.Lines] for a way to hold a list of positioned
+ * `PangoLine` objects.
  *
  *     line = pango_line_breaker_next_line (breaker,
  *                                          x, width,
diff --git a/pango/pango-line-iter.c b/pango/pango-line-iter.c
index 4625d064..627752a4 100644
--- a/pango/pango-line-iter.c
+++ b/pango/pango-line-iter.c
@@ -3,7 +3,7 @@
 #include "pango-line-iter-private.h"
 #include "pango-lines-private.h"
 #include "pango-line-private.h"
-#include "pango-layout-run-private.h"
+#include "pango-run-private.h"
 
 /**
  * PangoLineIter:
@@ -18,6 +18,7 @@
  * fields.
  */
 
+
 /* {{{ PangoLineIter implementation */
 
 struct _PangoLineIter
@@ -30,7 +31,7 @@ struct _PangoLineIter
   int line_y;
   PangoLine *line;
   GSList *run_link;
-  PangoLayoutRun *run;
+  PangoRun *run;
   int index;
 
   /* run handling */
@@ -118,7 +119,7 @@ update_cluster (PangoLineIter *iter,
   char *cluster_text;
   int  cluster_length;
 
-  glyph_item = pango_layout_run_get_glyph_item (iter->run);
+  glyph_item = pango_run_get_glyph_item (iter->run);
 
   iter->character_position = 0;
 
@@ -224,7 +225,7 @@ next_cluster_internal (PangoLineIter *iter,
   if (iter->run == NULL)
     return next_nonempty_line (iter, include_terminators);
 
-  glyph_item = pango_layout_run_get_glyph_item (iter->run);
+  glyph_item = pango_run_get_glyph_item (iter->run);
 
   if (iter->next_cluster_glyph == glyph_item->glyphs->num_glyphs)
     {
@@ -247,7 +248,7 @@ update_run (PangoLineIter *iter,
   PangoGlyphItem *glyph_item;
 
   if (iter->run)
-    glyph_item = pango_layout_run_get_glyph_item (iter->run);
+    glyph_item = pango_run_get_glyph_item (iter->run);
 
   if (iter->run_link == iter->line->runs)
     iter->run_x = 0;
@@ -320,7 +321,7 @@ offset_run (PangoLineIter  *iter,
 }
 
 /* }}} */
-/*  {{{ Private API */
+/*  {{{ Private API */ 
 
 PangoLineIter *
 pango_line_iter_new (PangoLines *lines)
@@ -341,7 +342,7 @@ pango_line_iter_new (PangoLines *lines)
   if (iter->run_link)
     {
       iter->run = iter->run_link->data;
-      run_start_index = iter->run->item->offset;
+      run_start_index = pango_run_get_glyph_item (iter->run)->item->offset;
     }
   else
     {
@@ -455,7 +456,7 @@ pango_line_iter_at_last_line (PangoLineIter *iter)
  *
  * Return value: (transfer none) (nullable): the current run
  */
-PangoLayoutRun *
+PangoRun *
 pango_line_iter_get_run (PangoLineIter *iter)
 {
   g_return_val_if_fail (ITER_IS_VALID (iter), NULL);
@@ -541,13 +542,14 @@ pango_line_iter_next_run (PangoLineIter *iter)
   iter->run_link = iter->run_link->next;
   if (iter->run_link == NULL)
     {
-      run_start_index = iter->run->item->offset + iter->run->item->length;
+      PangoItem *item = pango_run_get_glyph_item (iter->run)->item;
+      run_start_index = item->offset + item->length;
       iter->run = NULL;
     }
   else
     {
       iter->run = iter->run_link->data;
-      run_start_index = iter->run->item->offset;
+      run_start_index = pango_run_get_glyph_item (iter->run)->item->offset;
     }
 
   update_run (iter, run_start_index);
@@ -690,7 +692,7 @@ pango_line_iter_get_trimmed_line_extents (PangoLineIter    *iter,
  *
  * The logical extents returned by this function always have their leading
  * trimmed off. If you need extents that include leading, use
- * [method@Pango.LayoutRun.get_extents].
+ * [method Pango Run.get_extents].
  */
 void
 pango_line_iter_get_run_extents (PangoLineIter  *iter,
@@ -701,7 +703,7 @@ pango_line_iter_get_run_extents (PangoLineIter  *iter,
 
   if (iter->run)
     {
-      pango_layout_run_get_extents (iter->run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect);
+      pango_run_get_extents (iter->run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect);
     }
   else
     {
@@ -709,9 +711,9 @@ pango_line_iter_get_run_extents (PangoLineIter  *iter,
       if (runs)
         {
           /* Virtual run at the end of a nonempty line */
-          PangoLayoutRun *run = g_slist_last (runs)->data;
+          PangoRun *run = g_slist_last (runs)->data;
 
-          pango_layout_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect);
+          pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, ink_rect, logical_rect);
           if (ink_rect)
             {
               ink_rect->x += ink_rect->width;
@@ -768,7 +770,7 @@ pango_line_iter_get_cluster_extents (PangoLineIter  *iter,
       return;
     }
 
-  glyph_item = pango_layout_run_get_glyph_item (iter->run);
+  glyph_item = pango_run_get_glyph_item (iter->run);
 
   pango_glyph_string_extents_range (glyph_item->glyphs,
                                     iter->cluster_start,
@@ -781,14 +783,14 @@ pango_line_iter_get_cluster_extents (PangoLineIter  *iter,
   if (ink_rect)
     {
       ink_rect->x += iter->cluster_x + glyph_item->start_x_offset;
-      ink_rect->y -= iter->run->y_offset;
+      ink_rect->y -= glyph_item->y_offset;
     }
 
   if (logical_rect)
     {
       g_assert (logical_rect->width == iter->cluster_width);
       logical_rect->x += iter->cluster_x + glyph_item->start_x_offset;
-      logical_rect->y -= iter->run->y_offset;
+      logical_rect->y -= glyph_item->y_offset;
     }
 }
 
@@ -878,11 +880,11 @@ pango_line_iter_get_run_baseline (PangoLineIter *iter)
   g_return_val_if_fail (ITER_IS_VALID (iter), 0);
 
   if (iter->run)
-    return pango_line_iter_get_line_baseline (iter) - pango_layout_run_get_glyph_item (iter->run)->y_offset;
+    return pango_line_iter_get_line_baseline (iter) - pango_run_get_glyph_item (iter->run)->y_offset;
   else
     return pango_line_iter_get_line_baseline (iter);
 }
 
-/* }}} */
+/* }}} */ 
 
 /* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-line-iter.h b/pango/pango-line-iter.h
index 7bdbfb23..84c3c856 100644
--- a/pango/pango-line-iter.h
+++ b/pango/pango-line-iter.h
@@ -28,76 +28,74 @@
 G_BEGIN_DECLS
 
 PANGO_AVAILABLE_IN_ALL
-GType                   pango_line_iter_get_type           (void) G_GNUC_CONST;
+GType                pango_line_iter_get_type                 (void) G_GNUC_CONST;
 
 PANGO_AVAILABLE_IN_ALL
-PangoLineIter *         pango_line_iter_copy                (PangoLineIter *iter);
+PangoLineIter *      pango_line_iter_copy                     (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_free                (PangoLineIter *iter);
+void                 pango_line_iter_free                     (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-PangoLines *            pango_line_iter_get_lines           (PangoLineIter *iter);
+PangoLines *         pango_line_iter_get_lines                (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-PangoLine *             pango_line_iter_get_line            (PangoLineIter *iter);
+PangoLine *          pango_line_iter_get_line                 (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_iter_at_last_line        (PangoLineIter *iter);
+gboolean             pango_line_iter_at_last_line             (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-PangoLayoutRun *        pango_line_iter_get_run             (PangoLineIter *iter);
+PangoRun *           pango_line_iter_get_run                  (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-int                     pango_line_iter_get_index           (PangoLineIter *iter);
+int                  pango_line_iter_get_index                (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_iter_next_line           (PangoLineIter *iter);
+gboolean             pango_line_iter_next_line                (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_iter_next_run            (PangoLineIter *iter);
+gboolean             pango_line_iter_next_run                 (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_iter_next_cluster        (PangoLineIter *iter);
+gboolean             pango_line_iter_next_cluster             (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_iter_next_char           (PangoLineIter *iter);
+gboolean             pango_line_iter_next_char                (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_get_layout_extents  (PangoLineIter  *iter,
-                                                             PangoRectangle *ink_rect,
-                                                             PangoRectangle *logical_rect);
+void                 pango_line_iter_get_layout_extents       (PangoLineIter    *iter,
+                                                               PangoRectangle   *ink_rect,
+                                                               PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_get_line_extents    (PangoLineIter  *iter,
-                                                             PangoRectangle *ink_rect,
-                                                             PangoRectangle *logical_rect);
+void                 pango_line_iter_get_line_extents         (PangoLineIter    *iter,
+                                                               PangoRectangle   *ink_rect,
+                                                               PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_get_trimmed_line_extents
-                                                            (PangoLineIter    *iter,
-                                                             PangoLeadingTrim  trim,
-                                                             PangoRectangle   *logical_rect);
+void                 pango_line_iter_get_trimmed_line_extents (PangoLineIter    *iter,
+                                                               PangoLeadingTrim  trim,
+                                                               PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_get_run_extents     (PangoLineIter  *iter,
-                                                             PangoRectangle *ink_rect,
-                                                             PangoRectangle *logical_rect);
+void                 pango_line_iter_get_run_extents          (PangoLineIter    *iter,
+                                                               PangoRectangle   *ink_rect,
+                                                               PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_get_cluster_extents (PangoLineIter  *iter,
-                                                             PangoRectangle *ink_rect,
-                                                             PangoRectangle *logical_rect);
+void                 pango_line_iter_get_cluster_extents      (PangoLineIter    *iter,
+                                                               PangoRectangle   *ink_rect,
+                                                               PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_iter_get_char_extents    (PangoLineIter  *iter,
-                                                             PangoRectangle *logical_rect);
+void                 pango_line_iter_get_char_extents         (PangoLineIter    *iter,
+                                                               PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-int                     pango_line_iter_get_line_baseline   (PangoLineIter  *iter);
+int                  pango_line_iter_get_line_baseline        (PangoLineIter    *iter);
 
 PANGO_AVAILABLE_IN_ALL
-int                     pango_line_iter_get_run_baseline    (PangoLineIter  *iter);
-
+int                  pango_line_iter_get_run_baseline         (PangoLineIter    *iter);
 
 G_END_DECLS
diff --git a/pango/pango-line-private.h b/pango/pango-line-private.h
index dccb3982..ecd0f5bc 100644
--- a/pango/pango-line-private.h
+++ b/pango/pango-line-private.h
@@ -66,20 +66,20 @@ struct _PangoLine
   PangoRectangle logical_rect;
 };
 
-PangoLine * pango_line_new       (PangoContext       *context,
-                                  LineData           *data);
+PangoLine * pango_line_new               (PangoContext       *context,
+                                          LineData           *data);
 
-void        pango_line_ellipsize (PangoLine          *line,
-                                  PangoContext       *context,
-                                  PangoEllipsizeMode  ellipsize,
-                                  int                 goal_width);
+void        pango_line_ellipsize         (PangoLine          *line,
+                                          PangoContext       *context,
+                                          PangoEllipsizeMode  ellipsize,
+                                          int                 goal_width);
 
-void        pango_line_index_to_run (PangoLine       *line,
-                                     int              idx,
-                                     PangoLayoutRun **run);
+void        pango_line_index_to_run      (PangoLine          *line,
+                                          int                 idx,
+                                          PangoRun          **run);
 
-void        pango_line_get_empty_extents (PangoLine        *line,
-                                          PangoLeadingTrim  trim,
-                                          PangoRectangle   *logical_rect);
+void        pango_line_get_empty_extents (PangoLine          *line,
+                                          PangoLeadingTrim    trim,
+                                          PangoRectangle     *logical_rect);
 
-void        pango_line_check_invariants (PangoLine *line);
+void        pango_line_check_invariants  (PangoLine          *line);
diff --git a/pango/pango-line.c b/pango/pango-line.c
index c06e9007..5782e30c 100644
--- a/pango/pango-line.c
+++ b/pango/pango-line.c
@@ -6,7 +6,7 @@
 #include "pango-impl-utils.h"
 #include "pango-attributes-private.h"
 #include "pango-item-private.h"
-#include "pango-layout-run-private.h"
+#include "pango-run-private.h"
 
 #include <math.h>
 #include <hb-ot.h>
@@ -14,12 +14,12 @@
 /**
  * PangoLine:
  *
- * A `PangoLine` represents one of the lines resulting from laying
- * out a paragraph via `PangoLayout` or `PangoLineBreaker`.
+ * A `PangoLine` is an immutable object which represents a line resulting
+ * from laying out text via `PangoLayout` or `PangoLineBreaker`.
  *
  * A line consists of a number of runs (i.e. ranges of text with uniform
  * script, font and attributes that are shaped as a unit). Runs are
- * represented as [struct@Pango.LayoutRun] objects.
+ * represented as [struct Pango Run] objects.
  *
  * A `PangoLine` always has its origin at the leftmost point  of its
  * baseline. To position lines in an entire paragraph of text (i.e. in layout
@@ -337,12 +337,12 @@ compute_extents (PangoLine        *line,
 
   for (GSList *l = line->runs; l; l = l->next)
     {
-      PangoLayoutRun *run = l->data;
+      PangoRun *run = l->data;
       PangoRectangle run_ink;
       PangoRectangle run_logical;
       int new_pos;
 
-      pango_layout_run_get_extents (run, trim, &run_ink, &run_logical);
+      pango_run_get_extents (run, trim, &run_ink, &run_logical);
 
       if (ink->width == 0 || ink->height == 0)
         {
@@ -553,18 +553,18 @@ pango_line_new (PangoContext *context,
  * Finds the run in @line which contains @idx.
  */
 void
-pango_line_index_to_run (PangoLine       *line,
-                         int              idx,
-                         PangoLayoutRun **run)
+pango_line_index_to_run (PangoLine  *line,
+                         int         idx,
+                         PangoRun  **run)
 {
   *run = NULL;
 
   for (GSList *l = line->runs; l; l = l->next)
     {
-      PangoLayoutRun *r = l->data;
+      PangoRun *r = l->data;
       PangoItem *item;
 
-      item = pango_layout_run_get_glyph_item (r)->item;
+      item = pango_run_get_glyph_item (r)->item;
       if (item->offset <= idx && idx < item->offset + item->length)
         {
           *run = r;
@@ -783,7 +783,7 @@ pango_line_is_hyphenated (PangoLine *line)
  *
  * Gets whether the line is justified.
  *
- * See [method Pango Line.justify].
+ * See [method@Pango.LayoutLine.justify].
  *
  * Returns: `TRUE` if @line has been justified
  */
@@ -913,7 +913,7 @@ pango_line_justify (PangoLine *line,
  * trimmed according to paragraph boundaries: if the line starts a paragraph,
  * it has its start leading trimmed; if it ends a paragraph, it has its end
  * leading trimmed. If you need other trimming, use
- * [method Pango Line.get_trimmed_extents].
+ * [method@Pango.LayoutLine.get_trimmed_extents].
  *
  * Note that the origin is at the left end of the baseline.
  */
@@ -1010,7 +1010,7 @@ pango_line_index_to_pos (PangoLine      *line,
 {
   PangoRectangle run_logical;
   PangoRectangle line_logical;
-  PangoLayoutRun *run = NULL;
+  PangoRun *run = NULL;
   int x_pos;
 
   pango_line_get_extents (line, NULL, &line_logical);
@@ -1026,7 +1026,7 @@ pango_line_index_to_pos (PangoLine      *line,
   else
     pango_line_index_to_run (line, idx, &run);
 
-  pango_layout_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_logical);
+  pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_logical);
 
   pos->y = run_logical.y;
   pos->height = run_logical.height;
@@ -1358,7 +1358,7 @@ pango_line_get_cursor_pos (PangoLine      *line,
   PangoRectangle run_rect = { 666, };
   PangoDirection dir1, dir2;
   int level1, level2;
-  PangoLayoutRun *run = NULL;
+  PangoRun *run = NULL;
   int x1_trailing;
   int x2;
 
@@ -1372,7 +1372,7 @@ pango_line_get_cursor_pos (PangoLine      *line,
 
   pango_line_get_extents (line, NULL, &line_rect);
   if (run)
-    pango_layout_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_rect);
+    pango_run_get_extents (run, PANGO_LEADING_TRIM_BOTH, NULL, &run_rect);
   else
     {
       run_rect = line_rect;
@@ -1402,10 +1402,10 @@ pango_line_get_cursor_pos (PangoLine      *line,
         }
       else
         {
-          PangoLayoutRun *prev_run;
+          PangoRun *prev_run;
 
           pango_line_index_to_run (line, prev_index, &prev_run);
-          level1 = pango_layout_run_get_glyph_item (prev_run)->item->analysis.level;
+          level1 = pango_run_get_glyph_item (prev_run)->item->analysis.level;
           dir1 = level1 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
           pango_line_index_to_x (line, prev_index, TRUE, &x1_trailing);
         }
@@ -1424,7 +1424,7 @@ pango_line_get_cursor_pos (PangoLine      *line,
   else
     {
       pango_line_index_to_x (line, idx, FALSE, &x2);
-      level2 = pango_layout_run_get_glyph_item (run)->item->analysis.level;
+      level2 = pango_run_get_glyph_item (run)->item->analysis.level;
       dir2 = level2 % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
     }
 
@@ -1472,7 +1472,7 @@ done:
  *
  * Note that @idx is allowed to be @line->start_index + @line->length.
  *
- * This is a variant of [method Pango Line.get_cursor_pos] that applies
+ * This is a variant of [method@Pango.LayoutLine.get_cursor_pos] that applies
  * font metric information about caret slope and offset to the positions
  * it returns.
  *
@@ -1487,7 +1487,7 @@ pango_line_get_caret_pos (PangoLine      *line,
                           PangoRectangle *strong_pos,
                           PangoRectangle *weak_pos)
 {
-  PangoLayoutRun *run = NULL;
+  PangoRun *run = NULL;
   PangoGlyphItem *glyph_item;
   hb_font_t *hb_font;
   hb_position_t caret_offset, caret_run, caret_rise, descender;
@@ -1505,7 +1505,7 @@ pango_line_get_caret_pos (PangoLine      *line,
   if (!run)
     return;
 
-  glyph_item = pango_layout_run_get_glyph_item (run);
+  glyph_item = pango_run_get_glyph_item (run);
   hb_font = pango_font_get_hb_font (glyph_item->item->analysis.font);
 
   if (hb_ot_metrics_get_position (hb_font, HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, &caret_rise) &&
diff --git a/pango/pango-line.h b/pango/pango-line.h
index 606f794e..2293d6c4 100644
--- a/pango/pango-line.h
+++ b/pango/pango-line.h
@@ -22,105 +22,100 @@
 #include <glib-object.h>
 
 #include <pango/pango-types.h>
-#include <pango/pango-layout-run.h>
+#include <pango/pango-run.h>
 
 G_BEGIN_DECLS
 
-typedef PangoGlyphItem PangoLayoutRun;
-typedef struct _PangoLine PangoLine;
-
 PANGO_AVAILABLE_IN_ALL
-GType                   pango_line_get_type             (void) G_GNUC_CONST;
+GType                pango_line_get_type               (void) G_GNUC_CONST;
 
 PANGO_AVAILABLE_IN_ALL
-PangoLine *             pango_line_copy                 (PangoLine             *line);
+PangoLine *          pango_line_copy                   (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_free                 (PangoLine             *line);
-
+void                 pango_line_free                   (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-PangoLine *             pango_line_justify              (PangoLine             *line,
-                                                         int                    width);
+PangoLine *          pango_line_justify                (PangoLine        *line,
+                                                        int               width);
 
 PANGO_AVAILABLE_IN_ALL
-GSList *                pango_line_get_runs             (PangoLine             *line);
+GSList *             pango_line_get_runs               (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-const char *            pango_line_get_text             (PangoLine             *line,
-                                                         int                   *start_index,
-                                                         int                   *length);
+const char *         pango_line_get_text               (PangoLine        *line,
+                                                        int              *start_index,
+                                                        int              *length);
 
 PANGO_AVAILABLE_IN_ALL
-int                     pango_line_get_start_index      (PangoLine             *line);
+int                  pango_line_get_start_index        (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-int                     pango_line_get_length           (PangoLine             *line);
+int                  pango_line_get_length             (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-const PangoLogAttr *    pango_line_get_log_attrs        (PangoLine             *line,
-                                                         int                   *start_offset,
-                                                         int                   *n_attrs);
+const PangoLogAttr * pango_line_get_log_attrs          (PangoLine        *line,
+                                                        int              *start_offset,
+                                                        int              *n_attrs);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_is_wrapped           (PangoLine             *line);
+gboolean             pango_line_is_wrapped             (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_is_ellipsized        (PangoLine             *line);
+gboolean             pango_line_is_ellipsized          (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_is_hyphenated        (PangoLine             *line);
+gboolean             pango_line_is_hyphenated          (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_is_justified         (PangoLine             *line);
+gboolean             pango_line_is_justified           (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_is_paragraph_start   (PangoLine             *line);
+gboolean             pango_line_is_paragraph_start     (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_is_paragraph_end     (PangoLine             *line);
+gboolean             pango_line_is_paragraph_end       (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-PangoDirection          pango_line_get_resolved_direction
-                                                        (PangoLine             *line);
+PangoDirection       pango_line_get_resolved_direction (PangoLine        *line);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_get_extents          (PangoLine             *line,
-                                                         PangoRectangle        *ink_rect,
-                                                         PangoRectangle        *logical_rect);
+void                 pango_line_get_extents            (PangoLine        *line,
+                                                        PangoRectangle   *ink_rect,
+                                                        PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_get_trimmed_extents  (PangoLine             *line,
-                                                         PangoLeadingTrim       trim,
-                                                         PangoRectangle        *logical_rect);
+void                 pango_line_get_trimmed_extents    (PangoLine        *line,
+                                                        PangoLeadingTrim  trim,
+                                                        PangoRectangle   *logical_rect);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_index_to_pos         (PangoLine             *line,
-                                                         int                    idx,
-                                                         PangoRectangle        *pos);
+void                 pango_line_index_to_pos           (PangoLine        *line,
+                                                        int               idx,
+                                                        PangoRectangle   *pos);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_index_to_x           (PangoLine             *line,
-                                                         int                    idx,
-                                                         int                    trailing,
-                                                         int                   *x_pos);
+void                 pango_line_index_to_x             (PangoLine        *line,
+                                                        int               idx,
+                                                        int               trailing,
+                                                        int              *x_pos);
 
 PANGO_AVAILABLE_IN_ALL
-gboolean                pango_line_x_to_index           (PangoLine             *line,
-                                                         int                    x,
-                                                         int                   *idx,
-                                                         int                   *trailing);
+gboolean             pango_line_x_to_index             (PangoLine        *line,
+                                                        int               x,
+                                                        int              *idx,
+                                                        int              *trailing);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_get_cursor_pos       (PangoLine             *line,
-                                                         int                    idx,
-                                                         PangoRectangle        *strong_pos,
-                                                         PangoRectangle        *weak_pos);
+void                 pango_line_get_cursor_pos         (PangoLine        *line,
+                                                        int               idx,
+                                                        PangoRectangle   *strong_pos,
+                                                        PangoRectangle   *weak_pos);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_line_get_caret_pos        (PangoLine             *line,
-                                                         int                    idx,
-                                                         PangoRectangle        *strong_pos,
-                                                         PangoRectangle        *weak_pos);
+void                 pango_line_get_caret_pos          (PangoLine        *line,
+                                                        int               idx,
+                                                        PangoRectangle   *strong_pos,
+                                                        PangoRectangle   *weak_pos);
 
 G_END_DECLS
diff --git a/pango/pango-lines.c b/pango/pango-lines.c
index 0c678a73..b5dae232 100644
--- a/pango/pango-lines.c
+++ b/pango/pango-lines.c
@@ -11,7 +11,7 @@
  * A `PangoLines` object represents the result of formatting an
  * entire paragraph (or more) of text.
  *
- * A `PangoLines` object contains a list of `PangoLayoutLine` objects,
+ * A `PangoLines` object contains a list of `PangoLine` objects,
  * together with information about where to position each line
  * in layout coordinates.
  *
@@ -35,7 +35,7 @@
  * for the `PangoLines*`.
  *
  * The most convenient way to access the visual extents and components
- * of a `PangoLines` is via a [struct@Pango.LayoutIter] iterator.
+ * of a `PangoLines` is via a [struct@Pango.LineIter] iterator.
  */
 
 /*  {{{ PangoLines implementation */
@@ -104,10 +104,10 @@ compare_cursor (gconstpointer v1,
 }
 
 static void
-pango_line_get_cursors (PangoLines *lines,
-                        PangoLine  *line,
-                        gboolean    strong,
-                        GArray     *cursors)
+pango_line_get_cursors (PangoLines      *lines,
+                        PangoLine       *line,
+                        gboolean         strong,
+                        GArray          *cursors)
 {
   const char *start, *end;
   int start_offset;
@@ -158,7 +158,7 @@ pango_line_get_cursors (PangoLines *lines,
 }
 
 /* }}} */
-/* {{{ Public API */
+ /* {{{ Public API */
 
 /**
  * pango_lines_new:
@@ -212,10 +212,10 @@ pango_lines_get_serial (PangoLines *lines)
  * Note that this function takes ownership of the line.
  */
 void
-pango_lines_add_line (PangoLines *lines,
-                      PangoLine  *line,
-                      int         x_line,
-                      int         y_line)
+pango_lines_add_line (PangoLines      *lines,
+                      PangoLine       *line,
+                      int              x_line,
+                      int              y_line)
 {
   Line l;
 
@@ -523,7 +523,7 @@ pango_lines_get_baseline (PangoLines *lines)
 }
 
 /**
- * pango_layout_lines_get_x_ranges:
+ * pango_lines_get_x_ranges:
  * @lines: a `PangoLines` object
  * @line: the `PangoLine` in @lines whose x ranges will be reported
  * @start_line: (nullable): `PangoLine` wrt to which @start_index is
@@ -554,14 +554,14 @@ pango_lines_get_baseline (PangoLines *lines)
  * layout, not with respect to the line.
  */
 void
-pango_lines_get_x_ranges (PangoLines  *lines,
-                          PangoLine   *line,
-                          PangoLine   *start_line,
-                          int          start_index,
-                          PangoLine   *end_line,
-                          int          end_index,
-                          int        **ranges,
-                          int         *n_ranges)
+pango_lines_get_x_ranges (PangoLines *lines,
+                          PangoLine  *line,
+                          PangoLine  *start_line,
+                          int         start_index,
+                          PangoLine  *end_line,
+                          int         end_index,
+                          int       **ranges,
+                          int        *n_ranges)
 {
   int x_offset;
   int line_no, start_line_no, end_line_no;
@@ -691,8 +691,8 @@ pango_lines_get_x_ranges (PangoLines  *lines,
  * Given an index (and possibly line), determine the line number,
  * and offset for the line.
  *
- * @idx may refer to any byte position inside @lines, as well
- * as the position before the first or after the last character (i.e.
+ * @idx may refer to any byte position inside @lines, as well as
+ * the position before the first or after the last character (i.e.
  * line->start_index + line->length, for the last line).
  *
  * If @lines contains lines with different backing data (i.e.
@@ -702,12 +702,12 @@ pango_lines_get_x_ranges (PangoLines  *lines,
  * as *@line and use this function to find the line at @idx.
  */
 void
-pango_lines_index_to_line (PangoLines  *lines,
-                           int          idx,
-                           PangoLine  **line,
-                           int         *line_no,
-                           int         *x_offset,
-                           int         *y_offset)
+pango_lines_index_to_line (PangoLines *lines,
+                           int         idx,
+                           PangoLine **line,
+                           int        *line_no,
+                           int        *x_offset,
+                           int        *y_offset)
 {
   Line *found = NULL;
   int num;
@@ -764,11 +764,11 @@ pango_lines_index_to_line (PangoLines  *lines,
  * Returns: (transfer none) (nullable): the line that was found
  */
 PangoLine *
-pango_lines_pos_to_line (PangoLines  *lines,
-                         int          x,
-                         int          y,
-                         int         *line_x,
-                         int         *line_y)
+pango_lines_pos_to_line (PangoLines *lines,
+                         int         x,
+                         int         y,
+                         int        *line_x,
+                         int        *line_y)
 {
   g_return_val_if_fail (PANGO_IS_LINES (lines), FALSE);
 
@@ -859,11 +859,11 @@ pango_lines_index_to_pos (PangoLines     *lines,
  * Returns: (transfer none) (nullable): the line that was found
  */
 PangoLine *
-pango_lines_pos_to_index (PangoLines  *lines,
-                          int          x,
-                          int          y,
-                          int         *idx,
-                          int         *trailing)
+pango_lines_pos_to_index (PangoLines *lines,
+                          int         x,
+                          int         y,
+                          int        *idx,
+                          int        *trailing)
 {
   PangoLine *line;
   int x_offset;
diff --git a/pango/pango-lines.h b/pango/pango-lines.h
index d89e5a73..3b379aff 100644
--- a/pango/pango-lines.h
+++ b/pango/pango-lines.h
@@ -31,8 +31,6 @@ G_BEGIN_DECLS
 PANGO_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (PangoLines, pango_lines, PANGO, LINES, GObject);
 
-typedef struct _PangoLineIter PangoLineIter;
-
 PANGO_AVAILABLE_IN_ALL
 PangoLines *            pango_lines_new             (void);
 
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 015fe972..8bc33d83 100644
--- a/pango/pango-renderer.c
+++ b/pango/pango-renderer.c
@@ -24,9 +24,9 @@
 
 #include "pango-renderer.h"
 #include "pango-impl-utils.h"
-#include "pango-layout-private.h"
+#include "pango-layout.h"
+#include "pango-run-private.h"
 #include "pango-line-private.h"
-#include "pango-layout-run-private.h"
 
 #define N_RENDER_PARTS 5
 
@@ -65,7 +65,7 @@ struct _PangoRendererPrivate
   guint16 alpha[N_RENDER_PARTS];
 
   PangoLines *lines;
-  PangoLayoutLine *line;
+  PangoLine *line;
   LineState *line_state;
   PangoOverline overline;
 };
@@ -93,10 +93,10 @@ static void pango_renderer_default_draw_error_underline (PangoRenderer    *rende
                                                          int               width,
                                                          int               height);
 static void pango_renderer_default_prepare_run          (PangoRenderer    *renderer,
-                                                         PangoLayoutRun   *run);
+                                                         PangoRun         *run);
 
-static void pango_renderer_prepare_run (PangoRenderer  *renderer,
-                                        PangoLayoutRun *run);
+static void pango_renderer_prepare_run                  (PangoRenderer    *renderer,
+                                                         PangoRun         *run);
 
 static void
 to_device (PangoMatrix *matrix,
@@ -165,60 +165,6 @@ pango_renderer_activate_with_context (PangoRenderer *renderer,
   pango_renderer_activate (renderer);
 }
 
-/**
- * pango_renderer_draw_layout:
- * @renderer: a `PangoRenderer`
- * @layout: a `PangoLayout`
- * @x: X position of left edge of baseline, in user space coordinates
- *   in Pango units.
- * @y: Y position of left edge of baseline, in user space coordinates
- *   in Pango units.
- *
- * Draws @layout with the specified `PangoRenderer`.
- *
- * This is equivalent to drawing the lines of the layout, at their
- * respective positions relative to @x, @y.
- *
- * Since: 1.8
- */
-void
-pango_renderer_draw_layout (PangoRenderer *renderer,
-                            PangoLayout   *layout,
-                            int            x,
-                            int            y)
-{
-  PangoLayoutIter iter;
-
-  g_return_if_fail (PANGO_IS_RENDERER (renderer));
-  g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
-  pango_renderer_activate_with_context (renderer, pango_layout_get_context (layout));
-
-  _pango_layout_get_iter (layout, &iter);
-
-  do
-    {
-      PangoRectangle   logical_rect;
-      PangoLayoutLine *line;
-      int              baseline;
-
-      line = pango_layout_iter_get_line_readonly (&iter);
-
-      pango_layout_iter_get_line_extents (&iter, NULL, &logical_rect);
-      baseline = pango_layout_iter_get_baseline (&iter);
-
-      pango_renderer_draw_layout_line (renderer,
-                                       line,
-                                       x + logical_rect.x,
-                                       y + baseline);
-    }
-  while (pango_layout_iter_next_line (&iter));
-
-  _pango_layout_iter_destroy (&iter);
-
-  pango_renderer_deactivate (renderer);
-}
-
 static void
 draw_underline (PangoRenderer *renderer,
                 LineState     *state)
@@ -564,59 +510,6 @@ static void pango_renderer_draw_runs (PangoRenderer *renderer,
                                       int            x,
                                       int            y);
 
-/**
- * pango_renderer_draw_layout_line:
- * @renderer: a `PangoRenderer`
- * @line: a `PangoLayoutLine`
- * @x: X position of left edge of baseline, in user space coordinates
- *   in Pango units.
- * @y: Y position of left edge of baseline, in user space coordinates
- *   in Pango units.
- *
- * Draws @line with the specified `PangoRenderer`.
- *
- * This draws the glyph items that make up the line, as well as
- * shapes, backgrounds and lines that are specified by the attributes
- * of those items.
- *
- * Since: 1.8
- */
-void
-pango_renderer_draw_layout_line (PangoRenderer   *renderer,
-                                 PangoLayoutLine *line,
-                                 int              x,
-                                 int              y)
-{
-  LineState state = { 0, };
-  const char *text;
-
-  g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
-
-  pango_renderer_activate_with_context (renderer,
-                                        line->layout ? pango_layout_get_context (line->layout) : NULL);
-
-  renderer->priv->line = line;
-  renderer->priv->line_state = &state;
-
-  state.underline = PANGO_UNDERLINE_NONE;
-  state.overline = PANGO_OVERLINE_NONE;
-  state.strikethrough = FALSE;
-
-  text = G_LIKELY (line->layout) ? pango_layout_get_text (line->layout) : NULL;
-
-  pango_renderer_draw_runs (renderer, line->runs, text, x, y);
-
-  /* Finish off any remaining underlines */
-  draw_underline (renderer, &state);
-  draw_overline (renderer, &state);
-  draw_strikethrough (renderer, &state);
-
-  renderer->priv->line_state = NULL;
-  renderer->priv->line = NULL;
-
-  pango_renderer_deactivate (renderer);
-}
-
 /**
  * pango_renderer_draw_line:
  * @renderer: a `PangoRenderer`
@@ -633,10 +526,10 @@ pango_renderer_draw_layout_line (PangoRenderer   *renderer,
  * of those items.
  */
 void
-pango_renderer_draw_line (PangoRenderer *renderer,
-                          PangoLine     *line,
-                          int             x,
-                          int             y)
+pango_renderer_draw_line (PangoRenderer   *renderer,
+                          PangoLine      *line,
+                          int              x,
+                          int              y)
 {
   LineState state = { 0, };
 
@@ -644,7 +537,7 @@ pango_renderer_draw_line (PangoRenderer *renderer,
 
   pango_renderer_activate_with_context (renderer, line->context);
 
-  renderer->priv->line = NULL;
+  renderer->priv->line = line;
   renderer->priv->line_state = &state;
 
   state.underline = PANGO_UNDERLINE_NONE;
@@ -658,6 +551,7 @@ pango_renderer_draw_line (PangoRenderer *renderer,
   draw_overline (renderer, &state);
   draw_strikethrough (renderer, &state);
 
+  renderer->priv->line = NULL;
   renderer->priv->line_state = NULL;
   renderer->priv->line = NULL;
 
@@ -702,6 +596,8 @@ pango_renderer_draw_lines (PangoRenderer *renderer,
 
   if (n > 0)
     pango_renderer_deactivate (renderer);
+
+  renderer->priv->lines = NULL;
 }
 
 static void
@@ -720,7 +616,7 @@ pango_renderer_draw_runs (PangoRenderer *renderer,
   for (l = runs; l; l = l->next)
     {
       PangoFontMetrics *metrics;
-      PangoLayoutRun *run = l->data;
+      PangoRun *run = l->data;
       PangoGlyphItem *glyph_item = l->data;
       PangoItem *item = glyph_item->item;
       PangoGlyphString *glyphs = glyph_item->glyphs;
@@ -918,8 +814,8 @@ pango_renderer_default_draw_glyphs (PangoRenderer    *renderer,
  *
  * Note that this method does not handle attributes in @glyph_item.
  * If you want colors, shapes and lines handled automatically according
- * to those attributes, you need to use pango_renderer_draw_layout_line()
- * or pango_renderer_draw_layout().
+ * to those attributes, you need to use [method@Pango.Renderer.draw_line]
+ * or [method@Pango.Renderer.draw_lines].
  *
  * Note that @text is the start of the text for layout, which is then
  * indexed by `glyph_item->item->offset`.
@@ -1341,7 +1237,7 @@ pango_renderer_draw_glyph (PangoRenderer *renderer,
  * Does initial setup before rendering operations on @renderer.
  *
  * [method@Pango.Renderer.deactivate] should be called when done drawing.
- * Calls such as [method@Pango.Renderer.draw_layout] automatically
+ * Calls such as [method@Pango.Renderer.draw_lines] automatically
  * activate the layout before drawing on it.
  *
  * Calls to [method@Pango.Renderer.activate] and
@@ -1547,7 +1443,7 @@ pango_renderer_part_changed (PangoRenderer   *renderer,
 /**
  * pango_renderer_prepare_run:
  * @renderer: a `PangoRenderer`
- * @run: a `PangoLayoutRun`
+ * @run: a `PangoRun`
  *
  * Set up the state of the `PangoRenderer` for rendering @run.
  *
@@ -1555,7 +1451,7 @@ pango_renderer_part_changed (PangoRenderer   *renderer,
  */
 static void
 pango_renderer_prepare_run (PangoRenderer  *renderer,
-                            PangoLayoutRun *run)
+                            PangoRun       *run)
 {
   g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
 
@@ -1564,7 +1460,7 @@ pango_renderer_prepare_run (PangoRenderer  *renderer,
 
 static void
 pango_renderer_default_prepare_run (PangoRenderer  *renderer,
-                                    PangoLayoutRun *run)
+                                    PangoRun       *run)
 {
   PangoColor *fg_color = NULL;
   PangoColor *bg_color = NULL;
@@ -1576,7 +1472,7 @@ pango_renderer_default_prepare_run (PangoRenderer  *renderer,
   GSList *l;
   PangoGlyphItem *glyph_item;
 
-  glyph_item = pango_layout_run_get_glyph_item (run);
+  glyph_item = pango_run_get_glyph_item (run);
 
   renderer->underline = PANGO_UNDERLINE_NONE;
   renderer->priv->overline = PANGO_OVERLINE_NONE;
@@ -1699,10 +1595,10 @@ pango_renderer_get_matrix (PangoRenderer *renderer)
 }
 
 /**
- * pango_renderer_get_layout:
+ * pango_renderer_get_lines:
  * @renderer: a `PangoRenderer`
  *
- * Gets the layout currently being rendered using @renderer.
+ * Gets the `PangoLines` currently being rendered using @renderer.
  *
  * Calling this function only makes sense from inside a subclass's
  * methods, like in its draw_shape vfunc, for example.
@@ -1710,38 +1606,31 @@ pango_renderer_get_matrix (PangoRenderer *renderer)
  * The returned layout should not be modified while still being
  * rendered.
  *
- * Return value: (transfer none) (nullable): the layout, or %NULL if
- *   no layout is being rendered using @renderer at this time.
- *
- * Since: 1.20
+ * Return value: (transfer none) (nullable): the `PangoLines`, or
+ *   %NULL if no layout is being rendered using @renderer at this time.
  */
-PangoLayout *
-pango_renderer_get_layout (PangoRenderer *renderer)
+PangoLines *
+pango_renderer_get_lines (PangoRenderer *renderer)
 {
-  if (G_UNLIKELY (renderer->priv->line == NULL))
-    return NULL;
-
-  return renderer->priv->line->layout;
+  return renderer->priv->lines;
 }
 
 /**
  * pango_renderer_get_layout_line:
  * @renderer: a `PangoRenderer`
  *
- * Gets the layout line currently being rendered using @renderer.
+ * Gets the line currently being rendered using @renderer.
  *
  * Calling this function only makes sense from inside a subclass's
  * methods, like in its draw_shape vfunc, for example.
  *
- * The returned layout line should not be modified while still being
+ * The returned line should not be modified while still being
  * rendered.
  *
- * Return value: (transfer none) (nullable): the layout line, or %NULL
+ * Return value: (transfer none) (nullable): the line, or %NULL
  *   if no layout line is being rendered using @renderer at this time.
- *
- * Since: 1.20
  */
-PangoLayoutLine *
+PangoLine *
 pango_renderer_get_layout_line (PangoRenderer *renderer)
 {
   return renderer->priv->line;
diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h
index 61f18a72..0f5d0d3f 100644
--- a/pango/pango-renderer.h
+++ b/pango/pango-renderer.h
@@ -22,8 +22,9 @@
 #define __PANGO_RENDERER_H_
 
 #include <pango/pango-layout.h>
-#include <pango/pango-line.h>
 #include <pango/pango-lines.h>
+#include <pango/pango-glyph.h>
+#include <pango/pango-glyph-item.h>
 
 G_BEGIN_DECLS
 
@@ -180,7 +181,7 @@ struct _PangoRendererClass
   void (*end)                  (PangoRenderer    *renderer);
 
   void (*prepare_run)          (PangoRenderer    *renderer,
-                                PangoLayoutRun   *run);
+                                PangoRun         *run);
 
   void (*draw_glyph_item)      (PangoRenderer    *renderer,
                                 const char       *text,
@@ -199,26 +200,17 @@ struct _PangoRendererClass
 PANGO_AVAILABLE_IN_1_8
 GType pango_renderer_get_type            (void) G_GNUC_CONST;
 
-PANGO_AVAILABLE_IN_1_8
-void pango_renderer_draw_layout          (PangoRenderer    *renderer,
-                                          PangoLayout      *layout,
-                                          int               x,
-                                          int               y);
-PANGO_AVAILABLE_IN_1_8
-void pango_renderer_draw_layout_line     (PangoRenderer    *renderer,
-                                          PangoLayoutLine  *line,
+PANGO_AVAILABLE_IN_ALL
+void pango_renderer_draw_lines           (PangoRenderer    *renderer,
+                                          PangoLines       *lines,
                                           int               x,
                                           int               y);
+
 PANGO_AVAILABLE_IN_ALL
 void pango_renderer_draw_line            (PangoRenderer    *renderer,
                                           PangoLine        *line,
                                           int               x,
                                           int               y);
-PANGO_AVAILABLE_IN_ALL
-void pango_renderer_draw_lines           (PangoRenderer    *renderer,
-                                          PangoLines       *lines,
-                                          int               x,
-                                          int               y);
 PANGO_AVAILABLE_IN_1_8
 void pango_renderer_draw_glyphs          (PangoRenderer    *renderer,
                                           PangoFont        *font,
@@ -291,10 +283,11 @@ void               pango_renderer_set_matrix      (PangoRenderer     *renderer,
 PANGO_AVAILABLE_IN_1_8
 const PangoMatrix *pango_renderer_get_matrix      (PangoRenderer     *renderer);
 
-PANGO_AVAILABLE_IN_1_20
-PangoLayout       *pango_renderer_get_layout      (PangoRenderer     *renderer);
-PANGO_AVAILABLE_IN_1_20
-PangoLayoutLine   *pango_renderer_get_layout_line (PangoRenderer     *renderer);
+PANGO_AVAILABLE_IN_ALL
+PangoLines *       pango_renderer_get_lines       (PangoRenderer     *renderer);
+
+PANGO_AVAILABLE_IN_ALL
+PangoLine *        pango_renderer_get_layout_line (PangoRenderer     *renderer);
 
 PANGO_AVAILABLE_IN_ALL
 PangoContext *     pango_renderer_get_context     (PangoRenderer     *renderer);
diff --git a/pango/pango-layout-run-private.h b/pango/pango-run-private.h
similarity index 86%
rename from pango/pango-layout-run-private.h
rename to pango/pango-run-private.h
index dc19d09d..08a5d9cd 100644
--- a/pango/pango-layout-run-private.h
+++ b/pango/pango-run-private.h
@@ -21,13 +21,18 @@
 
 #include "config.h"
 
-#include "pango-layout-run.h"
+#include "pango-run.h"
 #include "pango-glyph-item.h"
 #include "pango-item-private.h"
 
 
+struct _PangoRun
+{
+  PangoGlyphItem glyph_item;
+};
+
 static inline PangoGlyphItem *
-pango_layout_run_get_glyph_item (PangoLayoutRun *run)
+pango_run_get_glyph_item (PangoRun *run)
 {
-  return (PangoGlyphItem *)run;
+  return &run->glyph_item;
 }
diff --git a/pango/pango-layout-run.c b/pango/pango-run.c
similarity index 86%
rename from pango/pango-layout-run.c
rename to pango/pango-run.c
index 8e86d14b..01ecb8d6 100644
--- a/pango/pango-layout-run.c
+++ b/pango/pango-run.c
@@ -1,62 +1,62 @@
 #include "config.h"
 
-#include "pango-layout-run-private.h"
+#include "pango-run-private.h"
 #include "pango-item-private.h"
 #include "pango-impl-utils.h"
 
 #include <math.h>
 
 /**
- * PangoLayoutRun:
+ * PangoRun:
  *
- * A `PangoLayoutRun` represents a single run within a `PangoLayoutLine`.
+ * A `PangoRun` represents a single run within a `PangoLayoutLine`.
  *
  * A run is a range of text with uniform script, font and attributes that
  * is shaped as a unit.
  *
  * Script, font and attributes of a run can be accessed via
- * [method@Pango.LayoutRun.get_item]. The glyphs that result from shaping
- * the text of the run can be obtained via [method@Pango.LayoutRun.get_glyphs].
+ * [method Pango Run.get_item]. The glyphs that result from shaping
+ * the text of the run can be obtained via [method Pango Run.get_glyphs].
  */
 
 /**
- * pango_layout_run_get_item:
- * @run: a `PangoLayoutRun`
+ * pango_run_get_item:
+ * @run: a `PangoRun`
  *
  * Gets the `PangoItem` for the run.
  *
  * Returns: (transfer none): the `PangoItem` of @run
  */
 PangoItem *
-pango_layout_run_get_item (PangoLayoutRun *run)
+pango_run_get_item (PangoRun *run)
 {
-  return run->item;
+  return run->glyph_item.item;
 }
 
 /**
- * pango_layout_run_get_glyphs:
- * @run: a `PangoLayoutRun`
+ * pango_run_get_glyphs:
+ * @run: a `PangoRun`
  *
  * Gets the `PangoGlyphString` for the run.
  *
  * Returns: (transfer none): the `PangoGlyphString` of @run
  */
 PangoGlyphString *
-pango_layout_run_get_glyphs (PangoLayoutRun *run)
+pango_run_get_glyphs (PangoRun *run)
 {
-  return run->glyphs;
+  return run->glyph_item.glyphs;
 }
 
 /**
- * pango_layout_run_get_extents:
- * @run: a `PangoLayoutRun`
+ * pango_run_get_extents:
+ * @run: a `PangoRun`
  * @trim: `PangoLeadingTrim` flags
  * @ink_rect: (out caller-allocates) (optional): return location
  *   for the ink extents
  * @logical_rect: (out caller-allocates) (optional): return location
  *   for the logical extents
  *
- * Gets the extents of a `PangoLayoutRun`.
+ * Gets the extents of a `PangoRun`.
  *
  * The @trim flags specify if line-height attributes are taken
  * into consideration for determining the logical height. See the
@@ -64,12 +64,12 @@ pango_layout_run_get_glyphs (PangoLayoutRun *run)
  * specification for details.
  */
 void
-pango_layout_run_get_extents (PangoLayoutRun   *run,
-                              PangoLeadingTrim  trim,
-                              PangoRectangle   *ink_rect,
-                              PangoRectangle   *logical_rect)
+pango_run_get_extents (PangoRun         *run,
+                       PangoLeadingTrim  trim,
+                       PangoRectangle   *ink_rect,
+                       PangoRectangle   *logical_rect)
 {
-  PangoGlyphItem *glyph_item = run;
+  PangoGlyphItem *glyph_item = &run->glyph_item;
   ItemProperties properties;
   gboolean has_underline;
   gboolean has_overline;
diff --git a/pango/pango-layout-run.h b/pango/pango-run.h
similarity index 64%
rename from pango/pango-layout-run.h
rename to pango/pango-run.h
index 1f676405..1264ecb5 100644
--- a/pango/pango-layout-run.h
+++ b/pango/pango-run.h
@@ -23,17 +23,15 @@
 #include <pango/pango-types.h>
 #include <pango/pango-item.h>
 #include <pango/pango-glyph.h>
-#include <pango/pango-layout.h>
-
 
 PANGO_AVAILABLE_IN_ALL
-PangoItem *             pango_layout_run_get_item     (PangoLayoutRun   *run);
+PangoItem *             pango_run_get_item     (PangoRun         *run);
 
 PANGO_AVAILABLE_IN_ALL
-PangoGlyphString *      pango_layout_run_get_glyphs   (PangoLayoutRun   *run);
+PangoGlyphString *      pango_run_get_glyphs   (PangoRun         *run);
 
 PANGO_AVAILABLE_IN_ALL
-void                    pango_layout_run_get_extents  (PangoLayoutRun   *run,
-                                                       PangoLeadingTrim  trim,
-                                                       PangoRectangle   *ink_rect,
-                                                       PangoRectangle   *logical_rect);
+void                    pango_run_get_extents  (PangoRun         *run,
+                                                PangoLeadingTrim  trim,
+                                                PangoRectangle   *ink_rect,
+                                                PangoRectangle   *logical_rect);
diff --git a/pango/pango-types.h b/pango/pango-types.h
index 98846969..ff21144d 100644
--- a/pango/pango-types.h
+++ b/pango/pango-types.h
@@ -53,7 +53,10 @@ typedef struct _PangoLanguage PangoLanguage;
  */
 typedef guint32 PangoGlyph;
 
-
+typedef struct _PangoLines PangoLines;
+typedef struct _PangoRun PangoRun;
+typedef struct _PangoLine PangoLine;
+typedef struct _PangoLineIter PangoLineIter;
 
 /**
  * PANGO_SCALE:
@@ -243,31 +246,23 @@ void pango_extents_to_pixels (PangoRectangle *inclusive,
  * @PANGO_ALIGN_LEFT: Put all available space on the right
  * @PANGO_ALIGN_CENTER: Center the line within the available space
  * @PANGO_ALIGN_RIGHT: Put all available space on the left
+ * @PANGO_ALIGN_JUSTIFY: Justify the content to fill the available
+ *   space, unless the line ends the paragraph
+ * @PANGO_ALIGN_JUSTIFY_ALL: Justify the content to fill the available
+ *   space, even if the line ends the paragraph
  *
  * `PangoAlignment` describes how to align the lines of a `PangoLayout`
  * within the available space.
- *
- * If the `PangoLayout` is set to justify using [method@Pango.Layout.set_justify],
- * this only affects partial lines.
- *
- * See [method@Pango.Layout.set_auto_dir] for how text direction affects
- * the interpretation of `PangoAlignment` values.
  */
-typedef enum {
+typedef enum
+{
   PANGO_ALIGN_LEFT,
   PANGO_ALIGN_CENTER,
-  PANGO_ALIGN_RIGHT
+  PANGO_ALIGN_RIGHT,
+  PANGO_ALIGN_JUSTIFY,
+  PANGO_ALIGN_JUSTIFY_ALL,
 } PangoAlignment;
 
-typedef enum
-{
-  PANGO_ALIGNMENT_LEFT,
-  PANGO_ALIGNMENT_CENTER,
-  PANGO_ALIGNMENT_RIGHT,
-  PANGO_ALIGNMENT_JUSTIFY,
-  PANGO_ALIGNMENT_JUSTIFY_ALL,
-} PangoAlignmentMode;
-
 /**
  * PangoWrapMode:
  * @PANGO_WRAP_WORD: wrap lines at word boundaries.
diff --git a/pango/pango.h b/pango/pango.h
index 5727e768..5248ede0 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -44,7 +44,6 @@
 #include <pango/pango-item.h>
 #include <pango/pango-language.h>
 #include <pango/pango-layout.h>
-#include <pango/pango-layout-run.h>
 #include <pango/pango-line.h>
 #include <pango/pango-line-breaker.h>
 #include <pango/pango-line-iter.h>
@@ -52,8 +51,8 @@
 #include <pango/pango-matrix.h>
 #include <pango/pango-markup.h>
 #include <pango/pango-renderer.h>
+#include <pango/pango-run.h>
 #include <pango/pango-script.h>
-#include <pango/pango-simple-layout.h>
 #include <pango/pango-tabs.h>
 #include <pango/pango-types.h>
 #include <pango/pango-utils.h>
diff --git a/pango/pangocairo-context.c b/pango/pangocairo-context.c
index 0ea8332a..b1d6a03e 100644
--- a/pango/pangocairo-context.c
+++ b/pango/pangocairo-context.c
@@ -463,7 +463,7 @@ pango_cairo_create_context (cairo_t *cr)
  * and target surface of the Cairo context.
  *
  * This layout can then be used for text measurement with functions
- * like [method@Pango.Layout.get_size] or drawing with functions like
+ * like [method@Pango.Lines.get_size] or drawing with functions like
  * [func@show_layout]. If you change the transformation or target
  * surface for @cr, you need to call [func@update_layout].
  *
@@ -491,21 +491,6 @@ pango_cairo_create_layout (cairo_t *cr)
   return layout;
 }
 
-PangoSimpleLayout *
-pango_cairo_create_simple_layout (cairo_t *cr)
-{
-  PangoContext *context;
-  PangoSimpleLayout *layout;
-
-  g_return_val_if_fail (cr != NULL, NULL);
-
-  context = pango_cairo_create_context (cr);
-  layout = pango_simple_layout_new (context);
-  g_object_unref (context);
-
-  return layout;
-}
-
 /**
  * pango_cairo_update_layout:
  * @cr: a Cairo context
@@ -526,14 +511,3 @@ pango_cairo_update_layout (cairo_t     *cr,
 
   _pango_cairo_update_context (cr, pango_layout_get_context (layout));
 }
-
-void
-pango_cairo_update_simple_layout (cairo_t           *cr,
-                                  PangoSimpleLayout *layout)
-{
-  g_return_if_fail (cr != NULL);
-  g_return_if_fail (PANGO_IS_SIMPLE_LAYOUT (layout));
-
-  _pango_cairo_update_context (cr, pango_simple_layout_get_context (layout));
-}
-
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 50a72239..a9274a29 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -186,26 +186,29 @@ _pango_cairo_font_install (PangoFont *font,
   return TRUE;
 }
 
-
 static int
 max_glyph_width (PangoLayout *layout)
 {
+  PangoLines *lines;
   int max_width = 0;
-  GSList *l, *r;
+  GSList *r;
 
-  for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+  lines = pango_layout_get_lines (layout);
+  for (int i = 0; i < pango_lines_get_line_count (lines); i++)
     {
-      PangoLayoutLine *line = l->data;
-
-      for (r = line->runs; r; r = r->next)
-       {
-         PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
-         int i;
+      PangoLine *line = pango_lines_get_line (lines, i, NULL, NULL);
 
-         for (i = 0; i < glyphs->num_glyphs; i++)
-           if (glyphs->glyphs[i].geometry.width > max_width)
-             max_width = glyphs->glyphs[i].geometry.width;
-       }
+      for (r = pango_line_get_runs (line); r; r = r->next)
+        {
+          PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+          int i;
+
+          for (i = 0; i < glyphs->num_glyphs; i++)
+            {
+              if (glyphs->glyphs[i].geometry.width > max_width)
+                max_width = glyphs->glyphs[i].geometry.width;
+            }
+        }
     }
 
   return max_width;
@@ -320,7 +323,7 @@ _pango_cairo_font_get_metrics (PangoFont     *font,
           pango_font_description_free (desc);
 
           pango_layout_set_text (layout, sample_str, -1);
-          pango_layout_get_extents (layout, NULL, &extents);
+          pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &extents);
 
           sample_str_width = pango_utf8_strwidth (sample_str);
           g_assert (sample_str_width > 0);
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 6c6d8d85..d226b389 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -972,25 +972,6 @@ _pango_cairo_do_glyph_item (cairo_t          *cr,
   release_renderer (crenderer);
 }
 
-static void
-_pango_cairo_do_layout_line (cairo_t          *cr,
-                            PangoLayoutLine  *line,
-                            gboolean          do_path)
-{
-  PangoCairoRenderer *crenderer = acquire_renderer ();
-  PangoRenderer *renderer = (PangoRenderer *) crenderer;
-
-  crenderer->cr = cr;
-  crenderer->do_path = do_path;
-  save_current_point (crenderer);
-
-  pango_renderer_draw_layout_line (renderer, line, 0, 0);
-
-  restore_current_point (crenderer);
-
-  release_renderer (crenderer);
-}
-
 static void
 _pango_cairo_do_line (cairo_t   *cr,
                       PangoLine *line,
@@ -1041,7 +1022,7 @@ _pango_cairo_do_layout (cairo_t     *cr,
   crenderer->do_path = do_path;
   save_current_point (crenderer);
 
-  pango_renderer_draw_layout (renderer, layout, 0, 0);
+  pango_renderer_draw_lines (renderer, pango_layout_get_lines (layout), 0, 0);
 
   restore_current_point (crenderer);
 
@@ -1132,28 +1113,6 @@ pango_cairo_show_glyph_item (cairo_t          *cr,
   _pango_cairo_do_glyph_item (cr, text, glyph_item, FALSE);
 }
 
-/**
- * pango_cairo_show_layout_line:
- * @cr: a Cairo context
- * @line: a `PangoLayoutLine`
- *
- * Draws a `PangoLayoutLine` in the specified cairo context.
- *
- * The origin of the glyphs (the left edge of the line) will
- * be drawn at the current point of the cairo context.
- *
- * Since: 1.10
- */
-void
-pango_cairo_show_layout_line (cairo_t          *cr,
-                             PangoLayoutLine  *line)
-{
-  g_return_if_fail (cr != NULL);
-  g_return_if_fail (line != NULL);
-
-  _pango_cairo_do_layout_line (cr, line, FALSE);
-}
-
 /**
  * pango_cairo_show_line:
  * @cr: a Cairo context
@@ -1272,33 +1231,10 @@ pango_cairo_glyph_string_path (cairo_t          *cr,
   _pango_cairo_do_glyph_string (cr, font, glyphs, TRUE);
 }
 
-/**
- * pango_cairo_layout_line_path:
- * @cr: a Cairo context
- * @line: a `PangoLayoutLine`
- *
- * Adds the text in `PangoLayoutLine` to the current path in the
- * specified cairo context.
- *
- * The origin of the glyphs (the left edge of the line) will be
- * at the current point of the cairo context.
- *
- * Since: 1.10
- */
-void
-pango_cairo_layout_line_path (cairo_t          *cr,
-                             PangoLayoutLine  *line)
-{
-  g_return_if_fail (cr != NULL);
-  g_return_if_fail (line != NULL);
-
-  _pango_cairo_do_layout_line (cr, line, TRUE);
-}
-
 /**
  * pango_cairo_line_path:
  * @cr: a Cairo context
- * @line: a `PangoLayoutLine`
+ * @line: a `PangoLine`
  *
  * Adds the text in `PangoLine` to the current path in the
  * specified cairo context.
diff --git a/pango/pangocairo.h b/pango/pangocairo.h
index c996285d..b32cf465 100644
--- a/pango/pangocairo.h
+++ b/pango/pangocairo.h
@@ -165,11 +165,6 @@ PANGO_AVAILABLE_IN_1_10
 void         pango_cairo_update_layout (cairo_t     *cr,
                                        PangoLayout *layout);
 
-PANGO_AVAILABLE_IN_ALL
-PangoSimpleLayout *pango_cairo_create_simple_layout (cairo_t     *cr);
-PANGO_AVAILABLE_IN_ALL
-void         pango_cairo_update_simple_layout (cairo_t           *cr,
-                                               PangoSimpleLayout *layout);
 /*
  * Rendering
  */
@@ -181,9 +176,6 @@ PANGO_AVAILABLE_IN_1_22
 void pango_cairo_show_glyph_item   (cairo_t          *cr,
                                    const char       *text,
                                    PangoGlyphItem   *glyph_item);
-PANGO_AVAILABLE_IN_1_10
-void pango_cairo_show_layout_line  (cairo_t          *cr,
-                                   PangoLayoutLine  *line);
 PANGO_AVAILABLE_IN_ALL
 void pango_cairo_show_line         (cairo_t          *cr,
                                     PangoLine        *line);
@@ -210,17 +202,14 @@ void pango_cairo_glyph_string_path (cairo_t          *cr,
                                    PangoFont        *font,
                                    PangoGlyphString *glyphs);
 PANGO_AVAILABLE_IN_1_10
-void pango_cairo_layout_line_path  (cairo_t          *cr,
-                                   PangoLayoutLine  *line);
-PANGO_AVAILABLE_IN_1_10
 void pango_cairo_layout_path       (cairo_t          *cr,
                                    PangoLayout      *layout);
 PANGO_AVAILABLE_IN_ALL
-void pango_cairo_line_path  (cairo_t   *cr,
-                             PangoLine *line);
+void pango_cairo_line_path         (cairo_t          *cr,
+                                    PangoLine        *line);
 PANGO_AVAILABLE_IN_ALL
-void pango_cairo_lines_path  (cairo_t    *cr,
-                              PangoLines *lines);
+void pango_cairo_lines_path        (cairo_t          *cr,
+                                    PangoLines       *lines);
 
 PANGO_AVAILABLE_IN_1_14
 void pango_cairo_error_underline_path (cairo_t       *cr,
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index a5b20968..573768c8 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -417,22 +417,26 @@ pango_fc_font_create_base_metrics_for_context (PangoFcFont   *fcfont,
 static int
 max_glyph_width (PangoLayout *layout)
 {
+  PangoLines *lines;
   int max_width = 0;
-  GSList *l, *r;
+  GSList *r;
 
-  for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+  lines = pango_layout_get_lines (layout);
+  for (int i = 0; i < pango_lines_get_line_count (lines); i++)
     {
-      PangoLayoutLine *line = l->data;
+      PangoLine *line = pango_lines_get_line (lines, i, NULL, NULL);
 
-      for (r = line->runs; r; r = r->next)
-       {
-         PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
-         int i;
+      for (r = pango_line_get_runs (line); r; r = r->next)
+        {
+          PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+          int i;
 
-         for (i = 0; i < glyphs->num_glyphs; i++)
-           if (glyphs->glyphs[i].geometry.width > max_width)
-             max_width = glyphs->glyphs[i].geometry.width;
-       }
+          for (i = 0; i < glyphs->num_glyphs; i++)
+            {
+              if (glyphs->glyphs[i].geometry.width > max_width)
+                max_width = glyphs->glyphs[i].geometry.width;
+            }
+        }
     }
 
   return max_width;
@@ -474,8 +478,7 @@ pango_fc_font_get_metrics (PangoFont     *font,
       /* Note: we need to add info to the list before calling
        * into PangoLayout below, to prevent recursion
        */
-      fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang,
-                                                info);
+      fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang, info);
 
       info->sample_str = sample_str;
 
@@ -499,7 +502,7 @@ pango_fc_font_get_metrics (PangoFont     *font,
           pango_font_description_free (desc);
 
           pango_layout_set_text (layout, sample_str, -1);
-          pango_layout_get_extents (layout, NULL, &extents);
+          pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &extents);
 
           sample_str_width = pango_utf8_strwidth (sample_str);
           g_assert (sample_str_width > 0);
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index d26e9aa2..538d16ac 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -1036,7 +1036,7 @@ pango_win32_render_layout (HDC          hdc,
                           int          x,
                           int          y)
 {
-  PangoLayoutIter *iter;
+  PangoLineIter *iter;
 
   g_return_if_fail (hdc != NULL);
   g_return_if_fail (PANGO_IS_LAYOUT (layout));
diff --git a/pango/serializer.c b/pango/serializer.c
index f2bf5cc2..cfc9931d 100644
--- a/pango/serializer.c
+++ b/pango/serializer.c
@@ -22,13 +22,10 @@
 #include "config.h"
 
 #include <pango/pango-layout.h>
-#include <pango/pango-layout-private.h>
 #include <pango/pango-context-private.h>
 #include <pango/pango-enum-types.h>
 #include <pango/pango-font-private.h>
 #include <pango/pango-line-private.h>
-#include <pango/pango-lines.h>
-#include <pango/pango-simple-layout.h>
 #include <pango/pango-utils-internal.h>
 
 #include <hb-ot.h>
@@ -236,14 +233,14 @@ static const char *direction_names[] = {
   NULL
 };
 
-static const char *alignment_names[] = {
-  "left",
-  "center",
-  "right",
+static const char *wrap_names[] = {
+  "word",
+  "char",
+  "word-char",
   NULL
 };
 
-static const char *alignment_names2[] = {
+static const char *alignment_names[] = {
   "left",
   "center",
   "right",
@@ -252,13 +249,6 @@ static const char *alignment_names2[] = {
   NULL
 };
 
-static const char *wrap_names[] = {
-  "word",
-  "char",
-  "word-char",
-  NULL
-};
-
 static const char *ellipsize_names[] = {
   "none",
   "start",
@@ -639,7 +629,7 @@ add_font (GtkJsonPrinter *printer,
 static void
 add_run (GtkJsonPrinter *printer,
          const char     *text,
-         PangoLayoutRun *run)
+         PangoGlyphItem *run)
 {
   char *str;
   char buf[5] = { 0, };
@@ -713,136 +703,10 @@ add_run (GtkJsonPrinter *printer,
 #undef ANALYSIS_FLAGS
 
 static void
-add_line (GtkJsonPrinter  *printer,
-          PangoLayoutLine *line)
-{
-  gtk_json_printer_start_object (printer, NULL);
-
-  gtk_json_printer_add_integer (printer, "start-index", line->start_index);
-  gtk_json_printer_add_integer (printer, "length", line->length);
-  gtk_json_printer_add_boolean (printer, "paragraph-start", line->is_paragraph_start);
-  gtk_json_printer_add_string (printer, "direction", direction_names[line->resolved_dir]);
-
-  gtk_json_printer_start_array (printer, "runs");
-  for (GSList *l = line->runs; l; l = l->next)
-    {
-      PangoLayoutRun *run = l->data;
-      add_run (printer, line->layout->text, run);
-    }
-  gtk_json_printer_end (printer);
-
-  gtk_json_printer_end (printer);
-}
-
-static void
-add_output (GtkJsonPrinter *printer,
-            PangoLayout    *layout)
-{
-  int width, height;
-  const PangoLogAttr *log_attrs;
-  int n_attrs;
-
-  gtk_json_printer_start_object (printer, "output");
-
-  gtk_json_printer_add_boolean (printer, "is-wrapped", pango_layout_is_wrapped (layout));
-  gtk_json_printer_add_boolean (printer, "is-ellipsized", pango_layout_is_ellipsized (layout));
-  gtk_json_printer_add_integer (printer, "unknown-glyphs", pango_layout_get_unknown_glyphs_count (layout));
-
-  pango_layout_get_size (layout, &width, &height);
-  gtk_json_printer_add_integer (printer, "width", width);
-  gtk_json_printer_add_integer (printer, "height", height);
-
-  log_attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
-  add_log_attrs (printer, log_attrs, n_attrs);
-
-  gtk_json_printer_start_array (printer, "lines");
-  for (GSList *l = layout->lines; l; l = l->next)
-    {
-      PangoLayoutLine *line = l->data;
-
-      add_line (printer, line);
-    }
-  gtk_json_printer_end (printer);
-
-  gtk_json_printer_end (printer);
-}
-
-static void
-layout_to_json (GtkJsonPrinter            *printer,
-                PangoLayout               *layout,
-                PangoLayoutSerializeFlags  flags)
-{
-  const char *str;
-
-  gtk_json_printer_start_object (printer, NULL);
-
-  if (flags & PANGO_LAYOUT_SERIALIZE_CONTEXT)
-    add_context (printer, layout->context);
-
-  str = (const char *) g_object_get_data (G_OBJECT (layout), "comment");
-  if (str)
-    gtk_json_printer_add_string (printer, "comment", str);
-
-  gtk_json_printer_add_string (printer, "text", layout->text);
-
-  add_attr_list (printer, layout->attrs);
-
-  if (layout->font_desc)
-    {
-      char *str = pango_font_description_to_string (layout->font_desc);
-      gtk_json_printer_add_string (printer, "font", str);
-      g_free (str);
-    }
-
-  add_tab_array (printer, layout->tabs);
-
-  if (layout->justify)
-    gtk_json_printer_add_boolean (printer, "justify", TRUE);
-
-  if (layout->justify_last_line)
-    gtk_json_printer_add_boolean (printer, "justify-last-line", TRUE);
-
-  if (layout->single_paragraph)
-    gtk_json_printer_add_boolean (printer, "single-paragraph", TRUE);
-
-  if (!layout->auto_dir)
-    gtk_json_printer_add_boolean (printer, "auto-dir", FALSE);
-
-  if (layout->alignment != PANGO_ALIGN_LEFT)
-    gtk_json_printer_add_string (printer, "alignment", alignment_names[layout->alignment]);
-
-  if (layout->wrap != PANGO_WRAP_WORD)
-    gtk_json_printer_add_string (printer, "wrap", wrap_names[layout->wrap]);
-
-  if (layout->ellipsize != PANGO_ELLIPSIZE_NONE)
-    gtk_json_printer_add_string (printer, "ellipsize", ellipsize_names[layout->ellipsize]);
-
-  if (layout->width != -1)
-    gtk_json_printer_add_integer (printer, "width", layout->width);
-
-  if (layout->height != -1)
-    gtk_json_printer_add_integer (printer, "height", layout->height);
-
-  if (layout->indent != 0)
-    gtk_json_printer_add_integer (printer, "indent", layout->indent);
-
-  if (layout->spacing != 0)
-    gtk_json_printer_add_integer (printer, "spacing", layout->spacing);
-
-  if (layout->line_spacing != 0.)
-    gtk_json_printer_add_number (printer, "line-spacing", layout->line_spacing);
-
-  if (flags & PANGO_LAYOUT_SERIALIZE_OUTPUT)
-    add_output (printer, layout);
-
-  gtk_json_printer_end (printer);
-}
-
-static void
-line_to_json (GtkJsonPrinter *printer,
-              PangoLine      *line,
-              int             x,
-              int             y)
+line_to_json (GtkJsonPrinter  *printer,
+              PangoLine       *line,
+              int              x,
+              int              y)
 {
   gtk_json_printer_start_object (printer, NULL);
 
@@ -869,7 +733,7 @@ line_to_json (GtkJsonPrinter *printer,
   gtk_json_printer_start_array (printer, "runs");
   for (GSList *l = line->runs; l; l = l->next)
     {
-      PangoLayoutRun *run = l->data;
+      PangoGlyphItem *run = l->data;
       add_run (printer, line->data->text, run);
     }
   gtk_json_printer_end (printer);
@@ -887,6 +751,10 @@ lines_to_json (GtkJsonPrinter *printer,
 
   gtk_json_printer_start_object (printer, "output");
 
+  gtk_json_printer_add_boolean (printer, "wrapped", pango_lines_is_wrapped (lines));
+  gtk_json_printer_add_boolean (printer, "ellipsized", pango_lines_is_ellipsized (lines));
+  gtk_json_printer_add_boolean (printer, "hypenated", pango_lines_is_hyphenated (lines));
+  gtk_json_printer_add_integer (printer, "unknown-glyphs", pango_lines_get_unknown_glyphs_count (lines));
   pango_lines_get_size (lines, &width, &height);
   gtk_json_printer_add_integer (printer, "width", width);
   gtk_json_printer_add_integer (printer, "height", height);
@@ -907,68 +775,67 @@ lines_to_json (GtkJsonPrinter *printer,
 }
 
 static void
-simple_layout_to_json (GtkJsonPrinter                  *printer,
-                       PangoSimpleLayout               *layout,
-                       PangoSimpleLayoutSerializeFlags  flags)
+layout_to_json (GtkJsonPrinter            *printer,
+                PangoLayout               *layout,
+                PangoLayoutSerializeFlags  flags)
 {
   const char *str;
 
   gtk_json_printer_start_object (printer, NULL);
 
-  if (flags & PANGO_SIMPLE_LAYOUT_SERIALIZE_CONTEXT)
-    add_context (printer, pango_simple_layout_get_context (layout));
+  if (flags & PANGO_LAYOUT_SERIALIZE_CONTEXT)
+    add_context (printer, pango_layout_get_context (layout));
 
   str = (const char *) g_object_get_data (G_OBJECT (layout), "comment");
   if (str)
     gtk_json_printer_add_string (printer, "comment", str);
 
-  gtk_json_printer_add_string (printer, "text", pango_simple_layout_get_text (layout));
+  gtk_json_printer_add_string (printer, "text", pango_layout_get_text (layout));
 
-  add_attr_list (printer, pango_simple_layout_get_attributes (layout));
+  add_attr_list (printer, pango_layout_get_attributes (layout));
 
-  if (pango_simple_layout_get_font_description (layout))
+  if (pango_layout_get_font_description (layout))
     {
-      char *str = pango_font_description_to_string (pango_simple_layout_get_font_description (layout));
+      char *str = pango_font_description_to_string (pango_layout_get_font_description (layout));
       gtk_json_printer_add_string (printer, "font", str);
       g_free (str);
     }
 
-  if (pango_simple_layout_get_tabs (layout))
-    add_tab_array (printer, pango_simple_layout_get_tabs (layout));
+  add_tab_array (printer, pango_layout_get_tabs (layout));
 
-  if (!pango_simple_layout_get_auto_dir (layout))
+  if (!pango_layout_get_auto_dir (layout))
     gtk_json_printer_add_boolean (printer, "auto-dir", FALSE);
 
-  if (pango_simple_layout_get_alignment (layout) != PANGO_ALIGNMENT_LEFT)
-    gtk_json_printer_add_string (printer, "alignment", alignment_names2[pango_simple_layout_get_alignment 
(layout)]);
+  if (pango_layout_get_alignment (layout) != PANGO_ALIGN_LEFT)
+    gtk_json_printer_add_string (printer, "alignment", alignment_names[pango_layout_get_alignment (layout)]);
 
-  if (pango_simple_layout_get_wrap (layout) != PANGO_WRAP_WORD)
-    gtk_json_printer_add_string (printer, "wrap", wrap_names[pango_simple_layout_get_wrap (layout)]);
+  if (pango_layout_get_wrap (layout) != PANGO_WRAP_WORD)
+    gtk_json_printer_add_string (printer, "wrap", wrap_names[pango_layout_get_wrap (layout)]);
 
-  if (pango_simple_layout_get_ellipsize (layout) != PANGO_ELLIPSIZE_NONE)
-    gtk_json_printer_add_string (printer, "ellipsize", ellipsize_names[pango_simple_layout_get_ellipsize 
(layout)]);
+  if (pango_layout_get_ellipsize (layout) != PANGO_ELLIPSIZE_NONE)
+    gtk_json_printer_add_string (printer, "ellipsize", ellipsize_names[pango_layout_get_ellipsize (layout)]);
 
-  if (pango_simple_layout_get_width (layout) != -1)
-    gtk_json_printer_add_integer (printer, "width", pango_simple_layout_get_width (layout));
+  if (pango_layout_get_width (layout) != -1)
+    gtk_json_printer_add_integer (printer, "width", pango_layout_get_width (layout));
 
-  if (pango_simple_layout_get_height (layout) != -1)
-    gtk_json_printer_add_integer (printer, "height", pango_simple_layout_get_height (layout));
+  if (pango_layout_get_height (layout) != -1)
+    gtk_json_printer_add_integer (printer, "height", pango_layout_get_height (layout));
 
-  if (pango_simple_layout_get_indent (layout) != 0)
-    gtk_json_printer_add_integer (printer, "indent", pango_simple_layout_get_indent (layout));
+  if (pango_layout_get_indent (layout) != 0)
+    gtk_json_printer_add_integer (printer, "indent", pango_layout_get_indent (layout));
 
-  if (pango_simple_layout_get_line_spacing (layout) != 0.)
-    gtk_json_printer_add_number (printer, "line-spacing", pango_simple_layout_get_line_spacing (layout));
+  if (pango_layout_get_line_spacing (layout) != 0.)
+    gtk_json_printer_add_number (printer, "line-spacing", pango_layout_get_line_spacing (layout));
 
   if (flags & PANGO_LAYOUT_SERIALIZE_OUTPUT)
     {
       const PangoLogAttr *log_attrs;
       int n_attrs;
 
-      log_attrs = pango_simple_layout_get_log_attrs (layout, &n_attrs);
+      log_attrs = pango_layout_get_log_attrs (layout, &n_attrs);
       add_log_attrs (printer, log_attrs, n_attrs);
 
-      lines_to_json (printer, pango_simple_layout_get_lines (layout));
+      lines_to_json (printer, pango_layout_get_lines (layout));
     }
 
   gtk_json_printer_end (printer);
@@ -1521,9 +1388,6 @@ enum {
   LAYOUT_ATTRIBUTES,
   LAYOUT_FONT,
   LAYOUT_TABS,
-  LAYOUT_JUSTIFY,
-  LAYOUT_JUSTIFY_LAST_LINE,
-  LAYOUT_SINGLE_PARAGRAPH,
   LAYOUT_AUTO_DIR,
   LAYOUT_ALIGNMENT,
   LAYOUT_WRAP,
@@ -1531,9 +1395,8 @@ enum {
   LAYOUT_WIDTH,
   LAYOUT_HEIGHT,
   LAYOUT_INDENT,
-  LAYOUT_SPACING,
   LAYOUT_LINE_SPACING,
-  LAYOUT_OUTPUT
+  LAYOUT_LINES
 };
 
 static const char *layout_members[] = {
@@ -1543,9 +1406,6 @@ static const char *layout_members[] = {
   "attributes",
   "font",
   "tabs",
-  "justify",
-  "justify-last-line",
-  "single-paragraph",
   "auto-dir",
   "alignment",
   "wrap",
@@ -1553,9 +1413,8 @@ static const char *layout_members[] = {
   "width",
   "height",
   "indent",
-  "spacing",
   "line-spacing",
-  "output",
+  "lines",
   NULL
 };
 
@@ -1605,6 +1464,14 @@ json_parser_fill_layout (GtkJsonParser               *parser,
           }
           break;
 
+        case LAYOUT_AUTO_DIR:
+          pango_layout_set_auto_dir (layout, gtk_json_parser_get_boolean (parser));
+          break;
+
+        case LAYOUT_LINE_SPACING:
+          pango_layout_set_line_spacing (layout, gtk_json_parser_get_number (parser));
+          break;
+
         case LAYOUT_TABS:
           {
             PangoTabArray *tabs = pango_tab_array_new (0, FALSE);
@@ -1614,22 +1481,6 @@ json_parser_fill_layout (GtkJsonParser               *parser,
           }
           break;
 
-        case LAYOUT_JUSTIFY:
-          pango_layout_set_justify (layout, gtk_json_parser_get_boolean (parser));
-          break;
-
-        case LAYOUT_JUSTIFY_LAST_LINE:
-          pango_layout_set_justify_last_line (layout, gtk_json_parser_get_boolean (parser));
-          break;
-
-        case LAYOUT_SINGLE_PARAGRAPH:
-          pango_layout_set_single_paragraph_mode (layout, gtk_json_parser_get_boolean (parser));
-          break;
-
-        case LAYOUT_AUTO_DIR:
-          pango_layout_set_auto_dir (layout, gtk_json_parser_get_boolean (parser));
-          break;
-
         case LAYOUT_ALIGNMENT:
           pango_layout_set_alignment (layout, (PangoAlignment) parser_select_string (parser, 
alignment_names));
           break;
@@ -1654,151 +1505,7 @@ json_parser_fill_layout (GtkJsonParser               *parser,
           pango_layout_set_indent (layout, (int) gtk_json_parser_get_number (parser));
           break;
 
-        case LAYOUT_SPACING:
-          pango_layout_set_spacing (layout, (int) gtk_json_parser_get_number (parser));
-          break;
-
-        case LAYOUT_LINE_SPACING:
-          pango_layout_set_line_spacing (layout, gtk_json_parser_get_number (parser));
-          break;
-
-        case LAYOUT_OUTPUT:
-          break;
-
-        default:
-          break;
-        }
-    }
-  while (gtk_json_parser_next (parser));
-
-  gtk_json_parser_end (parser);
-}
-
-enum {
-  SIMPLE_LAYOUT_CONTEXT,
-  SIMPLE_LAYOUT_COMMENT,
-  SIMPLE_LAYOUT_TEXT,
-  SIMPLE_LAYOUT_ATTRIBUTES,
-  SIMPLE_LAYOUT_FONT,
-  SIMPLE_LAYOUT_TABS,
-  SIMPLE_LAYOUT_AUTO_DIR,
-  SIMPLE_LAYOUT_ALIGNMENT,
-  SIMPLE_LAYOUT_WRAP,
-  SIMPLE_LAYOUT_ELLIPSIZE,
-  SIMPLE_LAYOUT_WIDTH,
-  SIMPLE_LAYOUT_HEIGHT,
-  SIMPLE_LAYOUT_INDENT,
-  SIMPLE_LAYOUT_LINE_SPACING,
-  SIMPLE_LAYOUT_LINES
-};
-
-static const char *simple_layout_members[] = {
-  "context",
-  "comment",
-  "text",
-  "attributes",
-  "font",
-  "tabs",
-  "auto-dir",
-  "alignment",
-  "wrap",
-  "ellipsize",
-  "width",
-  "height",
-  "indent",
-  "line-spacing",
-  "lines",
-  NULL
-};
-
-static void
-json_parser_fill_simple_layout (GtkJsonParser                     *parser,
-                                PangoSimpleLayout                 *layout,
-                                PangoSimpleLayoutDeserializeFlags  flags)
-{
-  gtk_json_parser_start_object (parser);
-
-  do
-    {
-      char *str;
-
-      switch (gtk_json_parser_select_member (parser, simple_layout_members))
-        {
-        case SIMPLE_LAYOUT_CONTEXT:
-          if (flags & PANGO_LAYOUT_DESERIALIZE_CONTEXT)
-            json_parser_fill_context (parser, pango_simple_layout_get_context (layout));
-          break;
-
-        case SIMPLE_LAYOUT_COMMENT:
-          str = gtk_json_parser_get_string (parser);
-          g_object_set_data_full (G_OBJECT (layout), "comment", str, g_free);
-          break;
-
-        case SIMPLE_LAYOUT_TEXT:
-          str = gtk_json_parser_get_string (parser);
-          pango_simple_layout_set_text (layout, str, -1);
-          g_free (str);
-          break;
-
-        case SIMPLE_LAYOUT_ATTRIBUTES:
-          {
-            PangoAttrList *attributes = pango_attr_list_new ();
-            json_parser_fill_attr_list (parser, attributes);
-            pango_simple_layout_set_attributes (layout, attributes);
-            pango_attr_list_unref (attributes);
-          }
-          break;
-
-        case SIMPLE_LAYOUT_FONT:
-          {
-            PangoFontDescription *desc = parser_get_font_description (parser);;
-            pango_simple_layout_set_font_description (layout, desc);
-            pango_font_description_free (desc);
-          }
-          break;
-
-        case SIMPLE_LAYOUT_AUTO_DIR:
-          pango_simple_layout_set_auto_dir (layout, gtk_json_parser_get_boolean (parser));
-          break;
-
-        case SIMPLE_LAYOUT_LINE_SPACING:
-          pango_simple_layout_set_line_spacing (layout, gtk_json_parser_get_number (parser));
-          break;
-
-        case SIMPLE_LAYOUT_TABS:
-          {
-            PangoTabArray *tabs = pango_tab_array_new (0, FALSE);
-            json_parser_fill_tab_array (parser, tabs);
-            pango_simple_layout_set_tabs (layout, tabs);
-            pango_tab_array_free (tabs);
-          }
-          break;
-
-        case SIMPLE_LAYOUT_ALIGNMENT:
-          pango_simple_layout_set_alignment (layout, (PangoAlignment) parser_select_string (parser, 
alignment_names2));
-          break;
-
-        case SIMPLE_LAYOUT_WRAP:
-          pango_simple_layout_set_wrap (layout, (PangoWrapMode) parser_select_string (parser, wrap_names));
-          break;
-
-        case SIMPLE_LAYOUT_ELLIPSIZE:
-          pango_simple_layout_set_ellipsize (layout, (PangoEllipsizeMode) parser_select_string (parser, 
ellipsize_names));
-          break;
-
-        case SIMPLE_LAYOUT_WIDTH:
-          pango_simple_layout_set_width (layout, (int) gtk_json_parser_get_number (parser));
-          break;
-
-        case SIMPLE_LAYOUT_HEIGHT:
-          pango_simple_layout_set_height (layout, (int) gtk_json_parser_get_number (parser));
-          break;
-
-        case SIMPLE_LAYOUT_INDENT:
-          pango_simple_layout_set_indent (layout, (int) gtk_json_parser_get_number (parser));
-          break;
-
-        case SIMPLE_LAYOUT_LINES:
+        case LAYOUT_LINES:
           break;
 
         default:
@@ -1873,8 +1580,6 @@ json_parser_load_font (GtkJsonParser  *parser,
  * The format is not meant as a permanent storage format.
  *
  * Returns: a `GBytes` containing the serialized form of @layout
- *
- * Since: 1.50
  */
 GBytes *
 pango_layout_serialize (PangoLayout               *layout,
@@ -1905,9 +1610,6 @@ pango_layout_serialize (PangoLayout               *layout,
 /**
  * pango_layout_write_to_file:
  * @layout: a `PangoLayout`
- * @flags: `PangoLayoutSerializeFlags`
- * @filename: (type filename): the file to save it to
- * @error: Return location for a potential error
  *
  * A convenience method to serialize a layout to a file.
  *
@@ -1920,27 +1622,24 @@ pango_layout_serialize (PangoLayout               *layout,
  * a layout to a file for later inspection.
  *
  * Returns: %TRUE if saving was successful
- *
- * Since: 1.50
  */
 gboolean
-pango_layout_write_to_file (PangoLayout                *layout,
-                            PangoLayoutSerializeFlags   flags,
-                            const char                 *filename,
-                            GError                    **error)
+pango_layout_write_to_file (PangoLayout *layout,
+                            const char  *filename)
 {
   GBytes *bytes;
   gboolean result;
 
   g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
   g_return_val_if_fail (filename != NULL, FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  bytes = pango_layout_serialize (layout, flags);
+  bytes = pango_layout_serialize (layout, PANGO_LAYOUT_SERIALIZE_CONTEXT |
+                                          PANGO_LAYOUT_SERIALIZE_OUTPUT);
+
   result = g_file_set_contents (filename,
                                 g_bytes_get_data (bytes, NULL),
                                 g_bytes_get_size (bytes),
-                                error);
+                                NULL);
   g_bytes_unref (bytes);
 
   return result;
@@ -1962,8 +1661,6 @@ pango_layout_write_to_file (PangoLayout                *layout,
  * result of serializing the layout again.
  *
  * Returns: (nullable) (transfer full): a new `PangoLayout`
- *
- * Since: 1.50
  */
 PangoLayout *
 pango_layout_deserialize (PangoContext                 *context,
@@ -2085,147 +1782,6 @@ pango_font_deserialize (PangoContext  *context,
   return font;
 }
 
-/**
- * pango_simple_layout_serialize:
- * @layout: a `PangoSimpleLayout`
- * @flags: `PangoSipleLayoutSerializeFlags`
- *
- * Serializes the @layout for later deserialization via [func@Pango.SimpleLayout.deserialize].
- *
- * There are no guarantees about the format of the output across different
- * versions of Pango and [func@Pango.SimpleLayout.deserialize] will reject data
- * that it cannot parse.
- *
- * The intended use of this function is testing, benchmarking and debugging.
- * The format is not meant as a permanent storage format.
- *
- * Returns: a `GBytes` containing the serialized form of @layout
- */
-GBytes *
-pango_simple_layout_serialize (PangoSimpleLayout               *layout,
-                               PangoSimpleLayoutSerializeFlags  flags)
-{
-  GString *str;
-  GtkJsonPrinter *printer;
-  char *data;
-  gsize size;
-
-  g_return_val_if_fail (PANGO_IS_SIMPLE_LAYOUT (layout), NULL);
-
-  str = g_string_new ("");
-
-  printer = gtk_json_printer_new (gstring_write, str, NULL);
-  gtk_json_printer_set_flags (printer, GTK_JSON_PRINTER_PRETTY);
-  simple_layout_to_json (printer, layout, flags);
-  gtk_json_printer_free (printer);
-
-  g_string_append_c (str, '\n');
-
-  size = str->len;
-  data = g_string_free (str, FALSE);
-
-  return g_bytes_new_take (data, size);
-}
-
-/**
- * pango_simple_layout_write_to_file:
- * @layout: a `PangoLayout`
- *
- * A convenience method to serialize a layout to a file.
- *
- * It is equivalent to calling [method@Pango.SimpleLayout.serialize]
- * followed by [func@GLib.file_set_contents].
- *
- * See those two functions for details on the arguments.
- *
- * It is mostly intended for use inside a debugger to quickly dump
- * a layout to a file for later inspection.
- *
- * Returns: %TRUE if saving was successful
- */
-gboolean
-pango_simple_layout_write_to_file (PangoSimpleLayout *layout,
-                                   const char        *filename)
-{
-  GBytes *bytes;
-  gboolean result;
-
-  g_return_val_if_fail (PANGO_IS_SIMPLE_LAYOUT (layout), FALSE);
-  g_return_val_if_fail (filename != NULL, FALSE);
-
-  bytes = pango_simple_layout_serialize (layout, PANGO_SIMPLE_LAYOUT_SERIALIZE_CONTEXT |
-                                                 PANGO_SIMPLE_LAYOUT_SERIALIZE_OUTPUT);
-
-  result = g_file_set_contents (filename,
-                                g_bytes_get_data (bytes, NULL),
-                                g_bytes_get_size (bytes),
-                                NULL);
-  g_bytes_unref (bytes);
-
-  return result;
-}
-
-/**
- * pango_simple_layout_deserialize:
- * @context: a `PangoContext`
- * @flags: `PangoSimpleLayoutDeserializeFlags`
- * @bytes: the bytes containing the data
- * @error: return location for an error
- *
- * Loads data previously created via [method@Pango.SimpleLayout.serialize].
- *
- * For a discussion of the supported format, see that function.
- *
- * Note: to verify that the returned layout is identical to
- * the one that was serialized, you can compare @bytes to the
- * result of serializing the layout again.
- *
- * Returns: (nullable) (transfer full): a new `PangoSimpleLayout`
- */
-PangoSimpleLayout *
-pango_simple_layout_deserialize (PangoContext                       *context,
-                                 GBytes                             *bytes,
-                                 PangoSimpleLayoutDeserializeFlags   flags,
-                                 GError                            **error)
-{
-  PangoSimpleLayout *layout;
-  GtkJsonParser *parser;
-  const GError *parser_error;
-
-  g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
-
-  layout = pango_simple_layout_new (context);
-
-  parser = gtk_json_parser_new_for_bytes (bytes);
-  json_parser_fill_simple_layout (parser, layout, flags);
-
-  parser_error = gtk_json_parser_get_error (parser);
-
-  if (parser_error)
-    {
-      gsize start, end;
-      int code;
-
-      gtk_json_parser_get_error_offset (parser, &start, &end);
-
-      if (g_error_matches (parser_error, GTK_JSON_ERROR, GTK_JSON_ERROR_VALUE))
-        code = PANGO_LAYOUT_DESERIALIZE_INVALID_VALUE;
-      else if (g_error_matches (parser_error, GTK_JSON_ERROR, GTK_JSON_ERROR_SCHEMA))
-        code = PANGO_LAYOUT_DESERIALIZE_MISSING_VALUE;
-      else
-        code = PANGO_LAYOUT_DESERIALIZE_INVALID;
-
-      g_set_error (error, PANGO_LAYOUT_DESERIALIZE_ERROR, code,
-                   "%ld:%ld: %s", start, end, parser_error->message);
-
-      g_clear_object (&layout);
-    }
-
-  gtk_json_parser_free (parser);
-
-  return layout;
-}
-
 /* }}} */
 
 /* vim:set foldmethod=marker expandtab: */
diff --git a/tests/test-bidi.c b/tests/test-bidi.c
index edd597b7..aeae7c9d 100644
--- a/tests/test-bidi.c
+++ b/tests/test-bidi.c
@@ -73,7 +73,7 @@ test_bidi_embedding_levels (void)
     }
 }
 
-/* Some basic tests for pango_simple_layout_move_cursor inside
+/* Some basic tests for pango_layout_move_cursor inside
  * a single PangoLine:
  * - check that we actually move the cursor in the right direction
  * - check that we get through the line with at most n steps
@@ -89,10 +89,10 @@ test_move_cursor_line (void)
     "aאב12b",
     "pa­ra­graph", // soft hyphens
   };
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   gboolean fail = FALSE;
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
 
   for (int i = 0; i < G_N_ELEMENTS (tests); i++)
     {
@@ -123,15 +123,15 @@ test_move_cursor_line (void)
       int j;
       const char *p;
 
-      pango_simple_layout_set_text (layout, tests[i], -1);
+      pango_layout_set_text (layout, tests[i], -1);
 
-      text = pango_simple_layout_get_text (layout);
-      lines = pango_simple_layout_get_lines (layout);
+      text = pango_layout_get_text (layout);
+      lines = pango_layout_get_lines (layout);
       line = pango_lines_get_line (lines, 0, NULL, NULL);
 
       n_chars = g_utf8_strlen (text, -1);
 
-      attrs = pango_simple_layout_get_log_attrs (layout, &n_attrs);
+      attrs = pango_layout_get_log_attrs (layout, &n_attrs);
       strong_cursor = g_new (int, n_attrs);
       weak_cursor = g_new (int, n_attrs);
       met_cursor = g_new (gboolean, n_attrs);
@@ -270,7 +270,7 @@ test_move_cursor_para (void)
     { "long word", 40 },
     { "זוהי השורה הראשונה" "\n" "זוהי השורה השנייה" "\n" "זוהי השורה השלישית" , 200 },
   };
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle pos, old_pos;
   int index;
   int trailing;
@@ -281,19 +281,19 @@ test_move_cursor_para (void)
   PangoLineIter *iter;
   PangoLine *new_line;
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
 
   for (int i = 0; i < G_N_ELEMENTS (tests); i++)
     {
-      pango_simple_layout_set_text (layout, tests[i].text, -1);
-      text = pango_simple_layout_get_text (layout);
+      pango_layout_set_text (layout, tests[i].text, -1);
+      text = pango_layout_get_text (layout);
       if (tests[i].width > 0)
-        pango_simple_layout_set_width (layout, tests[i].width * PANGO_SCALE);
+        pango_layout_set_width (layout, tests[i].width * PANGO_SCALE);
       else
-        pango_simple_layout_set_width (layout, -1);
+        pango_layout_set_width (layout, -1);
 
       index = 0;
-      lines = pango_simple_layout_get_lines (layout);
+      lines = pango_layout_get_lines (layout);
       pango_lines_get_cursor_pos (lines, NULL, index, &pos, NULL);
 
       while (index < G_MAXINT)
diff --git a/tests/test-break.c b/tests/test-break.c
index 570ba1a5..d9039fc0 100644
--- a/tests/test-break.c
+++ b/tests/test-break.c
@@ -52,7 +52,7 @@ test_file (const gchar *filename, GString *string)
   char *test;
   char *text;
   PangoAttrList *attributes;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
 
   g_file_get_contents (filename, &contents, &length, &error);
   g_assert_no_error (error);
@@ -69,9 +69,9 @@ test_file (const gchar *filename, GString *string)
   pango_parse_markup (test, -1, 0, &attributes, &text, NULL, &error);
   g_assert_no_error (error);
 
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, text, length);
-  pango_simple_layout_set_attributes (layout, attributes);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, text, length);
+  pango_layout_set_attributes (layout, attributes);
 
 #if 0
   if (pango_layout_get_unknown_glyphs_count (layout) > 0)
@@ -90,7 +90,7 @@ test_file (const gchar *filename, GString *string)
     }
 #endif
 
-  attrs = pango_simple_layout_get_log_attrs (layout, &len);
+  attrs = pango_layout_get_log_attrs (layout, &len);
 
   if (!pango_validate_log_attrs (text, length, attrs, len, &error))
     {
diff --git a/tests/test-ellipsize.c b/tests/test-ellipsize.c
index 3246f311..f8512a09 100644
--- a/tests/test-ellipsize.c
+++ b/tests/test-ellipsize.c
@@ -31,26 +31,26 @@ static PangoContext *context;
 static void
 test_ellipsize_height (void)
 {
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   int height1, height2;
   PangoFontDescription *desc;
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
 
   desc = pango_font_description_from_string ("Fixed 7");
   //pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);
 
-  pango_simple_layout_set_text (layout, "some text that should be ellipsized", -1);
-  g_assert_cmpint (pango_lines_get_line_count (pango_simple_layout_get_lines (layout)), ==, 1);
-  pango_lines_get_size (pango_simple_layout_get_lines (layout), NULL, &height1);
+  pango_layout_set_text (layout, "some text that should be ellipsized", -1);
+  g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1);
+  pango_lines_get_size (pango_layout_get_lines (layout), NULL, &height1);
 
-  pango_simple_layout_set_width (layout, 100 * PANGO_SCALE);
-  pango_simple_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+  pango_layout_set_width (layout, 100 * PANGO_SCALE);
+  pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
 
-  g_assert_cmpint (pango_lines_get_line_count (pango_simple_layout_get_lines (layout)), ==, 1);
-  g_assert_true (pango_lines_is_ellipsized (pango_simple_layout_get_lines (layout)));
-  pango_lines_get_size (pango_simple_layout_get_lines (layout), NULL, &height2);
+  g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1);
+  g_assert_true (pango_lines_is_ellipsized (pango_layout_get_lines (layout)));
+  pango_lines_get_size (pango_layout_get_lines (layout), NULL, &height2);
 
   g_assert_cmpint (height1, ==, height2);
 
@@ -62,18 +62,18 @@ test_ellipsize_height (void)
 static void
 test_ellipsize_crash (void)
 {
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
 
-  pango_simple_layout_set_text (layout, "some text that should be ellipsized", -1);
-  g_assert_cmpint (pango_lines_get_line_count (pango_simple_layout_get_lines (layout)), ==, 1);
+  pango_layout_set_text (layout, "some text that should be ellipsized", -1);
+  g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1);
 
-  pango_simple_layout_set_width (layout, 100 * PANGO_SCALE);
-  pango_simple_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+  pango_layout_set_width (layout, 100 * PANGO_SCALE);
+  pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
 
-  g_assert_cmpint (pango_lines_get_line_count (pango_simple_layout_get_lines (layout)), ==, 1);
-  g_assert_true (pango_lines_is_ellipsized (pango_simple_layout_get_lines (layout)));
+  g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1);
+  g_assert_true (pango_lines_is_ellipsized (pango_layout_get_lines (layout)));
 
   g_object_unref (layout);
 }
@@ -84,21 +84,21 @@ test_ellipsize_crash (void)
 static void
 test_ellipsize_fully (void)
 {
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle ink, logical;
   PangoRectangle ink2, logical2;
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
 
-  pango_simple_layout_set_text (layout, "…", -1);
-  pango_lines_get_extents (pango_simple_layout_get_lines (layout), &ink, &logical);
+  pango_layout_set_text (layout, "…", -1);
+  pango_lines_get_extents (pango_layout_get_lines (layout), &ink, &logical);
 
-  pango_simple_layout_set_text (layout, "ellipsized", -1);
+  pango_layout_set_text (layout, "ellipsized", -1);
 
-  pango_simple_layout_set_width (layout, 10 * PANGO_SCALE);
-  pango_simple_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+  pango_layout_set_width (layout, 10 * PANGO_SCALE);
+  pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
 
-  pango_lines_get_extents (pango_simple_layout_get_lines (layout), &ink2, &logical2);
+  pango_lines_get_extents (pango_layout_get_lines (layout), &ink2, &logical2);
 
   g_assert_cmpint (ink.width, ==, ink2.width);
   g_assert_cmpint (logical.width, ==, logical2.width);
diff --git a/tests/test-layout.c b/tests/test-layout.c
index fab6501f..f440952b 100644
--- a/tests/test-layout.c
+++ b/tests/test-layout.c
@@ -30,7 +30,6 @@
 #include "config.h"
 #include <pango/pangocairo.h>
 #include <pango/pangocairo-fc.h>
-#include <pango/pangofc-fontmap.h>
 #include "test-common.h"
 
 
@@ -45,7 +44,7 @@ test_layout (gconstpointer d)
   gsize length;
   GBytes *orig;
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
 
   if (!PANGO_FC_IS_FONT_MAP (pango_cairo_font_map_get_default ()))
     {
@@ -69,11 +68,11 @@ test_layout (gconstpointer d)
   orig = g_bytes_new_take (contents, length);
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_deserialize (context, orig, PANGO_SIMPLE_LAYOUT_DESERIALIZE_CONTEXT, &error);
+  layout = pango_layout_deserialize (context, orig, PANGO_LAYOUT_DESERIALIZE_CONTEXT, &error);
   g_assert_no_error (error);
 
-  bytes = pango_simple_layout_serialize (layout, PANGO_SIMPLE_LAYOUT_SERIALIZE_CONTEXT |
-                                                 PANGO_SIMPLE_LAYOUT_SERIALIZE_OUTPUT);
+  bytes = pango_layout_serialize (layout, PANGO_LAYOUT_SERIALIZE_CONTEXT |
+                                                 PANGO_LAYOUT_SERIALIZE_OUTPUT);
 
   g_object_unref (layout);
   g_object_unref (context);
@@ -176,17 +175,17 @@ main (int argc, char *argv[])
       GBytes *orig;
       GBytes *bytes;
       PangoContext *context;
-      PangoSimpleLayout *layout;
+      PangoLayout *layout;
 
       g_file_get_contents (argv[1], &contents, &length, &error);
       g_assert_no_error (error);
       orig = g_bytes_new_take (contents, length);
       context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-      layout = pango_simple_layout_deserialize (context, orig, PANGO_SIMPLE_LAYOUT_DESERIALIZE_CONTEXT, 
&error);
+      layout = pango_layout_deserialize (context, orig, PANGO_LAYOUT_DESERIALIZE_CONTEXT, &error);
       g_assert_no_error (error);
 
-      bytes = pango_simple_layout_serialize (layout, PANGO_SIMPLE_LAYOUT_SERIALIZE_CONTEXT |
-                                                     PANGO_SIMPLE_LAYOUT_SERIALIZE_OUTPUT);
+      bytes = pango_layout_serialize (layout, PANGO_LAYOUT_SERIALIZE_CONTEXT |
+                                              PANGO_LAYOUT_SERIALIZE_OUTPUT);
 
       g_object_unref (layout);
       g_object_unref (context);
diff --git a/tests/test-pangocairo-threads.c b/tests/test-pangocairo-threads.c
index 308f87e4..abdc5624 100644
--- a/tests/test-pangocairo-threads.c
+++ b/tests/test-pangocairo-threads.c
@@ -18,20 +18,20 @@ create_surface (void)
   return cairo_image_surface_create (CAIRO_FORMAT_A8, WIDTH, HEIGHT);
 }
 
-static PangoSimpleLayout *
+static PangoLayout *
 create_layout (cairo_t *cr)
 {
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
 
-  layout = pango_cairo_create_simple_layout (cr);
-  pango_simple_layout_set_text (layout, text, -1);
-  pango_simple_layout_set_width (layout, WIDTH * PANGO_SCALE);
+  layout = pango_cairo_create_layout (cr);
+  pango_layout_set_text (layout, text, -1);
+  pango_layout_set_width (layout, WIDTH * PANGO_SCALE);
 
   return layout;
 }
 
 static void
-draw (cairo_t *cr, PangoSimpleLayout *layout, unsigned int i)
+draw (cairo_t *cr, PangoLayout *layout, unsigned int i)
 {
   cairo_set_source_rgba (cr, 1, 1, 1, 1);
   cairo_paint (cr);
@@ -40,16 +40,16 @@ draw (cairo_t *cr, PangoSimpleLayout *layout, unsigned int i)
 
   cairo_identity_matrix (cr);
   cairo_scale (cr, (100 + i) / 100.,  (100 + i) / 100.);
-  pango_cairo_update_context (cr, pango_simple_layout_get_context (layout));
+  pango_cairo_update_context (cr, pango_layout_get_context (layout));
 
-  pango_cairo_show_lines (cr, pango_simple_layout_get_lines (layout));
+  pango_cairo_show_lines (cr, pango_layout_get_lines (layout));
 }
 
 static gpointer
 thread_func (gpointer data)
 {
   cairo_surface_t *surface = data;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   int i;
 
   cairo_t *cr = cairo_create (surface);
@@ -102,7 +102,7 @@ pangocairo_threads (void)
   {
     cairo_surface_t *ref_surface = create_surface ();
     cairo_t *cr = cairo_create (ref_surface);
-    PangoSimpleLayout *layout = create_layout (cr);
+    PangoLayout *layout = create_layout (cr);
     unsigned char *ref_data = cairo_image_surface_get_data (ref_surface);
     unsigned int len = WIDTH * HEIGHT;
 
diff --git a/tests/testiter.c b/tests/testiter.c
index 5282c236..8374505f 100644
--- a/tests/testiter.c
+++ b/tests/testiter.c
@@ -77,21 +77,21 @@ const char *test_texts[] =
  *  - GlyphString's index_to_x positions match those returned by the Iter
  */
 static void
-iter_char_test (PangoSimpleLayout *layout)
+iter_char_test (PangoLayout *layout)
 {
   PangoRectangle   extents, run_extents;
   PangoLineIter *iter;
-  PangoGlyphItem  *run;
+  PangoRun  *run;
   int              num_chars;
   int              i, index, offset;
   int              leading_x, trailing_x, x0, x1;
   gboolean         iter_next_ok, rtl;
   const char      *text, *ptr;
 
-  text = pango_simple_layout_get_text (layout);
+  text = pango_layout_get_text (layout);
   num_chars = g_utf8_strlen (text, -1);
 
-  iter = pango_lines_get_iter (pango_simple_layout_get_lines (layout));
+  iter = pango_lines_get_iter (pango_layout_get_lines (layout));
   iter_next_ok = TRUE;
 
   for (i = 0 ; i < num_chars; ++i)
@@ -117,26 +117,31 @@ iter_char_test (PangoSimpleLayout *layout)
         {
           PangoFontDescription *desc;
           char *str;
+          PangoItem *item;
+          PangoGlyphString *glyphs;
+
+          item = pango_run_get_item (run);
+          glyphs = pango_run_get_glyphs (run);
 
           /* Get needed data for the GlyphString */
           pango_line_iter_get_run_extents (iter, NULL, &run_extents);
-          offset = run->item->offset;
-          rtl = run->item->analysis.level%2;
-          desc = pango_font_describe (run->item->analysis.font);
+          offset = item->offset;
+          rtl = item->analysis.level%2;
+          desc = pango_font_describe (item->analysis.font);
           str = pango_font_description_to_string (desc);
           verbose ("  (current run: font=%s,offset=%d,x=%d,len=%d,rtl=%d)\n",
-                   str, offset, run_extents.x, run->item->length, rtl);
+                   str, offset, run_extents.x, item->length, rtl);
           g_free (str);
           pango_font_description_free (desc);
 
           /* Calculate expected x result using index_to_x */
-          pango_glyph_string_index_to_x (run->glyphs,
-                                         (char *)(text + offset), run->item->length,
-                                         &run->item->analysis,
+          pango_glyph_string_index_to_x (glyphs,
+                                         (char *)(text + offset), item->length,
+                                         &item->analysis,
                                          index - offset, FALSE, &leading_x);
-          pango_glyph_string_index_to_x (run->glyphs,
-                                         (char *)(text + offset), run->item->length,
-                                         &run->item->analysis,
+          pango_glyph_string_index_to_x (glyphs,
+                                         (char *)(text + offset), item->length,
+                                         &item->analysis,
                                          index - offset, TRUE, &trailing_x);
 
           x0 = run_extents.x + MIN (leading_x, trailing_x);
@@ -165,16 +170,16 @@ iter_char_test (PangoSimpleLayout *layout)
 }
 
 static void
-iter_cluster_test (PangoSimpleLayout *layout)
+iter_cluster_test (PangoLayout *layout)
 {
   PangoRectangle   extents;
   PangoLineIter *iter;
   int              index;
   gboolean         iter_next_ok;
-  PangoLine *last_line = NULL;
+  PangoLine       *last_line = NULL;
   int              expected_next_x = 0;
 
-  iter = pango_lines_get_iter (pango_simple_layout_get_lines (layout));
+  iter = pango_lines_get_iter (pango_layout_get_lines (layout));
   iter_next_ok = TRUE;
 
   while (iter_next_ok)
@@ -214,21 +219,21 @@ iter_cluster_test (PangoSimpleLayout *layout)
 }
 
 static void
-test_layout_iter (void)
+test_line_iter (void)
 {
   const char  **ptext;
   PangoFontMap *fontmap;
   PangoContext *context;
   PangoFontDescription *font_desc;
-  PangoSimpleLayout  *layout;
+  PangoLayout  *layout;
 
   fontmap = pango_cairo_font_map_get_default ();
   context = pango_font_map_create_context (fontmap);
   font_desc = pango_font_description_from_string ("cantarell 11");
   pango_context_set_font_description (context, font_desc);
 
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_width (layout, LAYOUT_WIDTH);
+  layout = pango_layout_new (context);
+  pango_layout_set_width (layout, LAYOUT_WIDTH);
 
   for (ptext = test_texts; *ptext != NULL; ++ptext)
     {
@@ -237,7 +242,7 @@ test_layout_iter (void)
       verbose ( "len=%ld, bytes=%ld\n",
                 (long)g_utf8_strlen (*ptext, -1), (long)strlen (*ptext));
 
-      pango_simple_layout_set_text (layout, *ptext, -1);
+      pango_layout_set_text (layout, *ptext, -1);
       iter_char_test (layout);
       iter_cluster_test (layout);
     }
@@ -253,7 +258,7 @@ test_glyphitem_iter (void)
   PangoFontMap *fontmap;
   PangoContext *context;
   PangoFontDescription *font_desc;
-  PangoSimpleLayout  *layout;
+  PangoLayout  *layout;
   PangoLine *line;
   const char *text;
   GSList *l;
@@ -263,12 +268,12 @@ test_glyphitem_iter (void)
   font_desc = pango_font_description_from_string ("cantarell 11");
   pango_context_set_font_description (context, font_desc);
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
   /* This shouldn't form any ligatures. */
-  pango_simple_layout_set_text (layout, "test تست", -1);
-  text = pango_simple_layout_get_text (layout);
+  pango_layout_set_text (layout, "test تست", -1);
+  text = pango_layout_get_text (layout);
 
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
   for (l = pango_line_get_runs (line); l; l = l->next)
   {
     PangoGlyphItem *run = l->data;
@@ -315,7 +320,7 @@ main (int argc, char *argv[])
 {
   g_test_init (&argc, &argv, NULL);
 
-  g_test_add_func ("/layout/iter", test_layout_iter);
+  g_test_add_func ("/layout/iter", test_line_iter);
   g_test_add_func ("/layout/glyphitem-iter", test_glyphitem_iter);
 
   return g_test_run ();
diff --git a/tests/testmisc.c b/tests/testmisc.c
index b3d7eb49..a8c6c689 100644
--- a/tests/testmisc.c
+++ b/tests/testmisc.c
@@ -57,13 +57,13 @@ static void
 test_short_string_crash (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle ext;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "short text", 200);
-  pango_lines_get_extents (pango_simple_layout_get_lines (layout), &ext, &ext);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "short text", 200);
+  pango_lines_get_extents (pango_layout_get_lines (layout), &ext, &ext);
 
   g_object_unref (layout);
   g_object_unref (context);
@@ -87,14 +87,14 @@ static void
 test_line_height (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoLine *line;
   PangoRectangle ext;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "one\ttwo", -1);
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "one\ttwo", -1);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
   pango_line_get_extents (line, NULL, &ext);
 
   g_assert_cmpint (ext.height, >, 0);
@@ -107,27 +107,27 @@ static void
 test_line_height2 (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoLine *line;
   PangoRectangle ext1, ext2;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "one", -1);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "one", -1);
 
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
   g_assert_nonnull (line);
   pango_line_get_extents (line, NULL, &ext1);
 
-  pango_simple_layout_write_to_file (layout, "one.layout");
+  pango_layout_write_to_file (layout, "one.layout");
 
-  pango_simple_layout_set_text (layout, "", -1);
+  pango_layout_set_text (layout, "", -1);
 
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
   g_assert_nonnull (line);
   pango_line_get_extents (line, NULL, &ext2);
 
-  pango_simple_layout_write_to_file (layout, "empty.layout");
+  pango_layout_write_to_file (layout, "empty.layout");
 
   g_assert_cmpint (ext1.height, ==, ext2.height);
 
@@ -139,28 +139,28 @@ static void
 test_line_height3 (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoLine *line;
   PangoAttrList *attrs;
   PangoRectangle ext1;
   PangoRectangle ext2;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "one", -1);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "one", -1);
   attrs = pango_attr_list_new ();
   pango_attr_list_insert (attrs, pango_attr_line_height_new (2.0));
-  pango_simple_layout_set_attributes (layout, attrs);
+  pango_layout_set_attributes (layout, attrs);
   pango_attr_list_unref (attrs);
 
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
-  g_assert_cmpint (pango_lines_get_line_count (pango_simple_layout_get_lines (layout)), ==, 1);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
+  g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1);
   pango_line_get_extents (line, NULL, &ext1);
 
-  pango_simple_layout_set_text (layout, "", -1);
+  pango_layout_set_text (layout, "", -1);
 
-  g_assert_cmpint (pango_lines_get_line_count (pango_simple_layout_get_lines (layout)), ==, 1);
-  line = pango_lines_get_line (pango_simple_layout_get_lines (layout), 0, NULL, NULL);
+  g_assert_cmpint (pango_lines_get_line_count (pango_layout_get_lines (layout)), ==, 1);
+  line = pango_lines_get_line (pango_layout_get_lines (layout), 0, NULL, NULL);
   pango_line_get_extents (line, NULL, &ext2);
 
   g_assert_cmpint (ext1.height, ==, ext2.height);
@@ -173,7 +173,7 @@ static void
 test_run_height (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoLineIter *iter;
   PangoRectangle logical1, logical2;
 
@@ -184,16 +184,16 @@ test_run_height (void)
     }
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "one", -1);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "one", -1);
 
-  iter = pango_lines_get_iter (pango_simple_layout_get_lines (layout));
+  iter = pango_lines_get_iter (pango_layout_get_lines (layout));
   pango_line_iter_get_run_extents (iter, NULL, &logical1);
   pango_line_iter_free (iter);
 
-  pango_simple_layout_set_text (layout, "", -1);
+  pango_layout_set_text (layout, "", -1);
 
-  iter = pango_lines_get_iter (pango_simple_layout_get_lines (layout));
+  iter = pango_lines_get_iter (pango_layout_get_lines (layout));
   pango_line_iter_get_run_extents (iter, NULL, &logical2);
   pango_line_iter_free (iter);
 
@@ -207,13 +207,13 @@ static void
 test_cursor_height (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle strong;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "one\ttwo", -1);
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 0, &strong, NULL);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "one\ttwo", -1);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 0, &strong, NULL);
 
   g_assert_cmpint (strong.height, >, 0);
 
@@ -225,7 +225,7 @@ static void
 test_cursor_height2 (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle strong1, strong2;
 
   if (strcmp (G_OBJECT_TYPE_NAME (pango_cairo_font_map_get_default ()), "PangoCairoCoreTextFontMap") == 0)
@@ -235,14 +235,14 @@ test_cursor_height2 (void)
     }
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "one", -1);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "one", -1);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 0, &strong1, NULL);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 0, &strong1, NULL);
 
-  pango_simple_layout_set_text (layout, "", -1);
+  pango_layout_set_text (layout, "", -1);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 0, &strong2, NULL);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 0, &strong2, NULL);
 
   g_assert_cmpint (strong1.height, ==, strong2.height);
 
@@ -416,22 +416,22 @@ static void
 test_get_cursor_crash (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   int i;
 
   const char *string = "foo\n\rbar\r\nbaz\n\nqux\n\n..";
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
 
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
 
-  pango_simple_layout_set_text (layout, string, -1);
+  pango_layout_set_text (layout, string, -1);
 
   for (i = 0; string[i]; i++)
     {
       PangoRectangle rectA, rectB;
 
-      pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, i, &rectA, &rectB);
+      pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, i, &rectA, &rectB);
       g_assert_cmpint (rectA.x, ==, rectB.x);
     }
 
@@ -448,27 +448,27 @@ test_get_cursor (void)
 {
   const char *text = "abאב";
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle strong, weak;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
 
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, text, -1);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, text, -1);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 0, &strong, &weak);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 0, &strong, &weak);
   g_assert_cmpint (strong.x, ==, weak.x);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 1, &strong, &weak);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 1, &strong, &weak);
   g_assert_cmpint (strong.x, ==, weak.x);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 2, &strong, &weak);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 2, &strong, &weak);
   g_assert_cmpint (strong.x, !=, weak.x);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 4, &strong, &weak);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 4, &strong, &weak);
   g_assert_cmpint (strong.x, ==, weak.x);
 
-  pango_lines_get_cursor_pos (pango_simple_layout_get_lines (layout), NULL, 6, &strong, &weak);
+  pango_lines_get_cursor_pos (pango_layout_get_lines (layout), NULL, 6, &strong, &weak);
   g_assert_cmpint (strong.x, !=, weak.x);
 
   g_object_unref (layout);
@@ -488,13 +488,13 @@ test_index_to_x (void)
 
   for (int i = 0; i < G_N_ELEMENTS (tests); i++)
     {
-      PangoSimpleLayout *layout;
+      PangoLayout *layout;
       const char *text;
       const char *p;
 
-      layout = pango_simple_layout_new (context);
-      pango_simple_layout_set_text (layout, tests[i], -1);
-      text = pango_simple_layout_get_text (layout);
+      layout = pango_layout_new (context);
+      pango_layout_set_text (layout, tests[i], -1);
+      text = pango_layout_get_text (layout);
 
       for (p = text; *p; p = g_utf8_next_char (p))
         {
@@ -506,7 +506,7 @@ test_index_to_x (void)
 
           ch = g_utf8_get_char (p);
 
-          pango_lines_index_to_line (pango_simple_layout_get_lines (layout), index, &line, NULL, NULL, NULL);
+          pango_lines_index_to_line (pango_layout_get_lines (layout), index, &line, NULL, NULL, NULL);
           g_assert_nonnull (line);
 
           pango_line_index_to_x (line, index, 0, &x);
@@ -555,7 +555,7 @@ test_extents (void)
 
   for (int i = 0; i < G_N_ELEMENTS (tests); i++)
     {
-      PangoSimpleLayout *layout;
+      PangoLayout *layout;
       PangoLines *lines;
       PangoLineIter *iter;
       PangoRectangle layout_extents;
@@ -567,11 +567,11 @@ test_extents (void)
       PangoRectangle strong, weak;
       int index;
 
-      layout = pango_simple_layout_new (context);
-      pango_simple_layout_set_text (layout, tests[i].text, -1);
-      pango_simple_layout_set_width (layout, tests[i].width > 0 ? tests[i].width * PANGO_SCALE : 
tests[i].width);
+      layout = pango_layout_new (context);
+      pango_layout_set_text (layout, tests[i].text, -1);
+      pango_layout_set_width (layout, tests[i].width > 0 ? tests[i].width * PANGO_SCALE : tests[i].width);
 
-      lines = pango_simple_layout_get_lines (layout);
+      lines = pango_layout_get_lines (layout);
       pango_lines_get_extents (lines, NULL, &layout_extents);
 
       iter = pango_lines_get_iter (lines);
@@ -613,7 +613,7 @@ static void
 test_empty_line_height (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoFontDescription *description;
   PangoRectangle ext1, ext2, ext3;
   cairo_font_options_t *options;
@@ -640,20 +640,20 @@ test_empty_line_height (void)
           pango_cairo_context_set_font_options (context, options);
           cairo_font_options_destroy (options);
 
-          layout = pango_simple_layout_new (context);
-          pango_simple_layout_set_font_description (layout, description);
+          layout = pango_layout_new (context);
+          pango_layout_set_font_description (layout, description);
 
-          pango_lines_get_extents (pango_simple_layout_get_lines (layout), NULL, &ext1);
+          pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &ext1);
 
-          pango_simple_layout_set_text (layout, "a", 1);
+          pango_layout_set_text (layout, "a", 1);
 
-          pango_lines_get_extents (pango_simple_layout_get_lines (layout), NULL, &ext2);
+          pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &ext2);
 
           g_assert_cmpint (ext1.height, ==, ext2.height);
 
-          pango_simple_layout_set_text (layout, "Pg", 1);
+          pango_layout_set_text (layout, "Pg", 1);
 
-          pango_lines_get_extents (pango_simple_layout_get_lines (layout), NULL, &ext3);
+          pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &ext3);
 
           g_assert_cmpint (ext2.height, ==, ext3.height);
 
@@ -748,19 +748,19 @@ static void
 test_wrap_char (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoRectangle ext, ext1;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, "Rows can have suffix widgets", -1);
-  pango_simple_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, "Rows can have suffix widgets", -1);
+  pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
 
-  pango_simple_layout_set_width (layout, 0);
-  pango_lines_get_extents (pango_simple_layout_get_lines (layout), NULL, &ext);
+  pango_layout_set_width (layout, 0);
+  pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &ext);
 
-  pango_simple_layout_set_width (layout, ext.width);
-  pango_lines_get_extents (pango_simple_layout_get_lines (layout), NULL, &ext1);
+  pango_layout_set_width (layout, ext.width);
+  pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &ext1);
 
   g_assert_cmpint (ext.width, ==, ext1.width);
   g_assert_cmpint (ext.height, >=, ext1.height);
@@ -774,7 +774,7 @@ static void
 test_small_caps_crash (void)
 {
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   PangoFontDescription *desc;
   PangoRectangle ext;
 
@@ -785,13 +785,13 @@ test_small_caps_crash (void)
     }
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
-  layout = pango_simple_layout_new (context);
+  layout = pango_layout_new (context);
   desc = pango_font_description_from_string ("Cantarell Small-Caps 11");
-  pango_simple_layout_set_font_description (layout, desc);
+  pango_layout_set_font_description (layout, desc);
 
-  pango_simple_layout_set_text (layout, "Pere Ràfols Soler\nEqualiser, LV2\nAudio: 1, 1\nMidi: 0, 
0\nControls: 53, 2\nCV: 0, 0", -1);
+  pango_layout_set_text (layout, "Pere Ràfols Soler\nEqualiser, LV2\nAudio: 1, 1\nMidi: 0, 0\nControls: 53, 
2\nCV: 0, 0", -1);
 
-  pango_lines_get_extents (pango_simple_layout_get_lines (layout), NULL, &ext);
+  pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &ext);
 
   pango_font_description_free (desc);
   g_object_unref (layout);
diff --git a/tests/testrandom.c b/tests/testrandom.c
index 8c0ef83f..d2e1bd19 100644
--- a/tests/testrandom.c
+++ b/tests/testrandom.c
@@ -92,13 +92,13 @@ compare_size (gconstpointer a,
 }
 
 static void
-layout_check_size (PangoSimpleLayout *layout,
+layout_check_size (PangoLayout *layout,
                    int                width,
                    Size              *out_size)
 {
   out_size->set_width = width;
-  pango_simple_layout_set_width (layout, width);
-  pango_lines_get_size (pango_simple_layout_get_lines (layout), &out_size->width, &out_size->height);
+  pango_layout_set_width (layout, width);
+  pango_lines_get_size (pango_layout_get_lines (layout), &out_size->width, &out_size->height);
 }
 
 static void
@@ -107,7 +107,7 @@ test_wrap_char (gconstpointer data)
   PangoDirection dir = GPOINTER_TO_UINT (data);
   PangoFontDescription *desc;
   PangoContext *context;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
   char *sentence;
   Size min, max;
   Size sizes[100];
@@ -115,15 +115,15 @@ test_wrap_char (gconstpointer data)
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
   desc = pango_font_description_from_string ("Sans 10");
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_font_description (layout, desc);
+  layout = pango_layout_new (context);
+  pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);
-  pango_simple_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
+  pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
 
   for (j = 0; j < N_SENTENCES; j++)
     {
       sentence = create_random_sentence (dir);
-      pango_simple_layout_set_text (layout, sentence, -1);
+      pango_layout_set_text (layout, sentence, -1);
       g_test_message ("%s", sentence);
       g_free (sentence);
 
@@ -177,7 +177,7 @@ test_wrap_char_min_width (gconstpointer data)
   PangoDirection dir = GPOINTER_TO_UINT (data);
   PangoFontDescription *desc;
   PangoContext *context;
-  PangoSimpleLayout *test_layout, *ref_layout;
+  PangoLayout *test_layout, *ref_layout;
   char *sentence, *s;
   GString *ref_string;
   gsize j;
@@ -185,18 +185,18 @@ test_wrap_char_min_width (gconstpointer data)
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
   desc = pango_font_description_from_string ("Sans 10");
-  ref_layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_font_description (ref_layout, desc);
-  test_layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_font_description (test_layout, desc);
-  pango_simple_layout_set_wrap (test_layout, PANGO_WRAP_WORD_CHAR);
-  pango_simple_layout_set_width (test_layout, 0);
+  ref_layout = pango_layout_new (context);
+  pango_layout_set_font_description (ref_layout, desc);
+  test_layout = pango_layout_new (context);
+  pango_layout_set_font_description (test_layout, desc);
+  pango_layout_set_wrap (test_layout, PANGO_WRAP_WORD_CHAR);
+  pango_layout_set_width (test_layout, 0);
   pango_font_description_free (desc);
 
   for (j = 0; j < N_SENTENCES; j++)
     {
       sentence = create_random_sentence (dir);
-      pango_simple_layout_set_text (test_layout, sentence, -1);
+      pango_layout_set_text (test_layout, sentence, -1);
       g_test_message ("%s", sentence);
       ref_string = g_string_new ("");
       for (s = sentence; *s; s = g_utf8_next_char (s))
@@ -205,12 +205,12 @@ test_wrap_char_min_width (gconstpointer data)
           g_string_append_unichar (ref_string, g_test_rand_bit () ? 0x2010 : '-');
           g_string_append_c (ref_string, '\n');
         }
-      pango_simple_layout_set_text (ref_layout, ref_string->str, ref_string->len);
+      pango_layout_set_text (ref_layout, ref_string->str, ref_string->len);
       g_string_free (ref_string, TRUE);
       g_free (sentence);
 
-      pango_lines_get_size (pango_simple_layout_get_lines (test_layout), &test_width, NULL);
-      pango_lines_get_size (pango_simple_layout_get_lines (ref_layout), &ref_width, NULL);
+      pango_lines_get_size (pango_layout_get_lines (test_layout), &test_width, NULL);
+      pango_lines_get_size (pango_layout_get_lines (ref_layout), &ref_width, NULL);
 
       g_assert_cmpint (test_width, <=, ref_width);
     }
diff --git a/utils/pango-segmentation.c b/utils/pango-segmentation.c
index 179def49..4c00dcc4 100644
--- a/utils/pango-segmentation.c
+++ b/utils/pango-segmentation.c
@@ -68,7 +68,7 @@ show_segmentation (const char *input,
   int i;
   char *text;
   PangoAttrList *attributes;
-  PangoSimpleLayout *layout;
+  PangoLayout *layout;
 
   context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
 
@@ -80,11 +80,11 @@ show_segmentation (const char *input,
   pango_parse_markup (input, -1, 0, &attributes, &text, NULL, &error);
   g_assert_no_error (error);
 
-  layout = pango_simple_layout_new (context);
-  pango_simple_layout_set_text (layout, text, length);
-  pango_simple_layout_set_attributes (layout, attributes);
+  layout = pango_layout_new (context);
+  pango_layout_set_text (layout, text, length);
+  pango_layout_set_attributes (layout, attributes);
 
-  attrs = pango_simple_layout_get_log_attrs (layout, &len);
+  attrs = pango_layout_get_log_attrs (layout, &len);
 
   for (i = 0, p = text; i < len; i++, p = g_utf8_next_char (p))
     {
diff --git a/utils/viewer-pangocairo.c b/utils/viewer-pangocairo.c
index ae5813bb..f2b5c85b 100644
--- a/utils/viewer-pangocairo.c
+++ b/utils/viewer-pangocairo.c
@@ -25,6 +25,7 @@
 #include "viewer-cairo.h"
 
 #include <pango/pangocairo.h>
+#include <pango/pango-run.h>
 
 #include <hb-ot.h>
 
@@ -206,9 +207,9 @@ render_callback (PangoLayout *layout,
       cairo_pattern_t *pattern;
       PangoRectangle ink, logical;
       double lw = cairo_get_line_width (cr);
-      PangoLayoutIter* iter;
+      PangoLineIter *iter;
 
-      pango_layout_get_extents (layout, &ink, &logical);
+      pango_lines_get_extents (pango_layout_get_lines (layout), &ink, &logical);
 
       if (annotate & ANNOTATE_GRAVITY_ROOF)
         {
@@ -286,15 +287,15 @@ render_callback (PangoLayout *layout,
           iter = pango_layout_get_iter (layout);
           do
             {
-              PangoLayoutLine *line = pango_layout_iter_get_line (iter);
+              PangoLine *line = pango_line_iter_get_line (iter);
               double width = (double)logical.width / PANGO_SCALE;
 
-              y = pango_layout_iter_get_baseline (iter);
+              y = pango_line_iter_get_line_baseline (iter);
               cairo_save (cr);
               cairo_translate (cr,
                              (double)logical.x / PANGO_SCALE + width * 0.5,
                              (double)y / PANGO_SCALE);
-              if (line->resolved_dir)
+              if (pango_line_get_resolved_direction (line))
                 cairo_scale (cr, -1, 1);
               cairo_move_to     (cr, -width * .5, -lw*0.2);
               cairo_rel_line_to (cr, +width * .9, -lw*0.3);
@@ -307,8 +308,8 @@ render_callback (PangoLayout *layout,
               cairo_fill (cr);
               cairo_restore (cr);
             }
-          while (pango_layout_iter_next_line (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_line (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -323,7 +324,8 @@ render_callback (PangoLayout *layout,
           iter = pango_layout_get_iter (layout);
           do
             {
-              PangoLayoutRun *run;
+              PangoRun *run;
+              PangoItem *item;
               PangoRectangle rect;
               hb_font_t *hb_font;
               hb_ot_layout_baseline_tag_t baselines[] = {
@@ -340,32 +342,34 @@ render_callback (PangoLayout *layout,
               hb_tag_t script, lang;
               hb_position_t coord;
 
-              run = pango_layout_iter_get_run (iter);
+              run = pango_line_iter_get_run (iter);
               if (!run)
                 {
                   baseline_tag = 0;
                   continue;
                 }
 
+              item = pango_run_get_item (run);
+
               if (baseline_tag == 0)
                 {
-                  hb_script_t script = (hb_script_t) g_unicode_script_to_iso15924 
(run->item->analysis.script);
+                  hb_script_t script = (hb_script_t) g_unicode_script_to_iso15924 (item->analysis.script);
 
-                  if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+                  if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
                     baseline_tag = HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL;
                   else
                     baseline_tag = hb_ot_layout_get_horizontal_baseline_tag_for_script (script);
                 }
 
-              y = pango_layout_iter_get_run_baseline (iter);
-              pango_layout_iter_get_run_extents (iter, NULL, &rect);
+              y = pango_line_iter_get_run_baseline (iter);
+              pango_line_iter_get_run_extents (iter, NULL, &rect);
 
-              hb_font = pango_font_get_hb_font (run->item->analysis.font);
-              if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+              hb_font = pango_font_get_hb_font (item->analysis.font);
+              if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
                 dir = HB_DIRECTION_TTB;
               else
                 dir = HB_DIRECTION_LTR;
-              script = (hb_script_t) g_unicode_script_to_iso15924 (run->item->analysis.script);
+              script = (hb_script_t) g_unicode_script_to_iso15924 (item->analysis.script);
               lang = HB_TAG_NONE;
 
               for (int i = 0; i < G_N_ELEMENTS (baselines); i++)
@@ -420,8 +424,8 @@ render_callback (PangoLayout *layout,
                   cairo_restore (cr);
                 }
             }
-          while (pango_layout_iter_next_run (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_run (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 #endif
@@ -463,7 +467,7 @@ render_callback (PangoLayout *layout,
             {
               PangoRectangle rect;
 
-              pango_layout_iter_get_line_extents (iter, NULL, &rect);
+              pango_line_iter_get_line_extents (iter, NULL, &rect);
               cairo_rectangle (cr,
                                (double)rect.x / PANGO_SCALE - lw / 2,
                                (double)rect.y / PANGO_SCALE - lw / 2,
@@ -471,8 +475,8 @@ render_callback (PangoLayout *layout,
                                (double)rect.height / PANGO_SCALE + lw);
               cairo_stroke (cr);
             }
-          while (pango_layout_iter_next_line (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_line (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -485,14 +489,14 @@ render_callback (PangoLayout *layout,
           iter = pango_layout_get_iter (layout);
           do
             {
-              PangoLayoutRun *run;
+              PangoRun *run;
               PangoRectangle rect;
 
-              run = pango_layout_iter_get_run (iter);
+              run = pango_line_iter_get_run (iter);
               if (!run)
                 continue;
 
-              pango_layout_iter_get_run_extents (iter, NULL, &rect);
+              pango_line_iter_get_run_extents (iter, NULL, &rect);
               cairo_rectangle (cr,
                                (double)rect.x / PANGO_SCALE - lw / 2,
                                (double)rect.y / PANGO_SCALE - lw / 2,
@@ -500,8 +504,8 @@ render_callback (PangoLayout *layout,
                                (double)rect.height / PANGO_SCALE + lw);
               cairo_stroke (cr);
             }
-          while (pango_layout_iter_next_run (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_run (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -516,7 +520,7 @@ render_callback (PangoLayout *layout,
             {
               PangoRectangle rect;
 
-              pango_layout_iter_get_cluster_extents (iter, NULL, &rect);
+              pango_line_iter_get_cluster_extents (iter, NULL, &rect);
               cairo_rectangle (cr,
                                (double)rect.x / PANGO_SCALE - lw / 2,
                                (double)rect.y / PANGO_SCALE - lw / 2,
@@ -524,8 +528,8 @@ render_callback (PangoLayout *layout,
                                (double)rect.height / PANGO_SCALE + lw);
               cairo_stroke (cr);
             }
-          while (pango_layout_iter_next_cluster (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_cluster (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -540,7 +544,7 @@ render_callback (PangoLayout *layout,
             {
               PangoRectangle rect;
 
-              pango_layout_iter_get_char_extents (iter, &rect);
+              pango_line_iter_get_char_extents (iter, &rect);
               cairo_rectangle (cr,
                                (double)rect.x / PANGO_SCALE - lw / 2,
                                (double)rect.y / PANGO_SCALE - lw / 2,
@@ -548,8 +552,8 @@ render_callback (PangoLayout *layout,
                                (double)rect.height / PANGO_SCALE + lw);
               cairo_stroke (cr);
             }
-          while (pango_layout_iter_next_cluster (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_cluster (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -562,29 +566,34 @@ render_callback (PangoLayout *layout,
           iter = pango_layout_get_iter (layout);
           do
             {
-              PangoLayoutRun *run;
+              PangoRun *run;
+              PangoItem *item;
+              PangoGlyphString *glyphs;
               PangoRectangle rect;
               int x_pos, y_pos;
 
-              run = pango_layout_iter_get_run (iter);
+              run = pango_line_iter_get_run (iter);
               if (!run)
                 continue;
 
-              pango_layout_iter_get_run_extents (iter, NULL, &rect);
+              item = pango_run_get_item (run);
+              glyphs = pango_run_get_glyphs (run);
+
+              pango_line_iter_get_run_extents (iter, NULL, &rect);
 
               x_pos = rect.x;
-              y_pos = pango_layout_iter_get_run_baseline (iter);
+              y_pos = pango_line_iter_get_run_baseline (iter);
 
-              for (int i = 0; i < run->glyphs->num_glyphs; i++)
+              for (int i = 0; i < glyphs->num_glyphs; i++)
                 {
                   PangoRectangle extents;
 
-                  pango_font_get_glyph_extents (run->item->analysis.font,
-                                                run->glyphs->glyphs[i].glyph,
+                  pango_font_get_glyph_extents (item->analysis.font,
+                                                glyphs->glyphs[i].glyph,
                                                 &extents, NULL);
 
-                  rect.x = x_pos + run->glyphs->glyphs[i].geometry.x_offset + extents.x;
-                  rect.y = y_pos + run->glyphs->glyphs[i].geometry.y_offset + extents.y;
+                  rect.x = x_pos + glyphs->glyphs[i].geometry.x_offset + extents.x;
+                  rect.y = y_pos + glyphs->glyphs[i].geometry.y_offset + extents.y;
                   rect.width = extents.width;
                   rect.height = extents.height;
 
@@ -596,16 +605,16 @@ render_callback (PangoLayout *layout,
                   cairo_stroke (cr);
 
                   cairo_arc (cr,
-                             (double) (x_pos + run->glyphs->glyphs[i].geometry.x_offset) / PANGO_SCALE,
-                             (double) (y_pos + run->glyphs->glyphs[i].geometry.y_offset) / PANGO_SCALE,
+                             (double) (x_pos + glyphs->glyphs[i].geometry.x_offset) / PANGO_SCALE,
+                             (double) (y_pos + glyphs->glyphs[i].geometry.y_offset) / PANGO_SCALE,
                              3.0, 0, 2*G_PI);
                   cairo_fill (cr);
 
-                  x_pos += run->glyphs->glyphs[i].geometry.width;
+                  x_pos += glyphs->glyphs[i].geometry.width;
                 }
             }
-          while (pango_layout_iter_next_run (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_run (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -620,40 +629,45 @@ render_callback (PangoLayout *layout,
           cairo_save (cr);
           cairo_set_source_rgba (cr, 1.0, 0.0, 1.0, 0.5);
 
-          attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
+          attrs = pango_layout_get_log_attrs (layout, &n_attrs);
 
           iter = pango_layout_get_iter (layout);
           do
             {
               PangoRectangle rect;
-              PangoLayoutRun *run;
+              PangoRun *run;
+              PangoItem *item;
+              PangoGlyphString *glyphs;
               const char *text, *start, *p;
               int x, y;
               gboolean trailing;
 
-              pango_layout_iter_get_run_extents (iter, NULL, &rect);
-              run = pango_layout_iter_get_run_readonly (iter);
+              pango_line_iter_get_run_extents (iter, NULL, &rect);
+              run = pango_line_iter_get_run (iter);
 
               if (!run)
                 continue;
 
+              item = pango_run_get_item (run);
+              glyphs = pango_run_get_glyphs (run);
+
               text = pango_layout_get_text (layout);
-              start = text + run->item->offset;
+              start = text + item->offset;
 
               offset = g_utf8_strlen (text, start - text);
 
-              y = pango_layout_iter_get_run_baseline (iter);
+              y = pango_line_iter_get_run_baseline (iter);
 
               trailing = FALSE;
               p = start;
-              for (int i = 0; i <= run->item->num_chars; i++)
+              for (int i = 0; i <= item->num_chars; i++)
                 {
                   if (attrs[offset + i].is_cursor_position)
                     {
-                      pango_glyph_string_index_to_x_full (run->glyphs,
-                                                          text + run->item->offset,
-                                                          run->item->length,
-                                                          &run->item->analysis,
+                      pango_glyph_string_index_to_x_full (glyphs,
+                                                          text + item->offset,
+                                                          item->length,
+                                                          &item->analysis,
                                                           (PangoLogAttr *)attrs + offset,
                                                           p - start,
                                                           trailing,
@@ -672,7 +686,7 @@ render_callback (PangoLayout *layout,
                       g_free (s);
                    }
 
-                  if (i < run->item->num_chars)
+                  if (i < item->num_chars)
                     {
                       num++;
                       p = g_utf8_next_char (p);
@@ -682,8 +696,8 @@ render_callback (PangoLayout *layout,
 
                 }
             }
-          while (pango_layout_iter_next_run (iter));
-          pango_layout_iter_free (iter);
+          while (pango_line_iter_next_run (iter));
+          pango_line_iter_free (iter);
           cairo_restore (cr);
         }
 
@@ -700,7 +714,7 @@ render_callback (PangoLayout *layout,
           cairo_save (cr);
           cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
 
-          attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
+          attrs = pango_layout_get_log_attrs (layout, &n_attrs);
 
           for (i = 0, p = text; i <= length; i++, p = g_utf8_next_char (p))
             {
@@ -709,7 +723,7 @@ render_callback (PangoLayout *layout,
               if (!attrs[i].is_cursor_position)
                 continue;
 
-              pango_layout_get_caret_pos (layout, p - text, &rect, NULL);
+              pango_lines_get_caret_pos (pango_layout_get_lines (layout), NULL, p - text, &rect, NULL);
 
               cairo_move_to (cr,
                              (double)rect.x / PANGO_SCALE + (double)rect.width / PANGO_SCALE - lw / 2,
diff --git a/utils/viewer-render.c b/utils/viewer-render.c
index 2f95af80..e0b37d7e 100644
--- a/utils/viewer-render.c
+++ b/utils/viewer-render.c
@@ -52,10 +52,7 @@ gboolean opt_waterfall = FALSE;
 int opt_width = -1;
 int opt_height = -1;
 int opt_indent = 0;
-int opt_spacing = 0;
 double opt_line_spacing = -1.0;
-gboolean opt_justify = 0;
-gboolean opt_justify_last_line = 0;
 int opt_runs = 1;
 PangoAlignment opt_align = PANGO_ALIGN_LEFT;
 PangoEllipsizeMode opt_ellipsize = PANGO_ELLIPSIZE_NONE;
@@ -131,9 +128,7 @@ make_layout(PangoContext *context,
 
   pango_layout_set_auto_dir (layout, opt_auto_dir);
   pango_layout_set_ellipsize (layout, opt_ellipsize);
-  pango_layout_set_justify (layout, opt_justify);
-  pango_layout_set_justify_last_line (layout, opt_justify_last_line);
-  pango_layout_set_single_paragraph_mode (layout, opt_single_par);
+  pango_layout_set_single_paragraph (layout, opt_single_par);
   pango_layout_set_wrap (layout, opt_wrap);
 
   font_description = pango_font_description_from_string (opt_font);
@@ -166,14 +161,6 @@ make_layout(PangoContext *context,
         pango_layout_set_indent (layout, (opt_indent * opt_dpi * PANGO_SCALE + 36) / 72);
     }
 
-  if (opt_spacing != 0)
-    {
-      if (opt_pango_units)
-        pango_layout_set_spacing (layout, opt_spacing);
-      else
-        pango_layout_set_spacing (layout, (opt_spacing * opt_dpi * PANGO_SCALE + 36) / 72);
-      pango_layout_set_line_spacing (layout, 0.0);
-    }
   if (opt_line_spacing >= 0.0)
     pango_layout_set_line_spacing (layout, (float)opt_line_spacing);
 
@@ -195,13 +182,8 @@ make_layout(PangoContext *context,
 out:
   if (opt_serialized_output)
     {
-      GError *error = NULL;
-
-      if (!pango_layout_write_to_file (layout,
-                                       PANGO_LAYOUT_SERIALIZE_CONTEXT|PANGO_LAYOUT_SERIALIZE_OUTPUT,
-                                       opt_serialized_output,
-                                       &error))
-        fail ("%s\n", error->message);
+      if (!pango_layout_write_to_file (layout, opt_serialized_output))
+        fail ("Failed to serialize\n");
     }
 
   return layout;
@@ -278,7 +260,8 @@ output_body (PangoLayout    *layout,
          pango_font_description_free (desc);
        }
 
-      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+      pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &logical_rect);
+      pango_extents_to_pixels (&logical_rect, NULL);
 
       if (render_cb)
        (*render_cb) (layout, x, y+*height, cb_context, cb_data);
@@ -347,7 +330,7 @@ do_output (PangoContext     *context,
       char *options_string = get_options_string ();
       pango_context_set_base_gravity (context, PANGO_GRAVITY_SOUTH);
       layout = make_layout (context, options_string, 10);
-      pango_layout_get_extents (layout, NULL, &rect);
+      pango_lines_get_extents (pango_layout_get_lines (layout), NULL, &rect);
 
       width = MAX (width, PANGO_PIXELS (rect.width));
       height += PANGO_PIXELS (rect.height);
@@ -911,14 +894,8 @@ parse_options (int argc, char *argv[])
      "Subpixel order",                                      "rgb/bgr/vrgb/vbgr"},
     {"indent",         0, 0, G_OPTION_ARG_INT,                         &opt_indent,
      "Width in points to indent paragraphs",                       "points"},
-    {"spacing",                0, 0, G_OPTION_ARG_INT,                         &opt_spacing,
-     "Spacing in points between lines",                                    "points"},
     {"line-spacing",   0, 0, G_OPTION_ARG_DOUBLE,                      &opt_line_spacing,
      "Spread factor for line height",                              "factor"},
-    {"justify",         0, 0, G_OPTION_ARG_NONE,                        &opt_justify,
-     "Stretch paragraph lines to be justified",                         NULL},
-    {"justify-last-line", 0, 0, G_OPTION_ARG_NONE,                      &opt_justify_last_line,
-     "Justify the last line of the paragraph",                          NULL},
     {"language",       0, 0, G_OPTION_ARG_STRING,                      &opt_language,
      "Language to use for font selection",                         "en_US/etc"},
     {"margin",         0, 0, G_OPTION_ARG_CALLBACK,                    &parse_margin,
@@ -939,8 +916,8 @@ parse_options (int argc, char *argv[])
      "Angle at which to rotate results",                          "degrees"},
     {"runs",           'n', 0, G_OPTION_ARG_INT,                       &opt_runs,
      "Run Pango layout engine this many times",                           "integer"},
-    {"single-par",     0, 0, G_OPTION_ARG_NONE,                        &opt_single_par,
-     "Enable single-paragraph mode",                                   NULL},
+    {"single-par",     0, 0, G_OPTION_ARG_NONE,                        &opt_single_par,
+     "Enable single-paragraph mode",                                   NULL},
     {"text",           't', 0, G_OPTION_ARG_STRING,                    &opt_text,
      "Text to display (instead of a file)",                        "string"},
     {"version",                0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &show_version,


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