[pango/line-breaker: 6/18] Add PangoLine




commit c5cfd5ed56e4b8c8e714b21a0b0096ce97a586b1
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jan 14 22:07:35 2022 -0500

    Add PangoLine
    
    This is an opaque, immutable object holding
    a line of shaped text.

 pango/meson.build          |   1 +
 pango/pango-line-private.h |  56 +++++++
 pango/pango-line.c         | 355 +++++++++++++++++++++++++++++++++++++++++++++
 pango/pango-line.h         |  73 ++++++++++
 pango/pango.h              |   1 +
 5 files changed, 486 insertions(+)
---
diff --git a/pango/meson.build b/pango/meson.build
index 9f4c49be..7d062f25 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -31,6 +31,7 @@ pango_sources = [
   'serializer.c',
   'json/gtkjsonparser.c',
   'json/gtkjsonprinter.c',
+  'pango-line.c',
 ]
 
 pango_headers = [
diff --git a/pango/pango-line-private.h b/pango/pango-line-private.h
new file mode 100644
index 00000000..7d01e751
--- /dev/null
+++ b/pango/pango-line-private.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "pango-line.h"
+#include "pango-break.h"
+#include "pango-attributes.h"
+
+typedef struct _LineData LineData;
+struct _LineData {
+  char *text;
+  int length;
+  int n_chars;
+  PangoDirection direction;
+
+  PangoAttrList *attrs;
+  PangoLogAttr *log_attrs;
+};
+
+LineData *      line_data_new           (void);
+LineData *      line_data_ref           (LineData *data);
+void            line_data_unref         (LineData *data);
+void            line_data_clear         (LineData *data);
+
+struct _PangoLine
+{
+  GObject parent_instance;
+
+  LineData *data;
+
+  int start_index;
+  int start_offset;
+  int length;
+  GSList *runs;
+
+  guint wrapped             : 1;
+  guint ellipsized          : 1;
+  guint hyphenated          : 1;
+  guint starts_paragraph    : 1;
+  guint ends_paragraph      : 1;
+  guint has_logical_rect    : 1;
+  guint has_ink_rect        : 1;
+
+  PangoDirection direction;
+
+  int x, y;
+
+  PangoRectangle ink_rect;
+  PangoRectangle logical_rect;
+};
+
+PangoLine * pango_line_new       (LineData *data);
+
+void        pango_line_ellipsize (PangoLine          *line,
+                                  PangoContext       *context,
+                                  PangoEllipsizeMode  ellipsize,
+                                  int                 goal_width);
+
diff --git a/pango/pango-line.c b/pango/pango-line.c
new file mode 100644
index 00000000..f2f5afd7
--- /dev/null
+++ b/pango/pango-line.c
@@ -0,0 +1,355 @@
+#include "config.h"
+
+#include "pango-line-private.h"
+
+#include "pango-tabs.h"
+#include "pango-impl-utils.h"
+#include "pango-attributes-private.h"
+
+/* {{{ LineData */
+
+void
+line_data_clear (LineData *data)
+{
+  g_free (data->text);
+  g_clear_pointer (&data->attrs, pango_attr_list_unref);
+  g_free (data->log_attrs);
+}
+
+LineData *
+line_data_new (void)
+{
+  return g_rc_box_new0 (LineData);
+}
+
+LineData *
+line_data_ref (LineData *data)
+{
+  return g_rc_box_acquire (data);
+}
+
+void
+line_data_unref (LineData *data)
+{
+  g_rc_box_release_full (data, (GDestroyNotify) line_data_clear);
+}
+
+/* }}} */
+/* {{{ PangoLine implementation */
+
+struct _PangoLineClass
+{
+  GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (PangoLine, pango_line, G_TYPE_OBJECT)
+
+static void
+pango_line_init (PangoLine *line)
+{
+}
+
+static void
+pango_line_finalize (GObject *object)
+{
+  PangoLine *line = PANGO_LINE (object);
+
+  line_data_unref (line->data);
+  g_slist_free_full (line->runs, (GDestroyNotify)pango_glyph_item_free);
+
+  G_OBJECT_CLASS (pango_line_parent_class)->finalize (object);
+}
+
+static void
+pango_line_class_init (PangoLineClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = pango_line_finalize;
+}
+
+/* }}} */
+/* {{{ Public API */
+
+PangoLine *
+pango_line_new (LineData *data)
+{
+  PangoLine *line;
+
+  line = g_object_new (PANGO_TYPE_LINE, NULL);
+
+  line->data = line_data_ref (data);
+
+  return line;
+}
+
+/**
+ * pango_line_get_runs:
+ * @line: a `PangoLine`
+ *
+ * Gets the runs of the line.
+ *
+ * Note that the returned list and its contents
+ * are owned by Pango and must not be modified.
+ *
+ * Returns: (transfer none): a list of `PangoGlyphItem`
+ */
+GSList *
+pango_line_get_runs (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), NULL);
+
+  return line->runs;
+}
+
+/**
+ * pango_line_is_wrapped:
+ * @line: a `PangoLine`
+ *
+ * Gets whether the line is wrapped.
+ *
+ * Returns: `TRUE` if @line has been wrapped
+ */
+gboolean
+pango_line_is_wrapped (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), FALSE);
+
+  return line->wrapped;
+}
+
+/**
+ * pango_line_is_ellipsized:
+ * @line: a `PangoLine`
+ *
+ * Gets whether the line is ellipsized.
+ *
+ * Returns: `TRUE` if @line has been ellipsized
+ */
+gboolean
+pango_line_is_ellipsized (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), FALSE);
+
+  return line->ellipsized;
+}
+
+/**
+ * pango_line_is_hyphenated:
+ * @line: a `PangoLine`
+ *
+ * Gets whether the line is hyphenated.
+ *
+ * Returns: `TRUE` if @line has been hyphenated
+ */
+gboolean
+pango_line_is_hyphenated (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), FALSE);
+
+  return line->hyphenated;
+}
+
+/**
+ * pango_line_starts_paragraph:
+ * @line: a `PangoLine`
+ *
+ * Gets whether the line is the first of a paragraph.
+ *
+ * Returns: `TRUE` if @line starts a paragraph
+ */
+gboolean
+pango_line_starts_paragraph (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), FALSE);
+
+  return line->starts_paragraph;
+}
+
+/**
+ * pango_line_ends_paragraph:
+ * @line: a `PangoLine`
+ *
+ * Gets whether the line is the last of a paragraph.
+ *
+ * Returns: `TRUE` if @line ends a paragraph
+ */
+gboolean
+pango_line_ends_paragraph (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), FALSE);
+
+  return line->ends_paragraph;
+}
+
+/**
+ * pango_line_get_direction:
+ * @line: a `PangoLine`
+ *
+ * Gets the text direction of the line.
+ *
+ * Returns: the direction of @line
+ */
+PangoDirection
+pango_line_get_direction (PangoLine *line)
+{
+  g_return_val_if_fail (PANGO_IS_LINE (line), PANGO_DIRECTION_LTR);
+
+  return line->direction;
+}
+
+extern void pango_layout_run_get_extents_and_height (PangoLayoutRun *run,
+                                                     PangoRectangle *run_ink,
+                                                     PangoRectangle *run_logical,
+                                                     PangoRectangle *line_logical,
+                                                     int            *height);
+
+/**
+ * pango_line_get_extents:
+ * @line: a `PangoLine`
+ * @ext: (out): rectangle that will be filled with the extents
+ *
+ * Gets the logical extents of the line.
+ *
+ * Note that the origin is at the left end of the baseline.
+ */
+void
+pango_line_get_extents (PangoLine      *line,
+                        PangoRectangle *ext)
+{
+  PangoRectangle rect = { 0, };
+  int x_pos, y_pos;
+  GSList *l;
+
+  if (line->has_logical_rect)
+    goto cached;
+
+  x_pos = line->x;
+  y_pos = line->y;
+
+  for (l = line->runs; l; l = l->next)
+    {
+      PangoLayoutRun *run = l->data;
+      PangoRectangle run_ext;
+      int new_pos;
+
+      pango_layout_run_get_extents_and_height (run, NULL, NULL, &run_ext, NULL);
+
+      new_pos = MIN (rect.x, x_pos + run_ext.x);
+      rect.width = MAX (rect.x + rect.width, x_pos + run_ext.x + run_ext.width) - new_pos;
+      rect.x = new_pos;
+
+      new_pos = MIN (rect.y, y_pos + run_ext.y);
+      rect.height = MAX (rect.y + rect.height, run_ext.y + run_ext.height) - new_pos;
+      rect.y = new_pos;
+
+      x_pos += run_ext.width;
+    }
+
+  line->logical_rect = rect;
+  line->has_logical_rect = TRUE;
+
+cached:
+  *ext = line->logical_rect;
+}
+
+/**
+ * pango_line_get_ink_extents:
+ * @line: a `PangoLine`
+ * @ext: (out): rectangle that will be filled with the extents
+ *
+ * Gets the ink extents of the line.
+ *
+ * Note that the origin is at the left end of the baseline.
+ */
+void
+pango_line_get_ink_extents (PangoLine      *line,
+                            PangoRectangle *ext)
+{
+  PangoRectangle rect = { 0, };
+  int x_pos, y_pos;
+  GSList *l;
+
+  if (line->has_ink_rect)
+    goto cached;
+
+  x_pos = line->x;
+  y_pos = line->y;
+
+  for (l = line->runs; l; l = l->next)
+    {
+      PangoLayoutRun *run = l->data;
+      PangoRectangle run_ext;
+      int new_pos;
+
+      pango_layout_run_get_extents_and_height (run, NULL, &run_ext, NULL, NULL);
+
+      if (rect.width == 0 || rect.height == 0)
+        {
+          rect = run_ext;
+          rect.x += x_pos;
+          rect.y += y_pos;
+        }
+      else
+        {
+          new_pos = MIN (rect.x, x_pos + run_ext.x);
+          rect.width = MAX (rect.x + rect.width, x_pos + run_ext.x + run_ext.width) - new_pos;
+          rect.x = new_pos;
+
+          new_pos = MIN (rect.y, y_pos + run_ext.y);
+          rect.height = MAX (rect.y + rect.height, run_ext.y + run_ext.height) - new_pos;
+          rect.y = new_pos;
+        }
+
+      x_pos += run_ext.width;
+    }
+
+  line->ink_rect = rect;
+  line->has_ink_rect = TRUE;
+
+cached:
+  *ext = line->ink_rect;
+}
+
+void
+pango_line_index_to_pos (PangoLine      *line,
+                         int             index,
+                         PangoRectangle *pos)
+{
+  /* FIXME */
+}
+
+gboolean
+pango_line_pos_to_index (PangoLine *lines,
+                         int        x,
+                         int        y,
+                         int       *index,
+                         int       *trailing)
+{
+  /* FIXME */
+  return FALSE;
+}
+
+void
+pango_line_get_cursor_pos (PangoLine      *lines,
+                           int             index,
+                           PangoRectangle *strong_pos,
+                           PangoRectangle *weak_pos)
+{
+  /* FIXME */
+}
+
+void
+pango_line_move_cursor_visually (PangoLine *lines,
+                                 gboolean   strong,
+                                 int        index,
+                                 int       trailing,
+                                 int       *new_index,
+                                 int       *new_trailing)
+{
+  /* FIXME */
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-line.h b/pango/pango-line.h
new file mode 100644
index 00000000..1302de9f
--- /dev/null
+++ b/pango/pango-line.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <glib-object.h>
+
+#include <pango/pango-types.h>
+#include <pango/pango-layout.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_LINE pango_line_get_type ()
+
+G_DECLARE_FINAL_TYPE (PangoLine, pango_line, PANGO, LINE, GObject);
+
+PANGO_AVAILABLE_IN_ALL
+GSList *                pango_line_get_runs             (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_line_is_wrapped           (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_line_is_ellipsized        (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_line_is_hyphenated        (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_line_starts_paragraph     (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_line_ends_paragraph       (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+PangoDirection          pango_line_get_direction        (PangoLine             *line);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_line_get_extents          (PangoLine             *line,
+                                                         PangoRectangle        *ext);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_line_get_ink_extents      (PangoLine             *line,
+                                                         PangoRectangle        *ext);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_line_index_to_pos         (PangoLine             *line,
+                                                         int                    index,
+                                                         PangoRectangle        *pos);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean                pango_line_pos_to_index         (PangoLine             *lines,
+                                                         int                    x,
+                                                         int                    y,
+                                                         int                   *index,
+                                                         int                   *trailing);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_line_get_cursor_pos       (PangoLine             *lines,
+                                                         int                    index,
+                                                         PangoRectangle        *strong_pos,
+                                                         PangoRectangle        *weak_pos);
+
+PANGO_AVAILABLE_IN_ALL
+void                    pango_line_move_cursor_visually (PangoLine             *lines,
+                                                         gboolean               strong,
+                                                         int                    index,
+                                                         int                    trailing,
+                                                         int                   *new_index,
+                                                         int                   *new_trailing);
+
+PANGO_AVAILABLE_IN_ALL
+GBytes *                pango_lines_serialize           (PangoLine            **lines,
+                                                         unsigned int           n_lines);
+
+G_END_DECLS
diff --git a/pango/pango.h b/pango/pango.h
index eca66265..c2aa5669 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -42,6 +42,7 @@
 #include <pango/pango-item.h>
 #include <pango/pango-language.h>
 #include <pango/pango-layout.h>
+#include <pango/pango-line.h>
 #include <pango/pango-matrix.h>
 #include <pango/pango-markup.h>
 #include <pango/pango-renderer.h>


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