[pango/line-breaker: 6/18] Add PangoLine
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/line-breaker: 6/18] Add PangoLine
- Date: Sat, 15 Jan 2022 15:37:29 +0000 (UTC)
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]