summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-02-05 19:18:57 +0100
committerMatthias Clasen <mclasen@redhat.com>2022-02-13 14:28:05 -0600
commit03d2aff5518b72652fab592ef3d72852ce3ae3ef (patch)
tree9fb0f3f67f4a38aa53c7d4d52da9960a3436bc6c
parent04aae5f7ad1ab48248307b8995e558ad866afee5 (diff)
downloadpango-03d2aff5518b72652fab592ef3d72852ce3ae3ef.tar.gz
Split pango-attributes.[hc]
Split pango-attributes.[hc] into separate files for PangoAttribute, PangoAttrList, PangoAttrIterator, and the predefined attribute types.
-rw-r--r--pango/break.c36
-rw-r--r--pango/ellipsize.c7
-rw-r--r--pango/itemize.c2
-rw-r--r--pango/meson.build6
-rw-r--r--pango/pango-attr-iterator-private.h (renamed from pango/pango-attributes-private.h)29
-rw-r--r--pango/pango-attr-iterator.c518
-rw-r--r--pango/pango-attr-iterator.h68
-rw-r--r--pango/pango-attr-list-private.h35
-rw-r--r--pango/pango-attr-list.c1285
-rw-r--r--pango/pango-attr-list.h114
-rw-r--r--pango/pango-attr-private.h24
-rw-r--r--pango/pango-attr.c540
-rw-r--r--pango/pango-attr.h214
-rw-r--r--pango/pango-attributes.c2264
-rw-r--r--pango/pango-attributes.h538
-rw-r--r--pango/pango-glyph-item.c7
-rw-r--r--pango/pango-item.h3
-rw-r--r--pango/pango-layout.c23
-rw-r--r--pango/pango-markup.h2
-rw-r--r--pango/pango.h3
-rw-r--r--pango/serializer.c3
21 files changed, 3006 insertions, 2715 deletions
diff --git a/pango/break.c b/pango/break.c
index b31eca13..3d3494f7 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -24,7 +24,9 @@
#include "pango-break.h"
#include "pango-script-private.h"
#include "pango-emoji-private.h"
-#include "pango-attributes-private.h"
+#include "pango-attributes.h"
+#include "pango-attr-list-private.h"
+#include "pango-attr-iterator-private.h"
#include "pango-break-table.h"
#include "pango-impl-utils.h"
#include <string.h>
@@ -1792,7 +1794,7 @@ handle_allow_breaks (const char *text,
PangoAttrIterator iter;
gboolean tailored = FALSE;
- _pango_attr_list_get_iterator (attrs, &iter);
+ pango_attr_list_init_iterator (attrs, &iter);
do
{
@@ -1828,7 +1830,7 @@ handle_allow_breaks (const char *text,
}
while (pango_attr_iterator_next (&iter));
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
return tailored;
}
@@ -1845,7 +1847,7 @@ handle_words (const char *text,
PangoAttrIterator iter;
gboolean tailored = FALSE;
- _pango_attr_list_get_iterator (attrs, &iter);
+ pango_attr_list_init_iterator (attrs, &iter);
do
{
@@ -1934,7 +1936,7 @@ handle_words (const char *text,
}
while (pango_attr_iterator_next (&iter));
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
return tailored;
}
@@ -1950,7 +1952,7 @@ handle_sentences (const char *text,
PangoAttrIterator iter;
gboolean tailored = FALSE;
- _pango_attr_list_get_iterator (attrs, &iter);
+ pango_attr_list_init_iterator (attrs, &iter);
do
{
@@ -2022,7 +2024,7 @@ handle_sentences (const char *text,
}
while (pango_attr_iterator_next (&iter));
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
return tailored;
}
@@ -2038,7 +2040,7 @@ handle_hyphens (const char *text,
PangoAttrIterator iter;
gboolean tailored = FALSE;
- _pango_attr_list_get_iterator (attrs, &iter);
+ pango_attr_list_init_iterator (attrs, &iter);
do {
const PangoAttribute *attr = pango_attr_iterator_get (&iter, PANGO_ATTR_INSERT_HYPHENS);
@@ -2071,7 +2073,7 @@ handle_hyphens (const char *text,
}
} while (pango_attr_iterator_next (&iter));
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
return tailored;
}
@@ -2091,10 +2093,10 @@ break_attrs (const char *text,
GSList *l;
gboolean tailored = FALSE;
- _pango_attr_list_init (&allow_breaks);
- _pango_attr_list_init (&words);
- _pango_attr_list_init (&sentences);
- _pango_attr_list_init (&hyphens);
+ pango_attr_list_init (&allow_breaks);
+ pango_attr_list_init (&words);
+ pango_attr_list_init (&sentences);
+ pango_attr_list_init (&hyphens);
for (l = attributes; l; l = l->next)
{
@@ -2122,10 +2124,10 @@ break_attrs (const char *text,
tailored |= handle_allow_breaks (text, length, &allow_breaks, offset,
log_attrs, log_attrs_len);
- _pango_attr_list_destroy (&allow_breaks);
- _pango_attr_list_destroy (&words);
- _pango_attr_list_destroy (&sentences);
- _pango_attr_list_destroy (&hyphens);
+ pango_attr_list_destroy (&allow_breaks);
+ pango_attr_list_destroy (&words);
+ pango_attr_list_destroy (&sentences);
+ pango_attr_list_destroy (&hyphens);
return tailored;
}
diff --git a/pango/ellipsize.c b/pango/ellipsize.c
index 13edd5a0..60567259 100644
--- a/pango/ellipsize.c
+++ b/pango/ellipsize.c
@@ -25,7 +25,8 @@
#include "pango-glyph-item.h"
#include "pango-layout-private.h"
#include "pango-font-private.h"
-#include "pango-attributes-private.h"
+#include "pango-attr-list-private.h"
+#include "pango-attr-iterator-private.h"
#include "pango-impl-utils.h"
typedef struct _EllipsizeState EllipsizeState;
@@ -310,7 +311,7 @@ shape_ellipsis (EllipsizeState *state)
int len;
int i;
- _pango_attr_list_init (&attrs);
+ pango_attr_list_init (&attrs);
/* Create/reset state->ellipsis_run
*/
@@ -370,7 +371,7 @@ shape_ellipsis (EllipsizeState *state)
item = itemize_text (state, ellipsis_text, &attrs);
}
- _pango_attr_list_destroy (&attrs);
+ pango_attr_list_destroy (&attrs);
state->ellipsis_run->item = item;
diff --git a/pango/itemize.c b/pango/itemize.c
index dab6eb7e..ad30460f 100644
--- a/pango/itemize.c
+++ b/pango/itemize.c
@@ -31,7 +31,7 @@
#include "pango-fontmap-private.h"
#include "pango-script-private.h"
#include "pango-emoji-private.h"
-#include "pango-attributes-private.h"
+#include "pango-attr-iterator-private.h"
#include "pango-item-private.h"
#include <hb-ot.h>
diff --git a/pango/meson.build b/pango/meson.build
index 5cf392ac..efaebfe6 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -5,6 +5,9 @@ pango_sources = [
'glyphstring.c',
'itemize.c',
'modules.c',
+ 'pango-attr.c',
+ 'pango-attr-list.c',
+ 'pango-attr-iterator.c',
'pango-attributes.c',
'pango-bidi-type.c',
'pango-color.c',
@@ -45,6 +48,9 @@ pango_sources = [
pango_headers = [
'pango.h',
+ 'pango-attr.h',
+ 'pango-attr-list.h',
+ 'pango-attr-iterator.h',
'pango-attributes.h',
'pango-bidi-type.h',
'pango-break.h',
diff --git a/pango/pango-attributes-private.h b/pango/pango-attr-iterator-private.h
index b4c5b671..b229cbad 100644
--- a/pango/pango-attributes-private.h
+++ b/pango/pango-attr-iterator-private.h
@@ -17,8 +17,9 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef __PANGO_ATTRIBUTES_PRIVATE_H__
-#define __PANGO_ATTRIBUTES_PRIVATE_H__
+#pragma once
+
+#include <pango/pango-attr-iterator.h>
struct _PangoAttrIterator
{
@@ -32,24 +33,6 @@ struct _PangoAttrIterator
guint end_index;
};
-struct _PangoAttrList
-{
- guint ref_count;
- GPtrArray *attributes;
-};
-
-char * pango_attr_value_serialize (PangoAttribute *attr);
-void _pango_attr_list_init (PangoAttrList *list);
-void _pango_attr_list_destroy (PangoAttrList *list);
-gboolean _pango_attr_list_has_attributes (const PangoAttrList *list);
-
-void _pango_attr_list_get_iterator (PangoAttrList *list,
- PangoAttrIterator *iterator);
-
-void _pango_attr_iterator_destroy (PangoAttrIterator *iterator);
-gboolean pango_attr_iterator_advance (PangoAttrIterator *iterator,
- int index);
-
-
-#endif
-
+void pango_attr_iterator_clear (PangoAttrIterator *iterator);
+gboolean pango_attr_iterator_advance (PangoAttrIterator *iterator,
+ int index);
diff --git a/pango/pango-attr-iterator.c b/pango/pango-attr-iterator.c
new file mode 100644
index 00000000..e940d5a1
--- /dev/null
+++ b/pango/pango-attr-iterator.c
@@ -0,0 +1,518 @@
+/* Pango
+ * pango-attr-iterator.c: Attribute iterator
+ *
+ * Copyright (C) 2000-2002 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 <string.h>
+
+#include "pango-attr-iterator-private.h"
+#include "pango-attr-list-private.h"
+#include "pango-attr-private.h"
+#include "pango-impl-utils.h"
+
+
+G_DEFINE_BOXED_TYPE (PangoAttrIterator,
+ pango_attr_iterator,
+ pango_attr_iterator_copy,
+ pango_attr_iterator_destroy)
+
+/* {{{ Private API */
+
+void
+pango_attr_list_init_iterator (PangoAttrList *list,
+ PangoAttrIterator *iterator)
+{
+ iterator->attribute_stack = NULL;
+ iterator->attrs = list->attributes;
+ iterator->n_attrs = iterator->attrs ? iterator->attrs->len : 0;
+
+ iterator->attr_index = 0;
+ iterator->start_index = 0;
+ iterator->end_index = 0;
+
+ if (!pango_attr_iterator_next (iterator))
+ iterator->end_index = G_MAXUINT;
+}
+
+void
+pango_attr_iterator_clear (PangoAttrIterator *iterator)
+{
+ if (iterator->attribute_stack)
+ g_ptr_array_free (iterator->attribute_stack, TRUE);
+}
+
+gboolean
+pango_attr_iterator_advance (PangoAttrIterator *iterator,
+ int index)
+{
+ int start_range, end_range;
+
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
+
+ while (index >= end_range)
+ {
+ if (!pango_attr_iterator_next (iterator))
+ return FALSE;
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
+ }
+
+ if (start_range > index)
+ g_warning ("pango_attr_iterator_advance(): iterator had already "
+ "moved beyond the index");
+
+ return TRUE;
+}
+
+/* }}} */
+/* {{{ Public API */
+
+/**
+ * pango_attr_list_get_iterator:
+ * @list: a `PangoAttrList`
+ *
+ * Create a iterator initialized to the beginning of the list.
+ *
+ * @list must not be modified until this iterator is freed.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttrIterator`, which should be freed with
+ * [method@Pango.AttrIterator.destroy]
+ */
+PangoAttrIterator *
+pango_attr_list_get_iterator (PangoAttrList *list)
+{
+ PangoAttrIterator *iterator;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ iterator = g_slice_new (PangoAttrIterator);
+ pango_attr_list_init_iterator (list, iterator);
+
+ return iterator;
+}
+
+/**
+ * pango_attr_iterator_destroy:
+ * @iterator: a `PangoAttrIterator`
+ *
+ * Destroy a `PangoAttrIterator` and free all associated memory.
+ */
+void
+pango_attr_iterator_destroy (PangoAttrIterator *iterator)
+{
+ g_return_if_fail (iterator != NULL);
+
+ pango_attr_iterator_clear (iterator);
+ g_slice_free (PangoAttrIterator, iterator);
+}
+
+/**
+ * pango_attr_iterator_copy:
+ * @iterator: a `PangoAttrIterator`
+ *
+ * Copy a `PangoAttrIterator`.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttrIterator`, which should be freed with
+ * [method@Pango.AttrIterator.destroy]
+ */
+PangoAttrIterator *
+pango_attr_iterator_copy (PangoAttrIterator *iterator)
+{
+ PangoAttrIterator *copy;
+
+ g_return_val_if_fail (iterator != NULL, NULL);
+
+ copy = g_slice_new (PangoAttrIterator);
+
+ *copy = *iterator;
+
+ if (iterator->attribute_stack)
+ copy->attribute_stack = g_ptr_array_copy (iterator->attribute_stack, NULL, NULL);
+ else
+ copy->attribute_stack = NULL;
+
+ return copy;
+}
+
+/**
+ * pango_attr_iterator_range:
+ * @iterator: a PangoAttrIterator
+ * @start: (out): location to store the start of the range
+ * @end: (out): location to store the end of the range
+ *
+ * Get the range of the current segment.
+ *
+ * Note that the stored return values are signed, not unsigned
+ * like the values in `PangoAttribute`. To deal with this API
+ * oversight, stored return values that wouldn't fit into
+ * a signed integer are clamped to %G_MAXINT.
+ */
+void
+pango_attr_iterator_range (PangoAttrIterator *iterator,
+ gint *start,
+ gint *end)
+{
+ g_return_if_fail (iterator != NULL);
+
+ if (start)
+ *start = MIN (iterator->start_index, G_MAXINT);
+ if (end)
+ *end = MIN (iterator->end_index, G_MAXINT);
+}
+
+/**
+ * pango_attr_iterator_next:
+ * @iterator: a `PangoAttrIterator`
+ *
+ * Advance the iterator until the next change of style.
+ *
+ * Return value: %FALSE if the iterator is at the end
+ * of the list, otherwise %TRUE
+ */
+gboolean
+pango_attr_iterator_next (PangoAttrIterator *iterator)
+{
+ int i;
+
+ g_return_val_if_fail (iterator != NULL, FALSE);
+
+ if (iterator->attr_index >= iterator->n_attrs &&
+ (!iterator->attribute_stack || iterator->attribute_stack->len == 0))
+ return FALSE;
+
+ iterator->start_index = iterator->end_index;
+ iterator->end_index = G_MAXUINT;
+
+ if (iterator->attribute_stack)
+ {
+ for (i = iterator->attribute_stack->len - 1; i>= 0; i--)
+ {
+ const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
+
+ if (attr->end_index == iterator->start_index)
+ g_ptr_array_remove_index (iterator->attribute_stack, i); /* Can't use index_fast :( */
+ else
+ iterator->end_index = MIN (iterator->end_index, attr->end_index);
+ }
+ }
+
+ while (1)
+ {
+ PangoAttribute *attr;
+
+ if (iterator->attr_index >= iterator->n_attrs)
+ break;
+
+ attr = g_ptr_array_index (iterator->attrs, iterator->attr_index);
+
+ if (attr->start_index != iterator->start_index)
+ break;
+
+ if (attr->end_index > iterator->start_index)
+ {
+ if (G_UNLIKELY (!iterator->attribute_stack))
+ iterator->attribute_stack = g_ptr_array_new ();
+
+ g_ptr_array_add (iterator->attribute_stack, attr);
+
+ iterator->end_index = MIN (iterator->end_index, attr->end_index);
+ }
+
+ iterator->attr_index++; /* NEXT! */
+ }
+
+ if (iterator->attr_index < iterator->n_attrs)
+ {
+ PangoAttribute *attr = g_ptr_array_index (iterator->attrs, iterator->attr_index);
+
+ iterator->end_index = MIN (iterator->end_index, attr->start_index);
+ }
+
+ return TRUE;
+}
+
+/**
+ * pango_attr_iterator_get:
+ * @iterator: a `PangoAttrIterator`
+ * @type: the type of attribute to find
+ *
+ * Find the current attribute of a particular type
+ * at the iterator location.
+ *
+ * When multiple attributes of the same type overlap,
+ * the attribute whose range starts closest to the
+ * current location is used.
+ *
+ * Return value: (nullable) (transfer none): the current
+ * attribute of the given type, or %NULL if no attribute
+ * of that type applies to the current location.
+ */
+PangoAttribute *
+pango_attr_iterator_get (PangoAttrIterator *iterator,
+ guint type)
+{
+ int i;
+
+ g_return_val_if_fail (iterator != NULL, NULL);
+
+ if (!iterator->attribute_stack)
+ return NULL;
+
+ for (i = iterator->attribute_stack->len - 1; i>= 0; i--)
+ {
+ PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
+
+ if (attr->type == type)
+ return attr;
+ }
+
+ return NULL;
+}
+
+/**
+ * pango_attr_iterator_get_font:
+ * @iterator: a `PangoAttrIterator`
+ * @desc: (out caller-allocates): a `PangoFontDescription` to fill in with the current
+ * values. The family name in this structure will be set using
+ * [method@Pango.FontDescription.set_family_static] using
+ * values from an attribute in the `PangoAttrList` associated
+ * with the iterator, so if you plan to keep it around, you
+ * must call:
+ * `pango_font_description_set_family (desc, pango_font_description_get_family (desc))`.
+ * @language: (out) (optional): location to store language tag
+ * for item, or %NULL if none is found.
+ * @extra_attrs: (out) (optional) (element-type Pango.Attribute) (transfer full):
+ * location in which to store a list of non-font attributes
+ * at the the current position; only the highest priority
+ * value of each attribute will be added to this list. In
+ * order to free this value, you must call
+ * [method@Pango.Attribute.destroy] on each member.
+ *
+ * Get the font and other attributes at the current
+ * iterator position.
+ */
+void
+pango_attr_iterator_get_font (PangoAttrIterator *iterator,
+ PangoFontDescription *desc,
+ PangoLanguage **language,
+ GSList **extra_attrs)
+{
+ PangoFontMask mask = 0;
+ gboolean have_language = FALSE;
+ gdouble scale = 0;
+ gboolean have_scale = FALSE;
+ int i;
+
+ g_return_if_fail (iterator != NULL);
+ g_return_if_fail (desc != NULL);
+
+ if (language)
+ *language = NULL;
+
+ if (extra_attrs)
+ *extra_attrs = NULL;
+
+ if (!iterator->attribute_stack)
+ return;
+
+ for (i = iterator->attribute_stack->len - 1; i >= 0; i--)
+ {
+ const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
+
+ switch ((int) attr->type)
+ {
+ case PANGO_ATTR_FONT_DESC:
+ {
+ PangoFontMask new_mask = pango_font_description_get_set_fields (attr->font_value) & ~mask;
+ mask |= new_mask;
+ pango_font_description_unset_fields (desc, new_mask);
+ pango_font_description_merge_static (desc, attr->font_value, FALSE);
+
+ break;
+ }
+ case PANGO_ATTR_FAMILY:
+ if (!(mask & PANGO_FONT_MASK_FAMILY))
+ {
+ mask |= PANGO_FONT_MASK_FAMILY;
+ pango_font_description_set_family (desc, attr->str_value);
+ }
+ break;
+ case PANGO_ATTR_STYLE:
+ if (!(mask & PANGO_FONT_MASK_STYLE))
+ {
+ mask |= PANGO_FONT_MASK_STYLE;
+ pango_font_description_set_style (desc, attr->int_value);
+ }
+ break;
+ case PANGO_ATTR_VARIANT:
+ if (!(mask & PANGO_FONT_MASK_VARIANT))
+ {
+ mask |= PANGO_FONT_MASK_VARIANT;
+ pango_font_description_set_variant (desc, attr->int_value);
+ }
+ break;
+ case PANGO_ATTR_WEIGHT:
+ if (!(mask & PANGO_FONT_MASK_WEIGHT))
+ {
+ mask |= PANGO_FONT_MASK_WEIGHT;
+ pango_font_description_set_weight (desc, attr->int_value);
+ }
+ break;
+ case PANGO_ATTR_STRETCH:
+ if (!(mask & PANGO_FONT_MASK_STRETCH))
+ {
+ mask |= PANGO_FONT_MASK_STRETCH;
+ pango_font_description_set_stretch (desc, attr->int_value);
+ }
+ break;
+ case PANGO_ATTR_SIZE:
+ if (!(mask & PANGO_FONT_MASK_SIZE))
+ {
+ mask |= PANGO_FONT_MASK_SIZE;
+ pango_font_description_set_size (desc, attr->int_value);
+ }
+ break;
+ case PANGO_ATTR_ABSOLUTE_SIZE:
+ if (!(mask & PANGO_FONT_MASK_SIZE))
+ {
+ mask |= PANGO_FONT_MASK_SIZE;
+ pango_font_description_set_absolute_size (desc, attr->int_value);
+ }
+ break;
+ case PANGO_ATTR_SCALE:
+ if (!have_scale)
+ {
+ have_scale = TRUE;
+ scale = attr->double_value;
+ }
+ break;
+ case PANGO_ATTR_LANGUAGE:
+ if (language)
+ {
+ if (!have_language)
+ {
+ have_language = TRUE;
+ *language = attr->lang_value;
+ }
+ }
+ break;
+ default:
+ if (extra_attrs)
+ {
+ gboolean found = FALSE;
+
+ /* Hack: special-case FONT_FEATURES, BASELINE_SHIFT and FONT_SCALE.
+ * We don't want these to accumulate, not override each other,
+ * so we never merge them.
+ * This needs to be handled more systematically.
+ */
+ if (attr->type != PANGO_ATTR_FONT_FEATURES &&
+ attr->type != PANGO_ATTR_BASELINE_SHIFT &&
+ attr->type != PANGO_ATTR_FONT_SCALE)
+ {
+ GSList *tmp_list = *extra_attrs;
+ while (tmp_list)
+ {
+ PangoAttribute *old_attr = tmp_list->data;
+ if (attr->type == old_attr->type)
+ {
+ found = TRUE;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+ }
+
+ if (!found)
+ *extra_attrs = g_slist_prepend (*extra_attrs, pango_attribute_copy (attr));
+ }
+ }
+ }
+
+ if (have_scale)
+ {
+ /* We need to use a local variable to ensure that the compiler won't
+ * implicitly cast it to integer while the result is kept in registers,
+ * leading to a wrong approximation in i386 (with 387 FPU)
+ */
+ volatile double size = scale * pango_font_description_get_size (desc);
+
+ if (pango_font_description_get_size_is_absolute (desc))
+ pango_font_description_set_absolute_size (desc, size);
+ else
+ pango_font_description_set_size (desc, size);
+ }
+}
+
+/**
+ * pango_attr_iterator_get_attrs:
+ * @iterator: a `PangoAttrIterator`
+ *
+ * Gets a list of all attributes at the current position of the
+ * iterator.
+ *
+ * Return value: (element-type Pango.Attribute) (transfer full):
+ * a list of all attributes for the current range. To free
+ * this value, call [method@Pango.Attribute.destroy] on each
+ * value and g_slist_free() on the list.
+ *
+ * Since: 1.2
+ */
+GSList *
+pango_attr_iterator_get_attrs (PangoAttrIterator *iterator)
+{
+ GSList *attrs = NULL;
+ int i;
+
+ if (!iterator->attribute_stack ||
+ iterator->attribute_stack->len == 0)
+ return NULL;
+
+ for (i = iterator->attribute_stack->len - 1; i >= 0; i--)
+ {
+ PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
+ GSList *tmp_list2;
+ gboolean found = FALSE;
+
+ if (attr->type != PANGO_ATTR_FONT_DESC &&
+ attr->type != PANGO_ATTR_BASELINE_SHIFT &&
+ attr->type != PANGO_ATTR_FONT_SCALE)
+ for (tmp_list2 = attrs; tmp_list2; tmp_list2 = tmp_list2->next)
+ {
+ PangoAttribute *old_attr = tmp_list2->data;
+ if (attr->type == old_attr->type)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ attrs = g_slist_prepend (attrs, pango_attribute_copy (attr));
+ }
+
+ return attrs;
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-attr-iterator.h b/pango/pango-attr-iterator.h
new file mode 100644
index 00000000..d805cb92
--- /dev/null
+++ b/pango/pango-attr-iterator.h
@@ -0,0 +1,68 @@
+/* Pango
+ * pango-attr-list.h: Attribute lists
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-attr-list.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+
+/**
+ * PangoAttrIterator:
+ *
+ * A `PangoAttrIterator` is used to iterate through a `PangoAttrList`.
+ *
+ * A new iterator is created with [method@Pango.AttrList.get_iterator].
+ * Once the iterator is created, it can be advanced through the style
+ * changes in the text using [method@Pango.AttrIterator.next]. At each
+ * style change, the range of the current style segment and the attributes
+ * currently in effect can be queried.
+ */
+
+PANGO_AVAILABLE_IN_1_44
+GType pango_attr_iterator_get_type (void) G_GNUC_CONST;
+
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_iterator_range (PangoAttrIterator *iterator,
+ int *start,
+ int *end);
+PANGO_AVAILABLE_IN_ALL
+gboolean pango_attr_iterator_next (PangoAttrIterator *iterator);
+PANGO_AVAILABLE_IN_ALL
+PangoAttrIterator * pango_attr_iterator_copy (PangoAttrIterator *iterator);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_iterator_destroy (PangoAttrIterator *iterator);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_iterator_get (PangoAttrIterator *iterator,
+ guint type);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_iterator_get_font (PangoAttrIterator *iterator,
+ PangoFontDescription *desc,
+ PangoLanguage **language,
+ GSList **extra_attrs);
+PANGO_AVAILABLE_IN_1_2
+GSList * pango_attr_iterator_get_attrs (PangoAttrIterator *iterator);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttrIterator, pango_attr_iterator_destroy)
+
+G_END_DECLS
diff --git a/pango/pango-attr-list-private.h b/pango/pango-attr-list-private.h
new file mode 100644
index 00000000..fcd9e0f6
--- /dev/null
+++ b/pango/pango-attr-list-private.h
@@ -0,0 +1,35 @@
+/* Pango
+ * pango-attributes-private.h: Internal structures of PangoLayout
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-attr-list.h>
+
+struct _PangoAttrList
+{
+ guint ref_count;
+ GPtrArray *attributes;
+};
+
+void pango_attr_list_init (PangoAttrList *list);
+void pango_attr_list_destroy (PangoAttrList *list);
+gboolean pango_attr_list_has_attributes (const PangoAttrList *list);
+
+void pango_attr_list_init_iterator (PangoAttrList *list,
+ PangoAttrIterator *iterator);
diff --git a/pango/pango-attr-list.c b/pango/pango-attr-list.c
new file mode 100644
index 00000000..2615ddf1
--- /dev/null
+++ b/pango/pango-attr-list.c
@@ -0,0 +1,1285 @@
+/* Pango
+ * pango-attr-list.c: Attribute lists
+ *
+ * Copyright (C) 2000-2002 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 <string.h>
+
+#include "pango-attr-list-private.h"
+#include "pango-attr-private.h"
+#include "pango-impl-utils.h"
+
+
+G_DEFINE_BOXED_TYPE (PangoAttrList, pango_attr_list,
+ pango_attr_list_copy,
+ pango_attr_list_unref);
+
+/* {{{ Utilities */
+
+static void
+pango_attr_list_insert_internal (PangoAttrList *list,
+ PangoAttribute *attr,
+ gboolean before)
+{
+ const guint start_index = attr->start_index;
+ PangoAttribute *last_attr;
+
+ if (G_UNLIKELY (!list->attributes))
+ list->attributes = g_ptr_array_new ();
+
+ if (list->attributes->len == 0)
+ {
+ g_ptr_array_add (list->attributes, attr);
+ return;
+ }
+
+ g_assert (list->attributes->len > 0);
+
+ last_attr = g_ptr_array_index (list->attributes, list->attributes->len - 1);
+
+ if (last_attr->start_index < start_index ||
+ (!before && last_attr->start_index == start_index))
+ {
+ g_ptr_array_add (list->attributes, attr);
+ }
+ else
+ {
+ guint i, p;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *cur = g_ptr_array_index (list->attributes, i);
+
+ if (cur->start_index > start_index ||
+ (before && cur->start_index == start_index))
+ {
+ g_ptr_array_insert (list->attributes, i, attr);
+ break;
+ }
+ }
+ }
+}
+
+/* }}} */
+/* {{{ Private API */
+
+void
+pango_attr_list_init (PangoAttrList *list)
+{
+ list->ref_count = 1;
+ list->attributes = NULL;
+}
+
+void
+pango_attr_list_destroy (PangoAttrList *list)
+{
+ if (!list->attributes)
+ return;
+
+ g_ptr_array_free (list->attributes, TRUE);
+}
+
+gboolean
+pango_attr_list_has_attributes (const PangoAttrList *list)
+{
+ return list && list->attributes != NULL && list->attributes->len > 0;
+}
+
+/* }}} */
+/* {{{ Public API */
+
+/**
+ * pango_attr_list_new:
+ *
+ * Create a new empty attribute list with a reference
+ * count of one.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttrList`, which should be freed with
+ * [method@Pango.AttrList.unref]
+ */
+PangoAttrList *
+pango_attr_list_new (void)
+{
+ PangoAttrList *list = g_slice_new (PangoAttrList);
+
+ pango_attr_list_init (list);
+
+ return list;
+}
+
+/**
+ * pango_attr_list_ref:
+ * @list: (nullable): a `PangoAttrList`
+ *
+ * Increase the reference count of the given attribute
+ * list by one.
+ *
+ * Return value: The attribute list passed in
+ *
+ * Since: 1.10
+ */
+PangoAttrList *
+pango_attr_list_ref (PangoAttrList *list)
+{
+ if (list == NULL)
+ return NULL;
+
+ g_atomic_int_inc ((int *) &list->ref_count);
+
+ return list;
+}
+
+/**
+ * pango_attr_list_unref:
+ * @list: (nullable): a `PangoAttrList`
+ *
+ * Decrease the reference count of the given attribute
+ * list by one.
+ *
+ * If the result is zero, free the attribute list
+ * and the attributes it contains.
+ */
+void
+pango_attr_list_unref (PangoAttrList *list)
+{
+ if (list == NULL)
+ return;
+
+ g_return_if_fail (list->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test ((int *) &list->ref_count))
+ {
+ pango_attr_list_destroy (list);
+ g_slice_free (PangoAttrList, list);
+ }
+}
+
+/**
+ * pango_attr_list_copy:
+ * @list: (nullable): a `PangoAttrList`
+ *
+ * Copy @list and return an identical new list.
+ *
+ * Return value: (nullable): the newly allocated
+ * `PangoAttrList`, with a reference count of one,
+ * which should be freed with [method@Pango.AttrList.unref].
+ * Returns %NULL if @list was %NULL.
+ */
+PangoAttrList *
+pango_attr_list_copy (PangoAttrList *list)
+{
+ PangoAttrList *new;
+
+ if (list == NULL)
+ return NULL;
+
+ new = pango_attr_list_new ();
+ if (!list->attributes || list->attributes->len == 0)
+ return new;
+
+ new->attributes = g_ptr_array_copy (list->attributes, (GCopyFunc)pango_attribute_copy, NULL);
+
+ return new;
+}
+
+/**
+ * pango_attr_list_insert:
+ * @list: a `PangoAttrList`
+ * @attr: (transfer full): the attribute to insert
+ *
+ * Insert the given attribute into the `PangoAttrList`.
+ *
+ * It will be inserted after all other attributes with a
+ * matching @start_index.
+ */
+void
+pango_attr_list_insert (PangoAttrList *list,
+ PangoAttribute *attr)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (attr != NULL);
+
+ pango_attr_list_insert_internal (list, attr, FALSE);
+}
+
+/**
+ * pango_attr_list_insert_before:
+ * @list: a `PangoAttrList`
+ * @attr: (transfer full): the attribute to insert
+ *
+ * Insert the given attribute into the `PangoAttrList`.
+ *
+ * It will be inserted before all other attributes with a
+ * matching @start_index.
+ */
+void
+pango_attr_list_insert_before (PangoAttrList *list,
+ PangoAttribute *attr)
+{
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (attr != NULL);
+
+ pango_attr_list_insert_internal (list, attr, TRUE);
+}
+
+/**
+ * pango_attr_list_change:
+ * @list: a `PangoAttrList`
+ * @attr: (transfer full): the attribute to insert
+ *
+ * Insert the given attribute into the `PangoAttrList`.
+ *
+ * It will replace any attributes of the same type
+ * on that segment and be merged with any adjoining
+ * attributes that are identical.
+ *
+ * This function is slower than [method@Pango.AttrList.insert]
+ * for creating an attribute list in order (potentially
+ * much slower for large lists). However,
+ * [method@Pango.AttrList.insert] is not suitable for
+ * continually changing a set of attributes since it
+ * never removes or combines existing attributes.
+ */
+void
+pango_attr_list_change (PangoAttrList *list,
+ PangoAttribute *attr)
+{
+ guint i, p;
+ guint start_index = attr->start_index;
+ guint end_index = attr->end_index;
+ gboolean inserted;
+
+ g_return_if_fail (list != NULL);
+
+ if (start_index == end_index) /* empty, nothing to do */
+ {
+ pango_attribute_destroy (attr);
+ return;
+ }
+
+ if (!list->attributes || list->attributes->len == 0)
+ {
+ pango_attr_list_insert (list, attr);
+ return;
+ }
+
+ inserted = FALSE;
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
+
+ if (tmp_attr->start_index > start_index)
+ {
+ g_ptr_array_insert (list->attributes, i, attr);
+ inserted = TRUE;
+ break;
+ }
+
+ if (tmp_attr->type != attr->type)
+ continue;
+
+ if (tmp_attr->end_index < start_index)
+ continue; /* This attr does not overlap with the new one */
+
+ g_assert (tmp_attr->start_index <= start_index);
+ g_assert (tmp_attr->end_index >= start_index);
+
+ if (pango_attribute_equal (tmp_attr, attr))
+ {
+ /* We can merge the new attribute with this attribute
+ */
+ if (tmp_attr->end_index >= end_index)
+ {
+ /* We are totally overlapping the previous attribute.
+ * No action is needed.
+ */
+ pango_attribute_destroy (attr);
+ return;
+ }
+
+ tmp_attr->end_index = end_index;
+ pango_attribute_destroy (attr);
+
+ attr = tmp_attr;
+ inserted = TRUE;
+ break;
+ }
+ else
+ {
+ /* Split, truncate, or remove the old attribute
+ */
+ if (tmp_attr->end_index > end_index)
+ {
+ PangoAttribute *end_attr = pango_attribute_copy (tmp_attr);
+
+ end_attr->start_index = end_index;
+ pango_attr_list_insert (list, end_attr);
+ }
+
+ if (tmp_attr->start_index == start_index)
+ {
+ pango_attribute_destroy (tmp_attr);
+ g_ptr_array_remove_index (list->attributes, i);
+ break;
+ }
+ else
+ {
+ tmp_attr->end_index = start_index;
+ }
+ }
+ }
+
+ if (!inserted)
+ /* we didn't insert attr yet */
+ pango_attr_list_insert (list, attr);
+
+ /* We now have the range inserted into the list one way or the
+ * other. Fix up the remainder
+ */
+ /* Attention: No i = 0 here. */
+ for (i = i + 1, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
+
+ if (tmp_attr->start_index > end_index)
+ break;
+
+ if (tmp_attr->type != attr->type)
+ continue;
+
+ if (tmp_attr->end_index <= attr->end_index ||
+ pango_attribute_equal (tmp_attr, attr))
+ {
+ /* We can merge the new attribute with this attribute. */
+ attr->end_index = MAX (end_index, tmp_attr->end_index);
+ pango_attribute_destroy (tmp_attr);
+ g_ptr_array_remove_index (list->attributes, i);
+ i--;
+ p--;
+ continue;
+ }
+ else
+ {
+ /* Trim the start of this attribute that it begins at the end
+ * of the new attribute. This may involve moving it in the list
+ * to maintain the required non-decreasing order of start indices.
+ */
+ int k, m;
+
+ tmp_attr->start_index = attr->end_index;
+
+ for (k = i + 1, m = list->attributes->len; k < m; k++)
+ {
+ PangoAttribute *tmp_attr2 = g_ptr_array_index (list->attributes, k);
+
+ if (tmp_attr2->start_index >= tmp_attr->start_index)
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * pango_attr_list_update:
+ * @list: a `PangoAttrList`
+ * @pos: the position of the change
+ * @remove: the number of removed bytes
+ * @add: the number of added bytes
+ *
+ * Update indices of attributes in @list for a change in the
+ * text they refer to.
+ *
+ * The change that this function applies is removing @remove
+ * bytes at position @pos and inserting @add bytes instead.
+ *
+ * Attributes that fall entirely in the (@pos, @pos + @remove)
+ * range are removed.
+ *
+ * Attributes that start or end inside the (@pos, @pos + @remove)
+ * range are shortened to reflect the removal.
+ *
+ * Attributes start and end positions are updated if they are
+ * behind @pos + @remove.
+ *
+ * Since: 1.44
+ */
+void
+pango_attr_list_update (PangoAttrList *list,
+ int pos,
+ int remove,
+ int add)
+{
+ guint i, p;
+
+ g_return_if_fail (pos >= 0);
+ g_return_if_fail (remove >= 0);
+ g_return_if_fail (add >= 0);
+
+ if (list->attributes)
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
+
+ if (attr->start_index >= pos &&
+ attr->end_index < pos + remove)
+ {
+ pango_attribute_destroy (attr);
+ g_ptr_array_remove_index (list->attributes, i);
+ i--; /* Look at this index again */
+ p--;
+ continue;
+ }
+
+ if (attr->start_index != PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING)
+ {
+ if (attr->start_index >= pos &&
+ attr->start_index < pos + remove)
+ {
+ attr->start_index = pos + add;
+ }
+ else if (attr->start_index >= pos + remove)
+ {
+ attr->start_index += add - remove;
+ }
+ }
+
+ if (attr->end_index != PANGO_ATTR_INDEX_TO_TEXT_END)
+ {
+ if (attr->end_index >= pos &&
+ attr->end_index < pos + remove)
+ {
+ attr->end_index = pos;
+ }
+ else if (attr->end_index >= pos + remove)
+ {
+ if (add > remove &&
+ G_MAXUINT - attr->end_index < add - remove)
+ attr->end_index = G_MAXUINT;
+ else
+ attr->end_index += add - remove;
+ }
+ }
+ }
+}
+
+/**
+ * pango_attr_list_splice:
+ * @list: a `PangoAttrList`
+ * @other: another `PangoAttrList`
+ * @pos: the position in @list at which to insert @other
+ * @len: the length of the spliced segment. (Note that this
+ * must be specified since the attributes in @other may only
+ * be present at some subsection of this range)
+ *
+ * This function opens up a hole in @list, fills it
+ * in with attributes from the left, and then merges
+ * @other on top of the hole.
+ *
+ * This operation is equivalent to stretching every attribute
+ * that applies at position @pos in @list by an amount @len,
+ * and then calling [method@Pango.AttrList.change] with a copy
+ * of each attribute in @other in sequence (offset in position
+ * by @pos, and limited in length to @len).
+ *
+ * This operation proves useful for, for instance, inserting
+ * a pre-edit string in the middle of an edit buffer.
+ *
+ * For backwards compatibility, the function behaves differently
+ * when @len is 0. In this case, the attributes from @other are
+ * not imited to @len, and are just overlayed on top of @list.
+ *
+ * This mode is useful for merging two lists of attributes together.
+ */
+void
+pango_attr_list_splice (PangoAttrList *list,
+ PangoAttrList *other,
+ gint pos,
+ gint len)
+{
+ guint i, p;
+ guint upos, ulen;
+ guint end;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (other != NULL);
+ g_return_if_fail (pos >= 0);
+ g_return_if_fail (len >= 0);
+
+ upos = (guint)pos;
+ ulen = (guint)len;
+
+/* This definition only works when a and b are unsigned; overflow
+ * isn't defined in the C standard for signed integers
+ */
+#define CLAMP_ADD(a,b) (((a) + (b) < (a)) ? G_MAXUINT : (a) + (b))
+
+ end = CLAMP_ADD (upos, ulen);
+
+ if (list->attributes)
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);;
+
+ if (attr->start_index <= upos)
+ {
+ if (attr->end_index > upos)
+ attr->end_index = CLAMP_ADD (attr->end_index, ulen);
+ }
+ else
+ {
+ /* This could result in a zero length attribute if it
+ * gets squashed up against G_MAXUINT, but deleting such
+ * an element could (in theory) suprise the caller, so
+ * we don't delete it.
+ */
+ attr->start_index = CLAMP_ADD (attr->start_index, ulen);
+ attr->end_index = CLAMP_ADD (attr->end_index, ulen);
+ }
+ }
+
+ if (!other->attributes || other->attributes->len == 0)
+ return;
+
+ for (i = 0, p = other->attributes->len; i < p; i++)
+ {
+ PangoAttribute *attr = pango_attribute_copy (g_ptr_array_index (other->attributes, i));
+ if (ulen > 0)
+ {
+ attr->start_index = MIN (CLAMP_ADD (attr->start_index, upos), end);
+ attr->end_index = MIN (CLAMP_ADD (attr->end_index, upos), end);
+ }
+ else
+ {
+ attr->start_index = CLAMP_ADD (attr->start_index, upos);
+ attr->end_index = CLAMP_ADD (attr->end_index, upos);
+ }
+
+ /* Same as above, the attribute could be squashed to zero-length; here
+ * pango_attr_list_change() will take care of deleting it.
+ */
+ pango_attr_list_change (list, attr);
+ }
+#undef CLAMP_ADD
+}
+
+/**
+ * pango_attr_list_get_attributes:
+ * @list: a `PangoAttrList`
+ *
+ * Gets a list of all attributes in @list.
+ *
+ * Return value: (element-type Pango.Attribute) (transfer full):
+ * a list of all attributes in @list. To free this value,
+ * call [method@Pango.Attribute.destroy] on each value and
+ * g_slist_free() on the list.
+ *
+ * Since: 1.44
+ */
+GSList *
+pango_attr_list_get_attributes (PangoAttrList *list)
+{
+ GSList *result = NULL;
+ guint i, p;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ if (!list->attributes || list->attributes->len == 0)
+ return NULL;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
+
+ result = g_slist_prepend (result, pango_attribute_copy (attr));
+ }
+
+ return g_slist_reverse (result);
+}
+
+/**
+ * pango_attr_list_equal:
+ * @list: a `PangoAttrList`
+ * @other_list: the other `PangoAttrList`
+ *
+ * Checks whether @list and @other_list contain the same
+ * attributes and whether those attributes apply to the
+ * same ranges.
+ *
+ * Beware that this will return wrong values if any list
+ * contains duplicates.
+ *
+ * Return value: %TRUE if the lists are equal, %FALSE if
+ * they aren't
+ *
+ * Since: 1.46
+ */
+gboolean
+pango_attr_list_equal (PangoAttrList *list,
+ PangoAttrList *other_list)
+{
+ GPtrArray *attrs, *other_attrs;
+ guint64 skip_bitmask = 0;
+ guint i;
+
+ if (list == other_list)
+ return TRUE;
+
+ if (list == NULL || other_list == NULL)
+ return FALSE;
+
+ if (list->attributes == NULL || other_list->attributes == NULL)
+ return list->attributes == other_list->attributes;
+
+ attrs = list->attributes;
+ other_attrs = other_list->attributes;
+
+ if (attrs->len != other_attrs->len)
+ return FALSE;
+
+ for (i = 0; i < attrs->len; i++)
+ {
+ PangoAttribute *attr = g_ptr_array_index (attrs, i);
+ gboolean attr_equal = FALSE;
+ guint other_attr_index;
+
+ for (other_attr_index = 0; other_attr_index < other_attrs->len; other_attr_index++)
+ {
+ PangoAttribute *other_attr = g_ptr_array_index (other_attrs, other_attr_index);
+ guint64 other_attr_bitmask = other_attr_index < 64 ? 1 << other_attr_index : 0;
+
+ if ((skip_bitmask & other_attr_bitmask) != 0)
+ continue;
+
+ if (attr->start_index == other_attr->start_index &&
+ attr->end_index == other_attr->end_index &&
+ pango_attribute_equal (attr, other_attr))
+ {
+ skip_bitmask |= other_attr_bitmask;
+ attr_equal = TRUE;
+ break;
+ }
+
+ }
+
+ if (!attr_equal)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * pango_attr_list_filter:
+ * @list: a `PangoAttrList`
+ * @func: (scope call) (closure data): callback function;
+ * returns %TRUE if an attribute should be filtered out
+ * @data: (closure): Data to be passed to @func
+ *
+ * Given a `PangoAttrList` and callback function, removes
+ * any elements of @list for which @func returns %TRUE and
+ * inserts them into a new list.
+ *
+ * Return value: (transfer full) (nullable): the new
+ * `PangoAttrList` or %NULL if no attributes of the
+ * given types were found
+ *
+ * Since: 1.2
+ */
+PangoAttrList *
+pango_attr_list_filter (PangoAttrList *list,
+ PangoAttrFilterFunc func,
+ gpointer data)
+
+{
+ PangoAttrList *new = NULL;
+ guint i, p;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ if (!list->attributes || list->attributes->len == 0)
+ return NULL;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
+
+ if ((*func) (tmp_attr, data))
+ {
+ g_ptr_array_remove_index (list->attributes, i);
+ i--; /* Need to look at this index again */
+ p--;
+
+ if (G_UNLIKELY (!new))
+ {
+ new = pango_attr_list_new ();
+ new->attributes = g_ptr_array_new ();
+ }
+
+ g_ptr_array_add (new->attributes, tmp_attr);
+ }
+ }
+
+ return new;
+}
+
+/* }}} */
+/* {{{ Serialization */
+
+/* We serialize attribute lists to strings. The format
+ * is a comma-separated list of the attributes in the order
+ * in which they are in the list, with each attribute having
+ * this format:
+ *
+ * START END NICK VALUE
+ *
+ * Values that can contain a comma, such as font descriptions
+ * are quoted with "".
+ */
+
+static GType
+get_attr_value_type (PangoAttrType type)
+{
+ switch ((int)type)
+ {
+ case PANGO_ATTR_STYLE: return PANGO_TYPE_STYLE;
+ case PANGO_ATTR_WEIGHT: return PANGO_TYPE_WEIGHT;
+ case PANGO_ATTR_VARIANT: return PANGO_TYPE_VARIANT;
+ case PANGO_ATTR_STRETCH: return PANGO_TYPE_STRETCH;
+ case PANGO_ATTR_GRAVITY: return PANGO_TYPE_GRAVITY;
+ case PANGO_ATTR_GRAVITY_HINT: return PANGO_TYPE_GRAVITY_HINT;
+ case PANGO_ATTR_UNDERLINE: return PANGO_TYPE_UNDERLINE;
+ case PANGO_ATTR_OVERLINE: return PANGO_TYPE_OVERLINE;
+ case PANGO_ATTR_BASELINE_SHIFT: return PANGO_TYPE_BASELINE_SHIFT;
+ case PANGO_ATTR_FONT_SCALE: return PANGO_TYPE_FONT_SCALE;
+ case PANGO_ATTR_TEXT_TRANSFORM: return PANGO_TYPE_TEXT_TRANSFORM;
+ default: return G_TYPE_INVALID;
+ }
+}
+
+static void
+append_enum_value (GString *str,
+ GType type,
+ int value)
+{
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+
+ enum_class = g_type_class_ref (type);
+ enum_value = g_enum_get_value (enum_class, value);
+ g_type_class_unref (enum_class);
+
+ if (enum_value)
+ g_string_append_printf (str, " %s", enum_value->value_nick);
+ else
+ g_string_append_printf (str, " %d", value);
+}
+
+static void
+attr_print (GString *str,
+ PangoAttribute *attr)
+{
+ const char *name;
+
+ name = pango_attr_type_get_name (attr->type);
+ if (!name)
+ return;
+
+ g_string_append_printf (str, "%u %u %s", attr->start_index, attr->end_index, name);
+
+ switch (PANGO_ATTR_VALUE_TYPE (attr))
+ {
+ case PANGO_ATTR_VALUE_INT:
+ if (attr->type == PANGO_ATTR_WEIGHT ||
+ attr->type == PANGO_ATTR_STYLE ||
+ attr->type == PANGO_ATTR_STRETCH ||
+ attr->type == PANGO_ATTR_VARIANT ||
+ attr->type == PANGO_ATTR_GRAVITY ||
+ attr->type == PANGO_ATTR_GRAVITY_HINT ||
+ attr->type == PANGO_ATTR_UNDERLINE ||
+ attr->type == PANGO_ATTR_OVERLINE ||
+ attr->type == PANGO_ATTR_BASELINE_SHIFT ||
+ attr->type == PANGO_ATTR_FONT_SCALE ||
+ attr->type == PANGO_ATTR_TEXT_TRANSFORM)
+ append_enum_value (str, get_attr_value_type (attr->type), attr->int_value);
+ else
+ g_string_append_printf (str, " %d", attr->int_value);
+ break;
+
+ case PANGO_ATTR_VALUE_BOOLEAN:
+ g_string_append (str, attr->int_value ? " true" : " false");
+ break;
+
+ case PANGO_ATTR_VALUE_STRING:
+ g_string_append_printf (str, " \"%s\"", attr->str_value);
+ break;
+
+ case PANGO_ATTR_VALUE_LANGUAGE:
+ g_string_append_printf (str, " %s", pango_language_to_string (attr->lang_value));
+ break;
+
+ case PANGO_ATTR_VALUE_FLOAT:
+ {
+ char buf[20];
+ g_ascii_formatd (buf, 20, "%f", attr->double_value);
+ g_string_append_printf (str, " %s", buf);
+ }
+ break;
+
+ case PANGO_ATTR_VALUE_FONT_DESC:
+ {
+ char *s = pango_font_description_to_string (attr->font_value);
+ g_string_append_printf (str, " \"%s\"", s);
+ g_free (s);
+ }
+ break;
+
+ case PANGO_ATTR_VALUE_COLOR:
+ {
+ char *s = pango_color_to_string (&attr->color_value);
+ g_string_append_printf (str, " %s", s);
+ g_free (s);
+ }
+ break;
+
+ case PANGO_ATTR_VALUE_POINTER:
+ {
+ char *s = pango_attr_value_serialize (attr);
+ g_string_append_printf (str, " %s", s);
+ g_free (s);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/**
+ * pango_attr_list_to_string:
+ * @list: a `PangoAttrList`
+ *
+ * Serializes a `PangoAttrList` to a string.
+ *
+ * No guarantees are made about the format of the string,
+ * it may change between Pango versions.
+ *
+ * The intended use of this function is testing and
+ * debugging. The format is not meant as a permanent
+ * storage format.
+ *
+ * Returns: (transfer full): a newly allocated string
+ * Since: 1.50
+ */
+char *
+pango_attr_list_to_string (PangoAttrList *list)
+{
+ GString *s;
+
+ s = g_string_new ("");
+
+ if (list->attributes)
+ for (int i = 0; i < list->attributes->len; i++)
+ {
+ PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
+
+ if (i > 0)
+ g_string_append (s, "\n");
+ attr_print (s, attr);
+ }
+
+ return g_string_free (s, FALSE);
+}
+
+static PangoAttrType
+get_attr_type_by_nick (const char *nick,
+ int len)
+{
+ GEnumClass *enum_class;
+
+ enum_class = g_type_class_ref (pango_attr_type_get_type ());
+ for (GEnumValue *ev = enum_class->values; ev->value_name; ev++)
+ {
+ if (ev->value_nick && strncmp (ev->value_nick, nick, len) == 0)
+ {
+ g_type_class_unref (enum_class);
+ return (PangoAttrType) ev->value;
+ }
+ }
+
+ g_type_class_unref (enum_class);
+ return PANGO_ATTR_INVALID;
+}
+
+static int
+get_attr_value (PangoAttrType type,
+ const char *str,
+ int len)
+{
+ GEnumClass *enum_class;
+ char *endp;
+ int value;
+
+ enum_class = g_type_class_ref (get_attr_value_type (type));
+ for (GEnumValue *ev = enum_class->values; ev->value_name; ev++)
+ {
+ if (ev->value_nick && strncmp (ev->value_nick, str, len) == 0)
+ {
+ g_type_class_unref (enum_class);
+ return ev->value;
+ }
+ }
+ g_type_class_unref (enum_class);
+
+ value = g_ascii_strtoll (str, &endp, 10);
+ if (endp - str == len)
+ return value;
+
+ return -1;
+}
+
+static gboolean
+is_valid_end_char (char c)
+{
+ return c == ',' || c == '\n' || c == '\0';
+}
+
+/**
+ * pango_attr_list_from_string:
+ * @text: a string
+ *
+ * Deserializes a `PangoAttrList` from a string.
+ *
+ * This is the counterpart to [method@Pango.AttrList.to_string].
+ * See that functions for details about the format.
+ *
+ * Returns: (transfer full) (nullable): a new `PangoAttrList`
+ * Since: 1.50
+ */
+PangoAttrList *
+pango_attr_list_from_string (const char *text)
+{
+ PangoAttrList *list;
+ const char *p;
+
+ g_return_val_if_fail (text != NULL, NULL);
+
+ list = pango_attr_list_new ();
+
+ if (*text == '\0')
+ return list;
+
+ list->attributes = g_ptr_array_new ();
+
+ p = text + strspn (text, " \t\n");
+ while (*p)
+ {
+ char *endp;
+ gint64 start_index;
+ gint64 end_index;
+ char *str;
+ PangoAttrType attr_type;
+ PangoAttribute *attr;
+ PangoLanguage *lang;
+ gint64 integer;
+ PangoFontDescription *desc;
+ PangoColor color;
+ double num;
+
+ start_index = g_ascii_strtoll (p, &endp, 10);
+ if (*endp != ' ')
+ goto fail;
+
+ p = endp + strspn (endp, " ");
+ if (!*p)
+ goto fail;
+
+ end_index = g_ascii_strtoll (p, &endp, 10);
+ if (*endp != ' ')
+ goto fail;
+
+ p = endp + strspn (endp, " ");
+
+ endp = (char *)p + strcspn (p, " ");
+ attr_type = get_attr_type_by_nick (p, endp - p);
+
+ p = endp + strspn (endp, " ");
+ if (*p == '\0')
+ goto fail;
+
+#define INT_ATTR(name,type) \
+ integer = g_ascii_strtoll (p, &endp, 10); \
+ if (!is_valid_end_char (*endp)) goto fail; \
+ attr = pango_attr_##name##_new ((type)integer);
+
+#define BOOLEAN_ATTR(name,type) \
+ if (strncmp (p, "true", strlen ("true")) == 0) \
+ { \
+ integer = 1; \
+ endp = (char *)(p + strlen ("true")); \
+ } \
+ else if (strncmp (p, "false", strlen ("false")) == 0) \
+ { \
+ integer = 0; \
+ endp = (char *)(p + strlen ("false")); \
+ } \
+ else \
+ integer = g_ascii_strtoll (p, &endp, 10); \
+ if (!is_valid_end_char (*endp)) goto fail; \
+ attr = pango_attr_##name##_new ((type)integer);
+
+#define ENUM_ATTR(name, type, min, max) \
+ endp = (char *)p + strcspn (p, ",\n"); \
+ integer = get_attr_value (attr_type, p, endp - p); \
+ attr = pango_attr_##name##_new ((type) CLAMP (integer, min, max));
+
+#define FLOAT_ATTR(name) \
+ num = g_ascii_strtod (p, &endp); \
+ if (!is_valid_end_char (*endp)) goto fail; \
+ attr = pango_attr_##name##_new ((float)num);
+
+#define COLOR_ATTR(name) \
+ endp = (char *)p + strcspn (p, ",\n"); \
+ if (!is_valid_end_char (*endp)) goto fail; \
+ str = g_strndup (p, endp - p); \
+ if (!pango_color_parse (&color, str)) \
+ { \
+ g_free (str); \
+ goto fail; \
+ } \
+ attr = pango_attr_##name##_new (color.red, color.green, color.blue); \
+ g_free (str);
+
+ switch (attr_type)
+ {
+ case PANGO_ATTR_INVALID:
+ pango_attr_list_unref (list);
+ return NULL;
+
+ case PANGO_ATTR_LANGUAGE:
+ endp = (char *)p + strcspn (p, ",\n");
+ if (!is_valid_end_char (*endp)) goto fail;
+ str = g_strndup (p, endp - p);
+ lang = pango_language_from_string (str);
+ attr = pango_attr_language_new (lang);
+ g_free (str);
+ break;
+
+ case PANGO_ATTR_FAMILY:
+ p++;
+ endp = strchr (p, '"');
+ if (!endp) goto fail;
+ str = g_strndup (p, endp - p);
+ attr = pango_attr_family_new (str);
+ g_free (str);
+ endp++;
+ if (!is_valid_end_char (*endp)) goto fail;
+ break;
+
+ case PANGO_ATTR_STYLE:
+ ENUM_ATTR(style, PangoStyle, PANGO_STYLE_NORMAL, PANGO_STYLE_ITALIC);
+ break;
+
+ case PANGO_ATTR_WEIGHT:
+ ENUM_ATTR(weight, PangoWeight, PANGO_WEIGHT_THIN, PANGO_WEIGHT_ULTRAHEAVY);
+ break;
+
+ case PANGO_ATTR_VARIANT:
+ ENUM_ATTR(variant, PangoVariant, PANGO_VARIANT_NORMAL, PANGO_VARIANT_TITLE_CAPS);
+ break;
+
+ case PANGO_ATTR_STRETCH:
+ ENUM_ATTR(stretch, PangoStretch, PANGO_STRETCH_ULTRA_CONDENSED, PANGO_STRETCH_ULTRA_EXPANDED);
+ break;
+
+ case PANGO_ATTR_SIZE:
+ INT_ATTR(size, int);
+ break;
+
+ case PANGO_ATTR_FONT_DESC:
+ p++;
+ endp = strchr (p, '"');
+ if (!endp) goto fail;
+ str = g_strndup (p, endp - p);
+ desc = pango_font_description_from_string (str);
+ attr = pango_attr_font_desc_new (desc);
+ pango_font_description_free (desc);
+ g_free (str);
+ endp++;
+ if (!is_valid_end_char (*endp)) goto fail;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ COLOR_ATTR(foreground);
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ COLOR_ATTR(background);
+ break;
+
+ case PANGO_ATTR_UNDERLINE:
+ ENUM_ATTR(underline, PangoUnderline, PANGO_UNDERLINE_NONE, PANGO_UNDERLINE_ERROR_LINE);
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH:
+ BOOLEAN_ATTR(strikethrough, gboolean);
+ break;
+
+ case PANGO_ATTR_RISE:
+ INT_ATTR(rise, int);
+ break;
+
+ case PANGO_ATTR_SCALE:
+ FLOAT_ATTR(scale);
+ break;
+
+ case PANGO_ATTR_FALLBACK:
+ BOOLEAN_ATTR(fallback, gboolean);
+ break;
+
+ case PANGO_ATTR_LETTER_SPACING:
+ INT_ATTR(letter_spacing, int);
+ break;
+
+ case PANGO_ATTR_UNDERLINE_COLOR:
+ COLOR_ATTR(underline_color);
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH_COLOR:
+ COLOR_ATTR(strikethrough_color);
+ break;
+
+ case PANGO_ATTR_ABSOLUTE_SIZE:
+ integer = g_ascii_strtoll (p, &endp, 10);
+ if (!is_valid_end_char (*endp)) goto fail;
+ attr = pango_attr_size_new_absolute (integer);
+ break;
+
+ case PANGO_ATTR_GRAVITY:
+ ENUM_ATTR(gravity, PangoGravity, PANGO_GRAVITY_SOUTH, PANGO_GRAVITY_WEST);
+ break;
+
+ case PANGO_ATTR_FONT_FEATURES:
+ p++;
+ endp = strchr (p, '"');
+ if (!endp) goto fail;
+ str = g_strndup (p, endp - p);
+ attr = pango_attr_font_features_new (str);
+ g_free (str);
+ endp++;
+ if (!is_valid_end_char (*endp)) goto fail;
+ break;
+
+ case PANGO_ATTR_GRAVITY_HINT:
+ ENUM_ATTR(gravity_hint, PangoGravityHint, PANGO_GRAVITY_HINT_NATURAL, PANGO_GRAVITY_HINT_LINE);
+ break;
+
+ case PANGO_ATTR_FOREGROUND_ALPHA:
+ INT_ATTR(foreground_alpha, int);
+ break;
+
+ case PANGO_ATTR_BACKGROUND_ALPHA:
+ INT_ATTR(background_alpha, int);
+ break;
+
+ case PANGO_ATTR_ALLOW_BREAKS:
+ BOOLEAN_ATTR(allow_breaks, gboolean);
+ break;
+
+ case PANGO_ATTR_SHOW:
+ INT_ATTR(show, PangoShowFlags);
+ break;
+
+ case PANGO_ATTR_INSERT_HYPHENS:
+ BOOLEAN_ATTR(insert_hyphens, gboolean);
+ break;
+
+ case PANGO_ATTR_OVERLINE:
+ ENUM_ATTR(overline, PangoOverline, PANGO_OVERLINE_NONE, PANGO_OVERLINE_SINGLE);
+ break;
+
+ case PANGO_ATTR_OVERLINE_COLOR:
+ COLOR_ATTR(overline_color);
+ break;
+
+ case PANGO_ATTR_LINE_HEIGHT:
+ FLOAT_ATTR(line_height);
+ break;
+
+ case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
+ integer = g_ascii_strtoll (p, &endp, 10);
+ if (!is_valid_end_char (*endp)) goto fail;
+ attr = pango_attr_line_height_new_absolute (integer);
+ break;
+
+ case PANGO_ATTR_TEXT_TRANSFORM:
+ ENUM_ATTR(text_transform, PangoTextTransform, PANGO_TEXT_TRANSFORM_NONE, PANGO_TEXT_TRANSFORM_CAPITALIZE);
+ break;
+
+ case PANGO_ATTR_WORD:
+ integer = g_ascii_strtoll (p, &endp, 10);
+ if (!is_valid_end_char (*endp)) goto fail;
+ attr = pango_attr_word_new ();
+ break;
+
+ case PANGO_ATTR_SENTENCE:
+ integer = g_ascii_strtoll (p, &endp, 10);
+ if (!is_valid_end_char (*endp)) goto fail;
+ attr = pango_attr_sentence_new ();
+ break;
+
+ case PANGO_ATTR_BASELINE_SHIFT:
+ ENUM_ATTR(baseline_shift, PangoBaselineShift, 0, G_MAXINT);
+ break;
+
+ case PANGO_ATTR_FONT_SCALE:
+ ENUM_ATTR(font_scale, PangoFontScale, PANGO_FONT_SCALE_NONE, PANGO_FONT_SCALE_SMALL_CAPS);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ attr->start_index = (guint)start_index;
+ attr->end_index = (guint)end_index;
+ g_ptr_array_add (list->attributes, attr);
+
+ p = endp;
+ if (*p)
+ {
+ if (*p == ',')
+ p++;
+ p += strspn (p, " \n");
+ }
+ }
+
+ goto success;
+
+fail:
+ pango_attr_list_unref (list);
+ list = NULL;
+
+success:
+ return list;
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-attr-list.h b/pango/pango-attr-list.h
new file mode 100644
index 00000000..ad1a0fb1
--- /dev/null
+++ b/pango/pango-attr-list.h
@@ -0,0 +1,114 @@
+/* Pango
+ * pango-attr-list.h: Attribute lists
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-attributes.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _PangoAttrList PangoAttrList;
+typedef struct _PangoAttrIterator PangoAttrIterator;
+
+#define PANGO_TYPE_ATTR_LIST pango_attr_list_get_type ()
+
+/**
+ * PangoAttrList:
+ *
+ * A `PangoAttrList` represents a list of attributes that apply to a section
+ * of text.
+ *
+ * The attributes in a `PangoAttrList` are, in general, allowed to overlap in
+ * an arbitrary fashion. However, if the attributes are manipulated only through
+ * [method@Pango.AttrList.change], the overlap between properties will meet
+ * stricter criteria.
+ */
+
+PANGO_AVAILABLE_IN_ALL
+GType pango_attr_list_get_type (void) G_GNUC_CONST;
+
+PANGO_AVAILABLE_IN_ALL
+PangoAttrList * pango_attr_list_new (void);
+PANGO_AVAILABLE_IN_1_10
+PangoAttrList * pango_attr_list_ref (PangoAttrList *list);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_list_unref (PangoAttrList *list);
+PANGO_AVAILABLE_IN_ALL
+PangoAttrList * pango_attr_list_copy (PangoAttrList *list);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_list_insert (PangoAttrList *list,
+ PangoAttribute *attr);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_list_insert_before (PangoAttrList *list,
+ PangoAttribute *attr);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_list_change (PangoAttrList *list,
+ PangoAttribute *attr);
+PANGO_AVAILABLE_IN_ALL
+void pango_attr_list_splice (PangoAttrList *list,
+ PangoAttrList *other,
+ int pos,
+ int len);
+PANGO_AVAILABLE_IN_1_44
+void pango_attr_list_update (PangoAttrList *list,
+ int pos,
+ int remove,
+ int add);
+
+/**
+ * PangoAttrFilterFunc:
+ * @attribute: a Pango attribute
+ * @user_data: user data passed to the function
+ *
+ * Type of a function filtering a list of attributes.
+ *
+ * Return value: `TRUE` if the attribute should be selected for
+ * filtering, `FALSE` otherwise.
+ */
+typedef gboolean (*PangoAttrFilterFunc) (PangoAttribute *attribute,
+ gpointer user_data);
+
+PANGO_AVAILABLE_IN_1_2
+PangoAttrList * pango_attr_list_filter (PangoAttrList *list,
+ PangoAttrFilterFunc func,
+ gpointer data);
+
+PANGO_AVAILABLE_IN_1_44
+GSList * pango_attr_list_get_attributes (PangoAttrList *list);
+
+PANGO_AVAILABLE_IN_1_46
+gboolean pango_attr_list_equal (PangoAttrList *list,
+ PangoAttrList *other_list);
+
+PANGO_AVAILABLE_IN_1_50
+char * pango_attr_list_to_string (PangoAttrList *list);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrList * pango_attr_list_from_string (const char *text);
+
+PANGO_AVAILABLE_IN_ALL
+PangoAttrIterator * pango_attr_list_get_iterator (PangoAttrList *list);
+
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttrList, pango_attr_list_unref)
+
+G_END_DECLS
diff --git a/pango/pango-attr-private.h b/pango/pango-attr-private.h
new file mode 100644
index 00000000..6e068931
--- /dev/null
+++ b/pango/pango-attr-private.h
@@ -0,0 +1,24 @@
+/* Pango
+ * pango-attributes-private.h: Internal structures of PangoLayout
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-attr.h>
+
+char * pango_attr_value_serialize (PangoAttribute *attr);
diff --git a/pango/pango-attr.c b/pango/pango-attr.c
new file mode 100644
index 00000000..0314bdcf
--- /dev/null
+++ b/pango/pango-attr.c
@@ -0,0 +1,540 @@
+/* Pango
+ * pango-attr.c: Attributed text
+ *
+ * Copyright (C) 2000-2002 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 <string.h>
+
+#include "pango-attr-private.h"
+#include "pango-impl-utils.h"
+
+
+/* {{{ Generic attribute code */
+
+G_LOCK_DEFINE_STATIC (attr_type);
+static GArray *attr_type;
+
+#define MIN_CUSTOM 1000
+
+typedef struct _PangoAttrClass PangoAttrClass;
+
+struct _PangoAttrClass {
+ guint type;
+ const char *name;
+ PangoAttrDataCopyFunc copy;
+ GDestroyNotify destroy;
+ GEqualFunc equal;
+ PangoAttrDataSerializeFunc serialize;
+};
+
+static const char *
+get_attr_type_nick (PangoAttrType type)
+{
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+
+ enum_class = g_type_class_ref (pango_attr_type_get_type ());
+ enum_value = g_enum_get_value (enum_class, type);
+ g_type_class_unref (enum_class);
+
+ return enum_value->value_nick;
+}
+
+/**
+ * pango_attr_type_register:
+ * @copy: function to copy the data of an attribute
+ * of this type
+ * @destroy: function to free the data of an attribute
+ * of this type
+ * @equal: function to compare the data of two attributes
+ * of this type
+ * @name: (nullable): an identifier for the type
+ * @serialize: (nullable): function to serialize the data
+ * of an attribute of this type
+ *
+ * Register a new attribute type.
+ *
+ * The attribute type name can be accessed later
+ * by using [func@Pango.AttrType.get_name].
+ *
+ * If @name and to @serialize are provided, they will be used
+ * to serialize attributes of this type.
+ *
+ * To create attributes with the new type, use [func@Pango.attr_custom_new].
+ *
+ * Return value: the attribute type ID
+ */
+guint
+pango_attr_type_register (PangoAttrDataCopyFunc copy,
+ GDestroyNotify destroy,
+ GEqualFunc equal,
+ const char *name,
+ PangoAttrDataSerializeFunc serialize)
+{
+ static guint current_id = MIN_CUSTOM; /* MT-safe */
+ PangoAttrClass class;
+
+ G_LOCK (attr_type);
+
+ class.type = PANGO_ATTR_VALUE_POINTER | (current_id << 8);
+ current_id++;
+
+ class.copy = copy;
+ class.destroy = destroy;
+ class.equal = equal;
+ class.serialize = serialize;
+
+ if (name)
+ class.name = g_intern_string (name);
+
+ if (attr_type == NULL)
+ attr_type = g_array_new (FALSE, FALSE, sizeof (PangoAttrClass));
+
+ g_array_append_val (attr_type, class);
+
+ G_UNLOCK (attr_type);
+
+ return class.type;
+}
+
+/**
+ * pango_attr_type_get_name:
+ * @type: an attribute type ID to fetch the name for
+ *
+ * Fetches the attribute type name.
+ *
+ * The attribute type name is the string passed in
+ * when registering the type using
+ * [func@Pango.AttrType.register].
+ *
+ * The returned value is an interned string (see
+ * g_intern_string() for what that means) that should
+ * not be modified or freed.
+ *
+ * Return value: (nullable): the type ID name (which
+ * may be %NULL), or %NULL if @type is a built-in Pango
+ * attribute type or invalid.
+ *
+ * Since: 1.22
+ */
+const char *
+pango_attr_type_get_name (guint type)
+{
+ const char *result = NULL;
+
+ if ((type >> 8) < MIN_CUSTOM)
+ return get_attr_type_nick (type);
+
+ G_LOCK (attr_type);
+
+ for (int i = 0; i < attr_type->len; i++)
+ {
+ PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
+ if (class->type == type)
+ {
+ result = class->name;
+ break;
+ }
+ }
+
+ G_UNLOCK (attr_type);
+
+ return result;
+}
+
+/**
+ * pango_attribute_copy:
+ * @attr: a `PangoAttribute`
+ *
+ * Make a copy of an attribute.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy].
+ */
+PangoAttribute *
+pango_attribute_copy (const PangoAttribute *attr)
+{
+ PangoAttribute *result;
+
+ g_return_val_if_fail (attr != NULL, NULL);
+
+ result = g_slice_dup (PangoAttribute, attr);
+
+ switch (PANGO_ATTR_VALUE_TYPE (attr))
+ {
+ case PANGO_ATTR_VALUE_STRING:
+ result->str_value = g_strdup (attr->str_value);
+ break;
+
+ case PANGO_ATTR_VALUE_FONT_DESC:
+ result->font_value = pango_font_description_copy (attr->font_value);
+ break;
+
+ case PANGO_ATTR_VALUE_POINTER:
+ {
+ PangoAttrDataCopyFunc copy = NULL;
+
+ G_LOCK (attr_type);
+
+ g_assert (attr_type != NULL);
+
+ for (int i = 0; i < attr_type->len; i++)
+ {
+ PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
+ if (class->type == attr->type)
+ {
+ copy = class->copy;
+ break;
+ }
+ }
+
+ G_UNLOCK (attr_type);
+
+ g_assert (copy != NULL);
+
+ result->pointer_value = copy (attr->pointer_value);
+ }
+ break;
+
+ case PANGO_ATTR_VALUE_INT:
+ case PANGO_ATTR_VALUE_BOOLEAN:
+ case PANGO_ATTR_VALUE_FLOAT:
+ case PANGO_ATTR_VALUE_COLOR:
+ case PANGO_ATTR_VALUE_LANGUAGE:
+ default: ;
+ }
+
+ return result;
+}
+
+/**
+ * pango_attribute_destroy:
+ * @attr: a `PangoAttribute`.
+ *
+ * Destroy a `PangoAttribute` and free all associated memory.
+ */
+void
+pango_attribute_destroy (PangoAttribute *attr)
+{
+ g_return_if_fail (attr != NULL);
+
+ switch (PANGO_ATTR_VALUE_TYPE (attr))
+ {
+ case PANGO_ATTR_VALUE_STRING:
+ g_free (attr->str_value);
+ break;
+
+ case PANGO_ATTR_VALUE_FONT_DESC:
+ pango_font_description_free (attr->font_value);
+ break;
+
+ case PANGO_ATTR_VALUE_POINTER:
+ {
+ GDestroyNotify destroy = NULL;
+
+ G_LOCK (attr_type);
+
+ g_assert (attr_type != NULL);
+
+ for (int i = 0; i < attr_type->len; i++)
+ {
+ PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
+ if (class->type == attr->type)
+ {
+ destroy = class->destroy;
+ break;
+ }
+ }
+
+ G_UNLOCK (attr_type);
+
+ g_assert (destroy != NULL);
+
+ destroy (attr->pointer_value);
+ }
+ break;
+
+ case PANGO_ATTR_VALUE_INT:
+ case PANGO_ATTR_VALUE_BOOLEAN:
+ case PANGO_ATTR_VALUE_FLOAT:
+ case PANGO_ATTR_VALUE_COLOR:
+ case PANGO_ATTR_VALUE_LANGUAGE:
+ default: ;
+ }
+
+ g_slice_free (PangoAttribute, attr);
+}
+
+G_DEFINE_BOXED_TYPE (PangoAttribute, pango_attribute,
+ pango_attribute_copy,
+ pango_attribute_destroy);
+
+/**
+ * pango_attribute_equal:
+ * @attr1: a `PangoAttribute`
+ * @attr2: another `PangoAttribute`
+ *
+ * Compare two attributes for equality.
+ *
+ * This compares only the actual value of the two
+ * attributes and not the ranges that the attributes
+ * apply to.
+ *
+ * Return value: %TRUE if the two attributes have the same value
+ */
+gboolean
+pango_attribute_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ g_return_val_if_fail (attr1 != NULL, FALSE);
+ g_return_val_if_fail (attr2 != NULL, FALSE);
+
+ if (attr1->type != attr2->type)
+ return FALSE;
+
+ switch (PANGO_ATTR_VALUE_TYPE (attr1))
+ {
+ case PANGO_ATTR_VALUE_STRING:
+ return strcmp (attr1->str_value, attr2->str_value) == 0;
+
+ case PANGO_ATTR_VALUE_INT:
+ return attr1->int_value == attr2->int_value;
+
+ case PANGO_ATTR_VALUE_BOOLEAN:
+ return attr1->boolean_value == attr2->boolean_value;
+
+ case PANGO_ATTR_VALUE_FLOAT:
+ return attr1->double_value == attr2->double_value;
+
+ case PANGO_ATTR_VALUE_COLOR:
+ return memcmp (&attr1->color_value, &attr2->color_value, sizeof (PangoColor)) == 0;
+
+ case PANGO_ATTR_VALUE_LANGUAGE:
+ return attr1->lang_value == attr2->lang_value;
+
+ case PANGO_ATTR_VALUE_FONT_DESC:
+ return pango_font_description_equal (attr1->font_value, attr2->font_value);
+
+ case PANGO_ATTR_VALUE_POINTER:
+ {
+ GEqualFunc equal = NULL;
+
+ G_LOCK (attr_type);
+
+ g_assert (attr_type != NULL);
+
+ for (int i = 0; i < attr_type->len; i++)
+ {
+ PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
+ if (class->type == attr1->type)
+ {
+ equal = class->equal;
+ break;
+ }
+ }
+
+ G_UNLOCK (attr_type);
+
+ g_assert (equal != NULL);
+
+ return equal (attr1->pointer_value, attr2->pointer_value);
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/**
+ * pango_attr_custom_new:
+ * @type: the attribute type
+ * @user_data: data for the attribute
+ *
+ * Creates a new attribute for the given type.
+ *
+ * The type must have been registered with [func@Pango.register_attr_type]
+ * before. @user_data will be copied with the copy function that
+ * was given when the type was registered.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy]
+ */
+PangoAttribute *
+pango_attr_custom_new (guint type,
+ gpointer user_data)
+{
+ PangoAttribute *attr;
+ PangoAttrDataCopyFunc copy = NULL;
+
+ g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_POINTER, NULL);
+
+ G_LOCK (attr_type);
+
+ g_assert (attr_type != NULL);
+
+ for (int i = 0; i < attr_type->len; i++)
+ {
+ PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
+ if (class->type == type)
+ {
+ copy = class->copy;
+ break;
+ }
+ }
+
+ g_assert (copy != NULL);
+
+ G_UNLOCK (attr_type);
+
+ attr = g_slice_new (PangoAttribute);
+ attr->type = type;
+ attr->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING;
+ attr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
+ attr->pointer_value = copy (user_data);
+
+ return attr;
+}
+
+/* }}} */
+/* {{{ Private API */
+
+char *
+pango_attr_value_serialize (PangoAttribute *attr)
+{
+ PangoAttrDataSerializeFunc serialize = NULL;
+
+ G_LOCK (attr_type);
+
+ g_assert (attr_type != NULL);
+
+ for (int i = 0; i < attr_type->len; i++)
+ {
+ PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
+ if (class->type == attr->type)
+ {
+ serialize = class->serialize;
+ break;
+ }
+ }
+
+ G_UNLOCK (attr_type);
+
+ if (serialize)
+ return serialize (attr->pointer_value);
+
+ return NULL;
+}
+
+/* }}} */
+/* {{{ Binding Helpers */
+
+gboolean
+pango_attribute_get_string (PangoAttribute *attribute,
+ const char **value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_STRING)
+ return FALSE;
+
+ *value = attribute->str_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_language (PangoAttribute *attribute,
+ PangoLanguage **value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_LANGUAGE)
+ return FALSE;
+
+ *value = attribute->lang_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_int (PangoAttribute *attribute,
+ int *value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_INT)
+ return FALSE;
+
+ *value = attribute->int_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_boolean (PangoAttribute *attribute,
+ int *value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_BOOLEAN)
+ return FALSE;
+
+ *value = attribute->boolean_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_float (PangoAttribute *attribute,
+ double *value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_FLOAT)
+ return FALSE;
+
+ *value = attribute->double_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_color (PangoAttribute *attribute,
+ PangoColor *value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_COLOR)
+ return FALSE;
+
+ *value = attribute->color_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_font_desc (PangoAttribute *attribute,
+ PangoFontDescription **value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_FONT_DESC)
+ return FALSE;
+
+ *value = attribute->font_value;
+ return TRUE;
+}
+
+gboolean
+pango_attribute_get_custom (PangoAttribute *attribute,
+ gpointer *value)
+{
+ if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_POINTER)
+ return FALSE;
+
+ *value = attribute->pointer_value;
+ return TRUE;
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-attr.h b/pango/pango-attr.h
new file mode 100644
index 00000000..7258d3ff
--- /dev/null
+++ b/pango/pango-attr.h
@@ -0,0 +1,214 @@
+/* Pango
+ * pango-attributes.h: Attributed text
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-font.h>
+#include <pango/pango-color.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _PangoAttribute PangoAttribute;
+
+/**
+ * PangoAttrValueType:
+ * @PANGO_ATTR_VALUE_STRING: a string
+ * @PANGO_ATTR_VALUE_INT: an integer
+ * @PANGO_ATTR_VALUE_BOOLEAN: a boolean
+ * @PANGO_ATTR_VALUE_FLOAT: a floating point number
+ * @PANGO_ATTR_VALUE_COLOR: a `PangoColor`
+ * @PANGO_ATTR_VALUE_LANGUAGE: a `PangoLanguage`
+ * @PANGO_ATTR_VALUE_FONT_DESC: a `PangoFontDescription`
+ * @PANGO_ATTR_VALUE_POINTER: a generic pointer
+ *
+ * The `PangoAttrValueType` enumeration describes the various types
+ * of values that a `PangoAttribute` can contain.
+ *
+ * The `PangoAttrValueType` of a `PangoAttribute` is part of its type,
+ * and can be obtained with `PANGO_ATTR_VALUE_TYPE()`.
+ */
+typedef enum
+{
+ PANGO_ATTR_VALUE_STRING,
+ PANGO_ATTR_VALUE_INT,
+ PANGO_ATTR_VALUE_BOOLEAN,
+ PANGO_ATTR_VALUE_FLOAT,
+ PANGO_ATTR_VALUE_COLOR,
+ PANGO_ATTR_VALUE_LANGUAGE,
+ PANGO_ATTR_VALUE_FONT_DESC,
+ PANGO_ATTR_VALUE_POINTER
+} PangoAttrValueType;
+
+/**
+ * PANGO_ATTR_TYPE_VALUE_TYPE:
+ * @type: an attribute type
+ *
+ * Extracts the `PangoAttrValueType` from an attribute type.
+ */
+#define PANGO_ATTR_TYPE_VALUE_TYPE(type) ((PangoAttrValueType)((type) & 0xff))
+
+/**
+ * PANGO_ATTR_VALUE_TYPE:
+ * @attr: a `PangoAttribute`
+ *
+ * Obtains the `PangoAttrValueType of a `PangoAttribute`.
+ */
+#define PANGO_ATTR_VALUE_TYPE(attr) PANGO_ATTR_TYPE_VALUE_TYPE ((attr)->type)
+
+/**
+ * PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING:
+ *
+ * Value for @start_index in `PangoAttribute` that indicates
+ * the beginning of the text.
+ *
+ * Since: 1.24
+ */
+#define PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING ((guint)0)
+
+/**
+ * PANGO_ATTR_INDEX_TO_TEXT_END: (value 4294967295)
+ *
+ * Value for @end_index in `PangoAttribute` that indicates
+ * the end of the text.
+ *
+ * Since: 1.24
+ */
+#define PANGO_ATTR_INDEX_TO_TEXT_END ((guint)(G_MAXUINT + 0))
+
+/**
+ * PangoAttribute:
+ * @klass: the class structure holding information about the type of the attribute
+ * @start_index: the start index of the range (in bytes).
+ * @end_index: end index of the range (in bytes). The character at this index
+ * is not included in the range.
+ * @str_value: the string value
+ * @int_value: the integer value
+ * @boolean_value: the boolean value
+ * @double_value: the double value
+ * @color_value: the `PangoColor` value
+ * @lang_value: the `PangoLanguage` value
+ * @font_value: the `PangoFontDescription` value
+ * @pointer_value: a custom value
+ *
+ * The `PangoAttribute` structure contains information for a single
+ * attribute.
+ *
+ * The common portion of the attribute holds the range to which
+ * the value in the type-specific part of the attribute applies.
+ * By default, an attribute will have an all-inclusive range of
+ * [0,%G_MAXUINT].
+ *
+ * Which of the values is used depends on the value type of the
+ * attribute, which can be obtained with `PANGO_ATTR_VALUE_TYPE()`.
+ */
+struct _PangoAttribute
+{
+ guint type;
+ guint start_index;
+ guint end_index;
+ union {
+ char *str_value;
+ int int_value;
+ gboolean boolean_value;
+ double double_value;
+ PangoColor color_value;
+ PangoLanguage *lang_value;
+ PangoFontDescription *font_value;
+ gpointer pointer_value;
+ };
+};
+
+/**
+ * PangoAttrDataCopyFunc:
+ * @value: value to copy
+ *
+ * Type of a function that can duplicate the value of an attribute.
+ *
+ * Return value: new copy of @value.
+ **/
+typedef gpointer (*PangoAttrDataCopyFunc) (gconstpointer value);
+
+/**
+ * PangoAttrDataSerializeFunc:
+ * @value: value to serialize
+ *
+ * Type of a function that can serialize the value of an attribute.
+ *
+ * Return value: a newly allocated string holding the serialization of @value
+ */
+typedef char * (*PangoAttrDataSerializeFunc) (gconstpointer value);
+
+PANGO_AVAILABLE_IN_ALL
+GType pango_attribute_get_type (void) G_GNUC_CONST;
+
+PANGO_AVAILABLE_IN_ALL
+guint pango_attr_type_register (PangoAttrDataCopyFunc copy,
+ GDestroyNotify destroy,
+ GEqualFunc equal,
+ const char *name,
+ PangoAttrDataSerializeFunc serialize);
+
+PANGO_AVAILABLE_IN_1_22
+const char * pango_attr_type_get_name (guint type) G_GNUC_CONST;
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attribute_copy (const PangoAttribute *attr);
+PANGO_AVAILABLE_IN_ALL
+void pango_attribute_destroy (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_ALL
+gboolean pango_attribute_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2) G_GNUC_PURE;
+
+PANGO_AVAILABLE_IN_1_52
+PangoAttribute * pango_attr_custom_new (guint type,
+ gpointer user_data);
+
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_string (PangoAttribute *attribute,
+ const char **value);
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_language (PangoAttribute *attribute,
+ PangoLanguage **value);
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_int (PangoAttribute *attribute,
+ int *value);
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_boolean (PangoAttribute *attribute,
+ gboolean *value);
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_float (PangoAttribute *attribute,
+ double *value);
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_color (PangoAttribute *attribute,
+ PangoColor *value);
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_font_desc (PangoAttribute *attribute,
+ PangoFontDescription **value);
+
+PANGO_AVAILABLE_IN_1_52
+gboolean pango_attribute_get_custom (PangoAttribute *attribute,
+ gpointer *value);
+
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttribute, pango_attribute_destroy)
+
+G_END_DECLS
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 73fd5799..8e8e1746 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -23,346 +23,10 @@
#include <string.h>
#include "pango-attributes.h"
-#include "pango-attributes-private.h"
+#include "pango-attr-private.h"
#include "pango-impl-utils.h"
-
-/* {{{ Generic attribute code */
-
-G_LOCK_DEFINE_STATIC (attr_type);
-static GArray *attr_type;
-
-#define MIN_CUSTOM 1000
-
-typedef struct _PangoAttrClass PangoAttrClass;
-
-struct _PangoAttrClass {
- PangoAttrType type;
- const char *name;
- PangoAttrDataCopyFunc copy;
- GDestroyNotify destroy;
- GEqualFunc equal;
- PangoAttrDataSerializeFunc serialize;
-};
-
-static const char *
-get_attr_type_nick (PangoAttrType type)
-{
- GEnumClass *enum_class;
- GEnumValue *enum_value;
-
- enum_class = g_type_class_ref (pango_attr_type_get_type ());
- enum_value = g_enum_get_value (enum_class, type);
- g_type_class_unref (enum_class);
-
- return enum_value->value_nick;
-}
-
-/**
- * pango_attr_type_register:
- * @copy: function to copy the data of an attribute
- * of this type
- * @destroy: function to free the data of an attribute
- * of this type
- * @equal: function to compare the data of two attributes
- * of this type
- * @name: (nullable): an identifier for the type
- * @serialize: (nullable): function to serialize the data
- * of an attribute of this type
- *
- * Allocate a new attribute type ID.
- *
- * The attribute type name can be accessed later
- * by using [func@Pango.AttrType.get_name].
- *
- * If @name and to @serialize are provided, they will be used
- * to serialize attributes of this type.
- *
- * Return value: the new type ID.
- */
-PangoAttrType
-pango_attr_type_register (PangoAttrDataCopyFunc copy,
- GDestroyNotify destroy,
- GEqualFunc equal,
- const char *name,
- PangoAttrDataSerializeFunc serialize)
-{
- static guint current_id = MIN_CUSTOM; /* MT-safe */
- PangoAttrClass class;
-
- G_LOCK (attr_type);
-
- class.type = PANGO_ATTR_VALUE_POINTER | (current_id << 8);
- current_id++;
-
- class.copy = copy;
- class.destroy = destroy;
- class.equal = equal;
- class.serialize = serialize;
-
- if (name)
- class.name = g_intern_string (name);
-
- if (attr_type == NULL)
- attr_type = g_array_new (FALSE, FALSE, sizeof (PangoAttrClass));
-
- g_array_append_val (attr_type, class);
-
- G_UNLOCK (attr_type);
-
- return class.type;
-}
-
-/**
- * pango_attr_type_get_name:
- * @type: an attribute type ID to fetch the name for
- *
- * Fetches the attribute type name.
- *
- * The attribute type name is the string passed in
- * when registering the type using
- * [func@Pango.AttrType.register].
- *
- * The returned value is an interned string (see
- * g_intern_string() for what that means) that should
- * not be modified or freed.
- *
- * Return value: (nullable): the type ID name (which
- * may be %NULL), or %NULL if @type is a built-in Pango
- * attribute type or invalid.
- *
- * Since: 1.22
- */
-const char *
-pango_attr_type_get_name (PangoAttrType type)
-{
- const char *result = NULL;
-
- if ((type >> 8) < MIN_CUSTOM)
- return get_attr_type_nick (type);
-
- G_LOCK (attr_type);
-
- for (int i = 0; i < attr_type->len; i++)
- {
- PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
- if (class->type == type)
- {
- result = class->name;
- break;
- }
- }
-
- G_UNLOCK (attr_type);
-
- return result;
-}
-
-/**
- * pango_attribute_copy:
- * @attr: a `PangoAttribute`
- *
- * Make a copy of an attribute.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttribute`, which should be freed with
- * [method@Pango.Attribute.destroy].
- */
-PangoAttribute *
-pango_attribute_copy (const PangoAttribute *attr)
-{
- PangoAttribute *result;
-
- g_return_val_if_fail (attr != NULL, NULL);
-
- result = g_slice_dup (PangoAttribute, attr);
-
- switch (PANGO_ATTR_VALUE_TYPE (attr))
- {
- case PANGO_ATTR_VALUE_STRING:
- result->str_value = g_strdup (attr->str_value);
- break;
-
- case PANGO_ATTR_VALUE_FONT_DESC:
- result->font_value = pango_font_description_copy (attr->font_value);
- break;
-
- case PANGO_ATTR_VALUE_POINTER:
- {
- PangoAttrDataCopyFunc copy = NULL;
-
- G_LOCK (attr_type);
-
- g_assert (attr_type != NULL);
-
- for (int i = 0; i < attr_type->len; i++)
- {
- PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
- if (class->type == attr->type)
- {
- copy = class->copy;
- break;
- }
- }
-
- G_UNLOCK (attr_type);
-
- g_assert (copy != NULL);
-
- result->pointer_value = copy (attr->pointer_value);
- }
- break;
-
- case PANGO_ATTR_VALUE_INT:
- case PANGO_ATTR_VALUE_BOOLEAN:
- case PANGO_ATTR_VALUE_FLOAT:
- case PANGO_ATTR_VALUE_COLOR:
- case PANGO_ATTR_VALUE_LANGUAGE:
- default: ;
- }
-
- return result;
-}
-
-/**
- * pango_attribute_destroy:
- * @attr: a `PangoAttribute`.
- *
- * Destroy a `PangoAttribute` and free all associated memory.
- */
-void
-pango_attribute_destroy (PangoAttribute *attr)
-{
- g_return_if_fail (attr != NULL);
-
- switch (PANGO_ATTR_VALUE_TYPE (attr))
- {
- case PANGO_ATTR_VALUE_STRING:
- g_free (attr->str_value);
- break;
-
- case PANGO_ATTR_VALUE_FONT_DESC:
- pango_font_description_free (attr->font_value);
- break;
-
- case PANGO_ATTR_VALUE_POINTER:
- {
- GDestroyNotify destroy = NULL;
-
- G_LOCK (attr_type);
-
- g_assert (attr_type != NULL);
-
- for (int i = 0; i < attr_type->len; i++)
- {
- PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
- if (class->type == attr->type)
- {
- destroy = class->destroy;
- break;
- }
- }
-
- G_UNLOCK (attr_type);
-
- g_assert (destroy != NULL);
-
- destroy (attr->pointer_value);
- }
- break;
-
- case PANGO_ATTR_VALUE_INT:
- case PANGO_ATTR_VALUE_BOOLEAN:
- case PANGO_ATTR_VALUE_FLOAT:
- case PANGO_ATTR_VALUE_COLOR:
- case PANGO_ATTR_VALUE_LANGUAGE:
- default: ;
- }
-
- g_slice_free (PangoAttribute, attr);
-}
-
-G_DEFINE_BOXED_TYPE (PangoAttribute, pango_attribute,
- pango_attribute_copy,
- pango_attribute_destroy);
-
-/**
- * pango_attribute_equal:
- * @attr1: a `PangoAttribute`
- * @attr2: another `PangoAttribute`
- *
- * Compare two attributes for equality.
- *
- * This compares only the actual value of the two
- * attributes and not the ranges that the attributes
- * apply to.
- *
- * Return value: %TRUE if the two attributes have the same value
- */
-gboolean
-pango_attribute_equal (const PangoAttribute *attr1,
- const PangoAttribute *attr2)
-{
- g_return_val_if_fail (attr1 != NULL, FALSE);
- g_return_val_if_fail (attr2 != NULL, FALSE);
-
- if (attr1->type != attr2->type)
- return FALSE;
-
- switch (PANGO_ATTR_VALUE_TYPE (attr1))
- {
- case PANGO_ATTR_VALUE_STRING:
- return strcmp (attr1->str_value, attr2->str_value) == 0;
-
- case PANGO_ATTR_VALUE_INT:
- return attr1->int_value == attr2->int_value;
-
- case PANGO_ATTR_VALUE_BOOLEAN:
- return attr1->boolean_value == attr2->boolean_value;
-
- case PANGO_ATTR_VALUE_FLOAT:
- return attr1->double_value == attr2->double_value;
-
- case PANGO_ATTR_VALUE_COLOR:
- return memcmp (&attr1->color_value, &attr2->color_value, sizeof (PangoColor)) == 0;
-
- case PANGO_ATTR_VALUE_LANGUAGE:
- return attr1->lang_value == attr2->lang_value;
-
- case PANGO_ATTR_VALUE_FONT_DESC:
- return pango_font_description_equal (attr1->font_value, attr2->font_value);
-
- case PANGO_ATTR_VALUE_POINTER:
- {
- GEqualFunc equal = NULL;
-
- G_LOCK (attr_type);
-
- g_assert (attr_type != NULL);
-
- for (int i = 0; i < attr_type->len; i++)
- {
- PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
- if (class->type == attr1->type)
- {
- equal = class->equal;
- break;
- }
- }
-
- G_UNLOCK (attr_type);
-
- g_assert (equal != NULL);
-
- return equal (attr1->pointer_value, attr2->pointer_value);
- }
-
- default:
- g_assert_not_reached ();
- }
-}
-
-/* {{{ Builtin Attribute value types */
+/* {{{ Attribute value types */
static inline PangoAttribute *
pango_attr_init (PangoAttrType type)
@@ -377,7 +41,7 @@ pango_attr_init (PangoAttrType type)
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_string_new (PangoAttrType type,
const char *value)
{
@@ -391,7 +55,7 @@ pango_attr_string_new (PangoAttrType type,
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_int_new (PangoAttrType type,
int value)
{
@@ -405,7 +69,7 @@ pango_attr_int_new (PangoAttrType type,
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_boolean_new (PangoAttrType type,
gboolean value)
{
@@ -419,7 +83,7 @@ pango_attr_boolean_new (PangoAttrType type,
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_float_new (PangoAttrType type,
double value)
{
@@ -433,7 +97,7 @@ pango_attr_float_new (PangoAttrType type,
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_color_new (PangoAttrType type,
guint16 red,
guint16 green,
@@ -451,7 +115,7 @@ pango_attr_color_new (PangoAttrType type,
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_lang_new (PangoAttrType type,
PangoLanguage *value)
{
@@ -465,7 +129,7 @@ pango_attr_lang_new (PangoAttrType type,
return attr;
}
-static PangoAttribute *
+static inline PangoAttribute *
pango_attr_font_description_new (PangoAttrType type,
const PangoFontDescription *value)
{
@@ -478,39 +142,9 @@ pango_attr_font_description_new (PangoAttrType type,
return attr;
}
-/* }}} */
-/* }}} */
-/* {{{ Private API */
-
-char *
-pango_attr_value_serialize (PangoAttribute *attr)
-{
- PangoAttrDataSerializeFunc serialize = NULL;
-
- G_LOCK (attr_type);
-
- g_assert (attr_type != NULL);
-
- for (int i = 0; i < attr_type->len; i++)
- {
- PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i);
- if (class->type == attr->type)
- {
- serialize = class->serialize;
- break;
- }
- }
-
- G_UNLOCK (attr_type);
-
- if (serialize)
- return serialize (attr->pointer_value);
-
- return NULL;
-}
/* }}} */
-/* {{{ Public API */
+/* {{{ Attribute types */
/**
* pango_attr_family_new:
@@ -1214,1884 +848,6 @@ pango_attr_text_transform_new (PangoTextTransform transform)
return pango_attr_int_new (PANGO_ATTR_TEXT_TRANSFORM, transform);
}
-/**
- * pango_attr_custom_new:
- * @type: the attribute type
- * @user_data: data for the attribute
- *
- * Creates a new attribute for the given type.
- *
- * The type must have been registered with [func@Pango.register_attr_type]
- * before. @user_data will be copied with the copy function that
- * was given when the type was registered.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttribute`, which should be freed with
- * [method@Pango.Attribute.destroy]
- */
-PangoAttribute *
-pango_attr_custom_new (PangoAttrType type,
- gpointer user_data)
-{
- PangoAttrClass *class = NULL;
- PangoAttribute *attr;
-
- g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_POINTER, NULL);
-
- G_LOCK (attr_type);
-
- g_assert (attr_type != NULL);
-
- for (int i = 0; i < attr_type->len; i++)
- {
- PangoAttrClass *c = &g_array_index (attr_type, PangoAttrClass, i);
- if (c->type == type)
- {
- class = c;
- break;
- }
- }
-
- g_assert (class != NULL);
-
- G_UNLOCK (attr_type);
-
- attr = pango_attr_init (type);
- attr->pointer_value = class->copy (user_data);
-
- return attr;
-}
-
-/* }}} */
-/* {{{ Binding Helpers */
-
-gboolean
-pango_attribute_get_string (PangoAttribute *attribute,
- const char **value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_STRING)
- return FALSE;
-
- *value = attribute->str_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_language (PangoAttribute *attribute,
- PangoLanguage **value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_LANGUAGE)
- return FALSE;
-
- *value = attribute->lang_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_int (PangoAttribute *attribute,
- int *value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_INT)
- return FALSE;
-
- *value = attribute->int_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_boolean (PangoAttribute *attribute,
- int *value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_BOOLEAN)
- return FALSE;
-
- *value = attribute->boolean_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_float (PangoAttribute *attribute,
- double *value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_FLOAT)
- return FALSE;
-
- *value = attribute->double_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_color (PangoAttribute *attribute,
- PangoColor *value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_COLOR)
- return FALSE;
-
- *value = attribute->color_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_font_desc (PangoAttribute *attribute,
- PangoFontDescription **value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_FONT_DESC)
- return FALSE;
-
- *value = attribute->font_value;
- return TRUE;
-}
-
-gboolean
-pango_attribute_get_custom (PangoAttribute *attribute,
- gpointer *value)
-{
- if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_POINTER)
- return FALSE;
-
- *value = attribute->pointer_value;
- return TRUE;
-}
-
-/* }}} */
-/* {{{ Attribute List */
-
-G_DEFINE_BOXED_TYPE (PangoAttrList, pango_attr_list,
- pango_attr_list_copy,
- pango_attr_list_unref);
-
-void
-_pango_attr_list_init (PangoAttrList *list)
-{
- list->ref_count = 1;
- list->attributes = NULL;
-}
-
-/**
- * pango_attr_list_new:
- *
- * Create a new empty attribute list with a reference
- * count of one.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttrList`, which should be freed with
- * [method@Pango.AttrList.unref]
- */
-PangoAttrList *
-pango_attr_list_new (void)
-{
- PangoAttrList *list = g_slice_new (PangoAttrList);
-
- _pango_attr_list_init (list);
-
- return list;
-}
-
-/**
- * pango_attr_list_ref:
- * @list: (nullable): a `PangoAttrList`
- *
- * Increase the reference count of the given attribute
- * list by one.
- *
- * Return value: The attribute list passed in
- *
- * Since: 1.10
- */
-PangoAttrList *
-pango_attr_list_ref (PangoAttrList *list)
-{
- if (list == NULL)
- return NULL;
-
- g_atomic_int_inc ((int *) &list->ref_count);
-
- return list;
-}
-
-void
-_pango_attr_list_destroy (PangoAttrList *list)
-{
-// guint i, p;
-
- if (!list->attributes)
- return;
-
-#if 0
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
- //attr->klass->destroy (attr);
- }
-#endif
-
- g_ptr_array_free (list->attributes, TRUE);
-}
-
-/**
- * pango_attr_list_unref:
- * @list: (nullable): a `PangoAttrList`
- *
- * Decrease the reference count of the given attribute
- * list by one.
- *
- * If the result is zero, free the attribute list
- * and the attributes it contains.
- */
-void
-pango_attr_list_unref (PangoAttrList *list)
-{
- if (list == NULL)
- return;
-
- g_return_if_fail (list->ref_count > 0);
-
- if (g_atomic_int_dec_and_test ((int *) &list->ref_count))
- {
- _pango_attr_list_destroy (list);
- g_slice_free (PangoAttrList, list);
- }
-}
-
-/**
- * pango_attr_list_copy:
- * @list: (nullable): a `PangoAttrList`
- *
- * Copy @list and return an identical new list.
- *
- * Return value: (nullable): the newly allocated
- * `PangoAttrList`, with a reference count of one,
- * which should be freed with [method@Pango.AttrList.unref].
- * Returns %NULL if @list was %NULL.
- */
-PangoAttrList *
-pango_attr_list_copy (PangoAttrList *list)
-{
- PangoAttrList *new;
-
- if (list == NULL)
- return NULL;
-
- new = pango_attr_list_new ();
- if (!list->attributes || list->attributes->len == 0)
- return new;
-
- new->attributes = g_ptr_array_copy (list->attributes, (GCopyFunc)pango_attribute_copy, NULL);
-
- return new;
-}
-
-static void
-pango_attr_list_insert_internal (PangoAttrList *list,
- PangoAttribute *attr,
- gboolean before)
-{
- const guint start_index = attr->start_index;
- PangoAttribute *last_attr;
-
- if (G_UNLIKELY (!list->attributes))
- list->attributes = g_ptr_array_new ();
-
- if (list->attributes->len == 0)
- {
- g_ptr_array_add (list->attributes, attr);
- return;
- }
-
- g_assert (list->attributes->len > 0);
-
- last_attr = g_ptr_array_index (list->attributes, list->attributes->len - 1);
-
- if (last_attr->start_index < start_index ||
- (!before && last_attr->start_index == start_index))
- {
- g_ptr_array_add (list->attributes, attr);
- }
- else
- {
- guint i, p;
-
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *cur = g_ptr_array_index (list->attributes, i);
-
- if (cur->start_index > start_index ||
- (before && cur->start_index == start_index))
- {
- g_ptr_array_insert (list->attributes, i, attr);
- break;
- }
- }
- }
-}
-
-/**
- * pango_attr_list_insert:
- * @list: a `PangoAttrList`
- * @attr: (transfer full): the attribute to insert
- *
- * Insert the given attribute into the `PangoAttrList`.
- *
- * It will be inserted after all other attributes with a
- * matching @start_index.
- */
-void
-pango_attr_list_insert (PangoAttrList *list,
- PangoAttribute *attr)
-{
- g_return_if_fail (list != NULL);
- g_return_if_fail (attr != NULL);
-
- pango_attr_list_insert_internal (list, attr, FALSE);
-}
-
-/**
- * pango_attr_list_insert_before:
- * @list: a `PangoAttrList`
- * @attr: (transfer full): the attribute to insert
- *
- * Insert the given attribute into the `PangoAttrList`.
- *
- * It will be inserted before all other attributes with a
- * matching @start_index.
- */
-void
-pango_attr_list_insert_before (PangoAttrList *list,
- PangoAttribute *attr)
-{
- g_return_if_fail (list != NULL);
- g_return_if_fail (attr != NULL);
-
- pango_attr_list_insert_internal (list, attr, TRUE);
-}
-
-/**
- * pango_attr_list_change:
- * @list: a `PangoAttrList`
- * @attr: (transfer full): the attribute to insert
- *
- * Insert the given attribute into the `PangoAttrList`.
- *
- * It will replace any attributes of the same type
- * on that segment and be merged with any adjoining
- * attributes that are identical.
- *
- * This function is slower than [method@Pango.AttrList.insert]
- * for creating an attribute list in order (potentially
- * much slower for large lists). However,
- * [method@Pango.AttrList.insert] is not suitable for
- * continually changing a set of attributes since it
- * never removes or combines existing attributes.
- */
-void
-pango_attr_list_change (PangoAttrList *list,
- PangoAttribute *attr)
-{
- guint i, p;
- guint start_index = attr->start_index;
- guint end_index = attr->end_index;
- gboolean inserted;
-
- g_return_if_fail (list != NULL);
-
- if (start_index == end_index) /* empty, nothing to do */
- {
- pango_attribute_destroy (attr);
- return;
- }
-
- if (!list->attributes || list->attributes->len == 0)
- {
- pango_attr_list_insert (list, attr);
- return;
- }
-
- inserted = FALSE;
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
-
- if (tmp_attr->start_index > start_index)
- {
- g_ptr_array_insert (list->attributes, i, attr);
- inserted = TRUE;
- break;
- }
-
- if (tmp_attr->type != attr->type)
- continue;
-
- if (tmp_attr->end_index < start_index)
- continue; /* This attr does not overlap with the new one */
-
- g_assert (tmp_attr->start_index <= start_index);
- g_assert (tmp_attr->end_index >= start_index);
-
- if (pango_attribute_equal (tmp_attr, attr))
- {
- /* We can merge the new attribute with this attribute
- */
- if (tmp_attr->end_index >= end_index)
- {
- /* We are totally overlapping the previous attribute.
- * No action is needed.
- */
- pango_attribute_destroy (attr);
- return;
- }
-
- tmp_attr->end_index = end_index;
- pango_attribute_destroy (attr);
-
- attr = tmp_attr;
- inserted = TRUE;
- break;
- }
- else
- {
- /* Split, truncate, or remove the old attribute
- */
- if (tmp_attr->end_index > end_index)
- {
- PangoAttribute *end_attr = pango_attribute_copy (tmp_attr);
-
- end_attr->start_index = end_index;
- pango_attr_list_insert (list, end_attr);
- }
-
- if (tmp_attr->start_index == start_index)
- {
- pango_attribute_destroy (tmp_attr);
- g_ptr_array_remove_index (list->attributes, i);
- break;
- }
- else
- {
- tmp_attr->end_index = start_index;
- }
- }
- }
-
- if (!inserted)
- /* we didn't insert attr yet */
- pango_attr_list_insert (list, attr);
-
- /* We now have the range inserted into the list one way or the
- * other. Fix up the remainder
- */
- /* Attention: No i = 0 here. */
- for (i = i + 1, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
-
- if (tmp_attr->start_index > end_index)
- break;
-
- if (tmp_attr->type != attr->type)
- continue;
-
- if (tmp_attr->end_index <= attr->end_index ||
- pango_attribute_equal (tmp_attr, attr))
- {
- /* We can merge the new attribute with this attribute. */
- attr->end_index = MAX (end_index, tmp_attr->end_index);
- pango_attribute_destroy (tmp_attr);
- g_ptr_array_remove_index (list->attributes, i);
- i--;
- p--;
- continue;
- }
- else
- {
- /* Trim the start of this attribute that it begins at the end
- * of the new attribute. This may involve moving it in the list
- * to maintain the required non-decreasing order of start indices.
- */
- int k, m;
-
- tmp_attr->start_index = attr->end_index;
-
- for (k = i + 1, m = list->attributes->len; k < m; k++)
- {
- PangoAttribute *tmp_attr2 = g_ptr_array_index (list->attributes, k);
-
- if (tmp_attr2->start_index >= tmp_attr->start_index)
- break;
- }
- }
- }
-}
-
-/**
- * pango_attr_list_update:
- * @list: a `PangoAttrList`
- * @pos: the position of the change
- * @remove: the number of removed bytes
- * @add: the number of added bytes
- *
- * Update indices of attributes in @list for a change in the
- * text they refer to.
- *
- * The change that this function applies is removing @remove
- * bytes at position @pos and inserting @add bytes instead.
- *
- * Attributes that fall entirely in the (@pos, @pos + @remove)
- * range are removed.
- *
- * Attributes that start or end inside the (@pos, @pos + @remove)
- * range are shortened to reflect the removal.
- *
- * Attributes start and end positions are updated if they are
- * behind @pos + @remove.
- *
- * Since: 1.44
- */
-void
-pango_attr_list_update (PangoAttrList *list,
- int pos,
- int remove,
- int add)
-{
- guint i, p;
-
- g_return_if_fail (pos >= 0);
- g_return_if_fail (remove >= 0);
- g_return_if_fail (add >= 0);
-
- if (list->attributes)
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
-
- if (attr->start_index >= pos &&
- attr->end_index < pos + remove)
- {
- pango_attribute_destroy (attr);
- g_ptr_array_remove_index (list->attributes, i);
- i--; /* Look at this index again */
- p--;
- continue;
- }
-
- if (attr->start_index != PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING)
- {
- if (attr->start_index >= pos &&
- attr->start_index < pos + remove)
- {
- attr->start_index = pos + add;
- }
- else if (attr->start_index >= pos + remove)
- {
- attr->start_index += add - remove;
- }
- }
-
- if (attr->end_index != PANGO_ATTR_INDEX_TO_TEXT_END)
- {
- if (attr->end_index >= pos &&
- attr->end_index < pos + remove)
- {
- attr->end_index = pos;
- }
- else if (attr->end_index >= pos + remove)
- {
- if (add > remove &&
- G_MAXUINT - attr->end_index < add - remove)
- attr->end_index = G_MAXUINT;
- else
- attr->end_index += add - remove;
- }
- }
- }
-}
-
-/**
- * pango_attr_list_splice:
- * @list: a `PangoAttrList`
- * @other: another `PangoAttrList`
- * @pos: the position in @list at which to insert @other
- * @len: the length of the spliced segment. (Note that this
- * must be specified since the attributes in @other may only
- * be present at some subsection of this range)
- *
- * This function opens up a hole in @list, fills it
- * in with attributes from the left, and then merges
- * @other on top of the hole.
- *
- * This operation is equivalent to stretching every attribute
- * that applies at position @pos in @list by an amount @len,
- * and then calling [method@Pango.AttrList.change] with a copy
- * of each attribute in @other in sequence (offset in position
- * by @pos, and limited in length to @len).
- *
- * This operation proves useful for, for instance, inserting
- * a pre-edit string in the middle of an edit buffer.
- *
- * For backwards compatibility, the function behaves differently
- * when @len is 0. In this case, the attributes from @other are
- * not imited to @len, and are just overlayed on top of @list.
- *
- * This mode is useful for merging two lists of attributes together.
- */
-void
-pango_attr_list_splice (PangoAttrList *list,
- PangoAttrList *other,
- gint pos,
- gint len)
-{
- guint i, p;
- guint upos, ulen;
- guint end;
-
- g_return_if_fail (list != NULL);
- g_return_if_fail (other != NULL);
- g_return_if_fail (pos >= 0);
- g_return_if_fail (len >= 0);
-
- upos = (guint)pos;
- ulen = (guint)len;
-
-/* This definition only works when a and b are unsigned; overflow
- * isn't defined in the C standard for signed integers
- */
-#define CLAMP_ADD(a,b) (((a) + (b) < (a)) ? G_MAXUINT : (a) + (b))
-
- end = CLAMP_ADD (upos, ulen);
-
- if (list->attributes)
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *attr = g_ptr_array_index (list->attributes, i);;
-
- if (attr->start_index <= upos)
- {
- if (attr->end_index > upos)
- attr->end_index = CLAMP_ADD (attr->end_index, ulen);
- }
- else
- {
- /* This could result in a zero length attribute if it
- * gets squashed up against G_MAXUINT, but deleting such
- * an element could (in theory) suprise the caller, so
- * we don't delete it.
- */
- attr->start_index = CLAMP_ADD (attr->start_index, ulen);
- attr->end_index = CLAMP_ADD (attr->end_index, ulen);
- }
- }
-
- if (!other->attributes || other->attributes->len == 0)
- return;
-
- for (i = 0, p = other->attributes->len; i < p; i++)
- {
- PangoAttribute *attr = pango_attribute_copy (g_ptr_array_index (other->attributes, i));
- if (ulen > 0)
- {
- attr->start_index = MIN (CLAMP_ADD (attr->start_index, upos), end);
- attr->end_index = MIN (CLAMP_ADD (attr->end_index, upos), end);
- }
- else
- {
- attr->start_index = CLAMP_ADD (attr->start_index, upos);
- attr->end_index = CLAMP_ADD (attr->end_index, upos);
- }
-
- /* Same as above, the attribute could be squashed to zero-length; here
- * pango_attr_list_change() will take care of deleting it.
- */
- pango_attr_list_change (list, attr);
- }
-#undef CLAMP_ADD
-}
-
-/**
- * pango_attr_list_get_attributes:
- * @list: a `PangoAttrList`
- *
- * Gets a list of all attributes in @list.
- *
- * Return value: (element-type Pango.Attribute) (transfer full):
- * a list of all attributes in @list. To free this value,
- * call [method@Pango.Attribute.destroy] on each value and
- * g_slist_free() on the list.
- *
- * Since: 1.44
- */
-GSList *
-pango_attr_list_get_attributes (PangoAttrList *list)
-{
- GSList *result = NULL;
- guint i, p;
-
- g_return_val_if_fail (list != NULL, NULL);
-
- if (!list->attributes || list->attributes->len == 0)
- return NULL;
-
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
-
- result = g_slist_prepend (result, pango_attribute_copy (attr));
- }
-
- return g_slist_reverse (result);
-}
-
-/**
- * pango_attr_list_equal:
- * @list: a `PangoAttrList`
- * @other_list: the other `PangoAttrList`
- *
- * Checks whether @list and @other_list contain the same
- * attributes and whether those attributes apply to the
- * same ranges.
- *
- * Beware that this will return wrong values if any list
- * contains duplicates.
- *
- * Return value: %TRUE if the lists are equal, %FALSE if
- * they aren't
- *
- * Since: 1.46
- */
-gboolean
-pango_attr_list_equal (PangoAttrList *list,
- PangoAttrList *other_list)
-{
- GPtrArray *attrs, *other_attrs;
- guint64 skip_bitmask = 0;
- guint i;
-
- if (list == other_list)
- return TRUE;
-
- if (list == NULL || other_list == NULL)
- return FALSE;
-
- if (list->attributes == NULL || other_list->attributes == NULL)
- return list->attributes == other_list->attributes;
-
- attrs = list->attributes;
- other_attrs = other_list->attributes;
-
- if (attrs->len != other_attrs->len)
- return FALSE;
-
- for (i = 0; i < attrs->len; i++)
- {
- PangoAttribute *attr = g_ptr_array_index (attrs, i);
- gboolean attr_equal = FALSE;
- guint other_attr_index;
-
- for (other_attr_index = 0; other_attr_index < other_attrs->len; other_attr_index++)
- {
- PangoAttribute *other_attr = g_ptr_array_index (other_attrs, other_attr_index);
- guint64 other_attr_bitmask = other_attr_index < 64 ? 1 << other_attr_index : 0;
-
- if ((skip_bitmask & other_attr_bitmask) != 0)
- continue;
-
- if (attr->start_index == other_attr->start_index &&
- attr->end_index == other_attr->end_index &&
- pango_attribute_equal (attr, other_attr))
- {
- skip_bitmask |= other_attr_bitmask;
- attr_equal = TRUE;
- break;
- }
-
- }
-
- if (!attr_equal)
- return FALSE;
- }
-
- return TRUE;
-}
-
-gboolean
-_pango_attr_list_has_attributes (const PangoAttrList *list)
-{
- return list && list->attributes != NULL && list->attributes->len > 0;
-}
-
-/**
- * pango_attr_list_filter:
- * @list: a `PangoAttrList`
- * @func: (scope call) (closure data): callback function;
- * returns %TRUE if an attribute should be filtered out
- * @data: (closure): Data to be passed to @func
- *
- * Given a `PangoAttrList` and callback function, removes
- * any elements of @list for which @func returns %TRUE and
- * inserts them into a new list.
- *
- * Return value: (transfer full) (nullable): the new
- * `PangoAttrList` or %NULL if no attributes of the
- * given types were found
- *
- * Since: 1.2
- */
-PangoAttrList *
-pango_attr_list_filter (PangoAttrList *list,
- PangoAttrFilterFunc func,
- gpointer data)
-
-{
- PangoAttrList *new = NULL;
- guint i, p;
-
- g_return_val_if_fail (list != NULL, NULL);
-
- if (!list->attributes || list->attributes->len == 0)
- return NULL;
-
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
-
- if ((*func) (tmp_attr, data))
- {
- g_ptr_array_remove_index (list->attributes, i);
- i--; /* Need to look at this index again */
- p--;
-
- if (G_UNLIKELY (!new))
- {
- new = pango_attr_list_new ();
- new->attributes = g_ptr_array_new ();
- }
-
- g_ptr_array_add (new->attributes, tmp_attr);
- }
- }
-
- return new;
-}
-
-/* {{{ PangoAttrList serialization */
-
-/* We serialize attribute lists to strings. The format
- * is a comma-separated list of the attributes in the order
- * in which they are in the list, with each attribute having
- * this format:
- *
- * START END NICK VALUE
- *
- * Values that can contain a comma, such as font descriptions
- * are quoted with "".
- */
-
-static GType
-get_attr_value_type (PangoAttrType type)
-{
- switch ((int)type)
- {
- case PANGO_ATTR_STYLE: return PANGO_TYPE_STYLE;
- case PANGO_ATTR_WEIGHT: return PANGO_TYPE_WEIGHT;
- case PANGO_ATTR_VARIANT: return PANGO_TYPE_VARIANT;
- case PANGO_ATTR_STRETCH: return PANGO_TYPE_STRETCH;
- case PANGO_ATTR_GRAVITY: return PANGO_TYPE_GRAVITY;
- case PANGO_ATTR_GRAVITY_HINT: return PANGO_TYPE_GRAVITY_HINT;
- case PANGO_ATTR_UNDERLINE: return PANGO_TYPE_UNDERLINE;
- case PANGO_ATTR_OVERLINE: return PANGO_TYPE_OVERLINE;
- case PANGO_ATTR_BASELINE_SHIFT: return PANGO_TYPE_BASELINE_SHIFT;
- case PANGO_ATTR_FONT_SCALE: return PANGO_TYPE_FONT_SCALE;
- case PANGO_ATTR_TEXT_TRANSFORM: return PANGO_TYPE_TEXT_TRANSFORM;
- default: return G_TYPE_INVALID;
- }
-}
-
-static void
-append_enum_value (GString *str,
- GType type,
- int value)
-{
- GEnumClass *enum_class;
- GEnumValue *enum_value;
-
- enum_class = g_type_class_ref (type);
- enum_value = g_enum_get_value (enum_class, value);
- g_type_class_unref (enum_class);
-
- if (enum_value)
- g_string_append_printf (str, " %s", enum_value->value_nick);
- else
- g_string_append_printf (str, " %d", value);
-}
-
-static void
-attr_print (GString *str,
- PangoAttribute *attr)
-{
- const char *name;
-
- name = pango_attr_type_get_name (attr->type);
- if (!name)
- return;
-
- g_string_append_printf (str, "%u %u %s", attr->start_index, attr->end_index, name);
-
- switch (PANGO_ATTR_VALUE_TYPE (attr))
- {
- case PANGO_ATTR_VALUE_INT:
- if (attr->type == PANGO_ATTR_WEIGHT ||
- attr->type == PANGO_ATTR_STYLE ||
- attr->type == PANGO_ATTR_STRETCH ||
- attr->type == PANGO_ATTR_VARIANT ||
- attr->type == PANGO_ATTR_GRAVITY ||
- attr->type == PANGO_ATTR_GRAVITY_HINT ||
- attr->type == PANGO_ATTR_UNDERLINE ||
- attr->type == PANGO_ATTR_OVERLINE ||
- attr->type == PANGO_ATTR_BASELINE_SHIFT ||
- attr->type == PANGO_ATTR_FONT_SCALE ||
- attr->type == PANGO_ATTR_TEXT_TRANSFORM)
- append_enum_value (str, get_attr_value_type (attr->type), attr->int_value);
- else
- g_string_append_printf (str, " %d", attr->int_value);
- break;
-
- case PANGO_ATTR_VALUE_BOOLEAN:
- g_string_append (str, attr->int_value ? " true" : " false");
- break;
-
- case PANGO_ATTR_VALUE_STRING:
- g_string_append_printf (str, " \"%s\"", attr->str_value);
- break;
-
- case PANGO_ATTR_VALUE_LANGUAGE:
- g_string_append_printf (str, " %s", pango_language_to_string (attr->lang_value));
- break;
-
- case PANGO_ATTR_VALUE_FLOAT:
- {
- char buf[20];
- g_ascii_formatd (buf, 20, "%f", attr->double_value);
- g_string_append_printf (str, " %s", buf);
- }
- break;
-
- case PANGO_ATTR_VALUE_FONT_DESC:
- {
- char *s = pango_font_description_to_string (attr->font_value);
- g_string_append_printf (str, " \"%s\"", s);
- g_free (s);
- }
- break;
-
- case PANGO_ATTR_VALUE_COLOR:
- {
- char *s = pango_color_to_string (&attr->color_value);
- g_string_append_printf (str, " %s", s);
- g_free (s);
- }
- break;
-
- case PANGO_ATTR_VALUE_POINTER:
- {
- char *s = pango_attr_value_serialize (attr);
- g_string_append_printf (str, " %s", s);
- g_free (s);
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-/**
- * pango_attr_list_to_string:
- * @list: a `PangoAttrList`
- *
- * Serializes a `PangoAttrList` to a string.
- *
- * No guarantees are made about the format of the string,
- * it may change between Pango versions.
- *
- * The intended use of this function is testing and
- * debugging. The format is not meant as a permanent
- * storage format.
- *
- * Returns: (transfer full): a newly allocated string
- * Since: 1.50
- */
-char *
-pango_attr_list_to_string (PangoAttrList *list)
-{
- GString *s;
-
- s = g_string_new ("");
-
- if (list->attributes)
- for (int i = 0; i < list->attributes->len; i++)
- {
- PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
-
- if (i > 0)
- g_string_append (s, "\n");
- attr_print (s, attr);
- }
-
- return g_string_free (s, FALSE);
-}
-
-static PangoAttrType
-get_attr_type_by_nick (const char *nick,
- int len)
-{
- GEnumClass *enum_class;
-
- enum_class = g_type_class_ref (pango_attr_type_get_type ());
- for (GEnumValue *ev = enum_class->values; ev->value_name; ev++)
- {
- if (ev->value_nick && strncmp (ev->value_nick, nick, len) == 0)
- {
- g_type_class_unref (enum_class);
- return (PangoAttrType) ev->value;
- }
- }
-
- g_type_class_unref (enum_class);
- return PANGO_ATTR_INVALID;
-}
-
-static int
-get_attr_value (PangoAttrType type,
- const char *str,
- int len)
-{
- GEnumClass *enum_class;
- char *endp;
- int value;
-
- enum_class = g_type_class_ref (get_attr_value_type (type));
- for (GEnumValue *ev = enum_class->values; ev->value_name; ev++)
- {
- if (ev->value_nick && strncmp (ev->value_nick, str, len) == 0)
- {
- g_type_class_unref (enum_class);
- return ev->value;
- }
- }
- g_type_class_unref (enum_class);
-
- value = g_ascii_strtoll (str, &endp, 10);
- if (endp - str == len)
- return value;
-
- return -1;
-}
-
-static gboolean
-is_valid_end_char (char c)
-{
- return c == ',' || c == '\n' || c == '\0';
-}
-
-/**
- * pango_attr_list_from_string:
- * @text: a string
- *
- * Deserializes a `PangoAttrList` from a string.
- *
- * This is the counterpart to [method@Pango.AttrList.to_string].
- * See that functions for details about the format.
- *
- * Returns: (transfer full) (nullable): a new `PangoAttrList`
- * Since: 1.50
- */
-PangoAttrList *
-pango_attr_list_from_string (const char *text)
-{
- PangoAttrList *list;
- const char *p;
-
- g_return_val_if_fail (text != NULL, NULL);
-
- list = pango_attr_list_new ();
-
- if (*text == '\0')
- return list;
-
- list->attributes = g_ptr_array_new ();
-
- p = text + strspn (text, " \t\n");
- while (*p)
- {
- char *endp;
- gint64 start_index;
- gint64 end_index;
- char *str;
- PangoAttrType attr_type;
- PangoAttribute *attr;
- PangoLanguage *lang;
- gint64 integer;
- PangoFontDescription *desc;
- PangoColor color;
- double num;
-
- start_index = g_ascii_strtoll (p, &endp, 10);
- if (*endp != ' ')
- goto fail;
-
- p = endp + strspn (endp, " ");
- if (!*p)
- goto fail;
-
- end_index = g_ascii_strtoll (p, &endp, 10);
- if (*endp != ' ')
- goto fail;
-
- p = endp + strspn (endp, " ");
-
- endp = (char *)p + strcspn (p, " ");
- attr_type = get_attr_type_by_nick (p, endp - p);
-
- p = endp + strspn (endp, " ");
- if (*p == '\0')
- goto fail;
-
-#define INT_ATTR(name,type) \
- integer = g_ascii_strtoll (p, &endp, 10); \
- if (!is_valid_end_char (*endp)) goto fail; \
- attr = pango_attr_##name##_new ((type)integer);
-
-#define BOOLEAN_ATTR(name,type) \
- if (strncmp (p, "true", strlen ("true")) == 0) \
- { \
- integer = 1; \
- endp = (char *)(p + strlen ("true")); \
- } \
- else if (strncmp (p, "false", strlen ("false")) == 0) \
- { \
- integer = 0; \
- endp = (char *)(p + strlen ("false")); \
- } \
- else \
- integer = g_ascii_strtoll (p, &endp, 10); \
- if (!is_valid_end_char (*endp)) goto fail; \
- attr = pango_attr_##name##_new ((type)integer);
-
-#define ENUM_ATTR(name, type, min, max) \
- endp = (char *)p + strcspn (p, ",\n"); \
- integer = get_attr_value (attr_type, p, endp - p); \
- attr = pango_attr_##name##_new ((type) CLAMP (integer, min, max));
-
-#define FLOAT_ATTR(name) \
- num = g_ascii_strtod (p, &endp); \
- if (!is_valid_end_char (*endp)) goto fail; \
- attr = pango_attr_##name##_new ((float)num);
-
-#define COLOR_ATTR(name) \
- endp = (char *)p + strcspn (p, ",\n"); \
- if (!is_valid_end_char (*endp)) goto fail; \
- str = g_strndup (p, endp - p); \
- if (!pango_color_parse (&color, str)) \
- { \
- g_free (str); \
- goto fail; \
- } \
- attr = pango_attr_##name##_new (color.red, color.green, color.blue); \
- g_free (str);
-
- switch (attr_type)
- {
- case PANGO_ATTR_INVALID:
- pango_attr_list_unref (list);
- return NULL;
-
- case PANGO_ATTR_LANGUAGE:
- endp = (char *)p + strcspn (p, ",\n");
- if (!is_valid_end_char (*endp)) goto fail;
- str = g_strndup (p, endp - p);
- lang = pango_language_from_string (str);
- attr = pango_attr_language_new (lang);
- g_free (str);
- break;
-
- case PANGO_ATTR_FAMILY:
- p++;
- endp = strchr (p, '"');
- if (!endp) goto fail;
- str = g_strndup (p, endp - p);
- attr = pango_attr_family_new (str);
- g_free (str);
- endp++;
- if (!is_valid_end_char (*endp)) goto fail;
- break;
-
- case PANGO_ATTR_STYLE:
- ENUM_ATTR(style, PangoStyle, PANGO_STYLE_NORMAL, PANGO_STYLE_ITALIC);
- break;
-
- case PANGO_ATTR_WEIGHT:
- ENUM_ATTR(weight, PangoWeight, PANGO_WEIGHT_THIN, PANGO_WEIGHT_ULTRAHEAVY);
- break;
-
- case PANGO_ATTR_VARIANT:
- ENUM_ATTR(variant, PangoVariant, PANGO_VARIANT_NORMAL, PANGO_VARIANT_TITLE_CAPS);
- break;
-
- case PANGO_ATTR_STRETCH:
- ENUM_ATTR(stretch, PangoStretch, PANGO_STRETCH_ULTRA_CONDENSED, PANGO_STRETCH_ULTRA_EXPANDED);
- break;
-
- case PANGO_ATTR_SIZE:
- INT_ATTR(size, int);
- break;
-
- case PANGO_ATTR_FONT_DESC:
- p++;
- endp = strchr (p, '"');
- if (!endp) goto fail;
- str = g_strndup (p, endp - p);
- desc = pango_font_description_from_string (str);
- attr = pango_attr_font_desc_new (desc);
- pango_font_description_free (desc);
- g_free (str);
- endp++;
- if (!is_valid_end_char (*endp)) goto fail;
- break;
-
- case PANGO_ATTR_FOREGROUND:
- COLOR_ATTR(foreground);
- break;
-
- case PANGO_ATTR_BACKGROUND:
- COLOR_ATTR(background);
- break;
-
- case PANGO_ATTR_UNDERLINE:
- ENUM_ATTR(underline, PangoUnderline, PANGO_UNDERLINE_NONE, PANGO_UNDERLINE_ERROR_LINE);
- break;
-
- case PANGO_ATTR_STRIKETHROUGH:
- BOOLEAN_ATTR(strikethrough, gboolean);
- break;
-
- case PANGO_ATTR_RISE:
- INT_ATTR(rise, int);
- break;
-
- case PANGO_ATTR_SCALE:
- FLOAT_ATTR(scale);
- break;
-
- case PANGO_ATTR_FALLBACK:
- BOOLEAN_ATTR(fallback, gboolean);
- break;
-
- case PANGO_ATTR_LETTER_SPACING:
- INT_ATTR(letter_spacing, int);
- break;
-
- case PANGO_ATTR_UNDERLINE_COLOR:
- COLOR_ATTR(underline_color);
- break;
-
- case PANGO_ATTR_STRIKETHROUGH_COLOR:
- COLOR_ATTR(strikethrough_color);
- break;
-
- case PANGO_ATTR_ABSOLUTE_SIZE:
- integer = g_ascii_strtoll (p, &endp, 10);
- if (!is_valid_end_char (*endp)) goto fail;
- attr = pango_attr_size_new_absolute (integer);
- break;
-
- case PANGO_ATTR_GRAVITY:
- ENUM_ATTR(gravity, PangoGravity, PANGO_GRAVITY_SOUTH, PANGO_GRAVITY_WEST);
- break;
-
- case PANGO_ATTR_FONT_FEATURES:
- p++;
- endp = strchr (p, '"');
- if (!endp) goto fail;
- str = g_strndup (p, endp - p);
- attr = pango_attr_font_features_new (str);
- g_free (str);
- endp++;
- if (!is_valid_end_char (*endp)) goto fail;
- break;
-
- case PANGO_ATTR_GRAVITY_HINT:
- ENUM_ATTR(gravity_hint, PangoGravityHint, PANGO_GRAVITY_HINT_NATURAL, PANGO_GRAVITY_HINT_LINE);
- break;
-
- case PANGO_ATTR_FOREGROUND_ALPHA:
- INT_ATTR(foreground_alpha, int);
- break;
-
- case PANGO_ATTR_BACKGROUND_ALPHA:
- INT_ATTR(background_alpha, int);
- break;
-
- case PANGO_ATTR_ALLOW_BREAKS:
- BOOLEAN_ATTR(allow_breaks, gboolean);
- break;
-
- case PANGO_ATTR_SHOW:
- INT_ATTR(show, PangoShowFlags);
- break;
-
- case PANGO_ATTR_INSERT_HYPHENS:
- BOOLEAN_ATTR(insert_hyphens, gboolean);
- break;
-
- case PANGO_ATTR_OVERLINE:
- ENUM_ATTR(overline, PangoOverline, PANGO_OVERLINE_NONE, PANGO_OVERLINE_SINGLE);
- break;
-
- case PANGO_ATTR_OVERLINE_COLOR:
- COLOR_ATTR(overline_color);
- break;
-
- case PANGO_ATTR_LINE_HEIGHT:
- FLOAT_ATTR(line_height);
- break;
-
- case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
- integer = g_ascii_strtoll (p, &endp, 10);
- if (!is_valid_end_char (*endp)) goto fail;
- attr = pango_attr_line_height_new_absolute (integer);
- break;
-
- case PANGO_ATTR_TEXT_TRANSFORM:
- ENUM_ATTR(text_transform, PangoTextTransform, PANGO_TEXT_TRANSFORM_NONE, PANGO_TEXT_TRANSFORM_CAPITALIZE);
- break;
-
- case PANGO_ATTR_WORD:
- integer = g_ascii_strtoll (p, &endp, 10);
- if (!is_valid_end_char (*endp)) goto fail;
- attr = pango_attr_word_new ();
- break;
-
- case PANGO_ATTR_SENTENCE:
- integer = g_ascii_strtoll (p, &endp, 10);
- if (!is_valid_end_char (*endp)) goto fail;
- attr = pango_attr_sentence_new ();
- break;
-
- case PANGO_ATTR_BASELINE_SHIFT:
- ENUM_ATTR(baseline_shift, PangoBaselineShift, 0, G_MAXINT);
- break;
-
- case PANGO_ATTR_FONT_SCALE:
- ENUM_ATTR(font_scale, PangoFontScale, PANGO_FONT_SCALE_NONE, PANGO_FONT_SCALE_SMALL_CAPS);
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- attr->start_index = (guint)start_index;
- attr->end_index = (guint)end_index;
- g_ptr_array_add (list->attributes, attr);
-
- p = endp;
- if (*p)
- {
- if (*p == ',')
- p++;
- p += strspn (p, " \n");
- }
- }
-
- goto success;
-
-fail:
- pango_attr_list_unref (list);
- list = NULL;
-
-success:
- return list;
-}
-
-/* }}} */
-/* {{{ Attribute Iterator */
-
-G_DEFINE_BOXED_TYPE (PangoAttrIterator,
- pango_attr_iterator,
- pango_attr_iterator_copy,
- pango_attr_iterator_destroy)
-
-void
-_pango_attr_list_get_iterator (PangoAttrList *list,
- PangoAttrIterator *iterator)
-{
- iterator->attribute_stack = NULL;
- iterator->attrs = list->attributes;
- iterator->n_attrs = iterator->attrs ? iterator->attrs->len : 0;
-
- iterator->attr_index = 0;
- iterator->start_index = 0;
- iterator->end_index = 0;
-
- if (!pango_attr_iterator_next (iterator))
- iterator->end_index = G_MAXUINT;
-}
-
-/**
- * pango_attr_list_get_iterator:
- * @list: a `PangoAttrList`
- *
- * Create a iterator initialized to the beginning of the list.
- *
- * @list must not be modified until this iterator is freed.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttrIterator`, which should be freed with
- * [method@Pango.AttrIterator.destroy]
- */
-PangoAttrIterator *
-pango_attr_list_get_iterator (PangoAttrList *list)
-{
- PangoAttrIterator *iterator;
-
- g_return_val_if_fail (list != NULL, NULL);
-
- iterator = g_slice_new (PangoAttrIterator);
- _pango_attr_list_get_iterator (list, iterator);
-
- return iterator;
-}
-
-/**
- * pango_attr_iterator_range:
- * @iterator: a PangoAttrIterator
- * @start: (out): location to store the start of the range
- * @end: (out): location to store the end of the range
- *
- * Get the range of the current segment.
- *
- * Note that the stored return values are signed, not unsigned
- * like the values in `PangoAttribute`. To deal with this API
- * oversight, stored return values that wouldn't fit into
- * a signed integer are clamped to %G_MAXINT.
- */
-void
-pango_attr_iterator_range (PangoAttrIterator *iterator,
- gint *start,
- gint *end)
-{
- g_return_if_fail (iterator != NULL);
-
- if (start)
- *start = MIN (iterator->start_index, G_MAXINT);
- if (end)
- *end = MIN (iterator->end_index, G_MAXINT);
-}
-
-/**
- * pango_attr_iterator_next:
- * @iterator: a `PangoAttrIterator`
- *
- * Advance the iterator until the next change of style.
- *
- * Return value: %FALSE if the iterator is at the end
- * of the list, otherwise %TRUE
- */
-gboolean
-pango_attr_iterator_next (PangoAttrIterator *iterator)
-{
- int i;
-
- g_return_val_if_fail (iterator != NULL, FALSE);
-
- if (iterator->attr_index >= iterator->n_attrs &&
- (!iterator->attribute_stack || iterator->attribute_stack->len == 0))
- return FALSE;
-
- iterator->start_index = iterator->end_index;
- iterator->end_index = G_MAXUINT;
-
- if (iterator->attribute_stack)
- {
- for (i = iterator->attribute_stack->len - 1; i>= 0; i--)
- {
- const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
-
- if (attr->end_index == iterator->start_index)
- g_ptr_array_remove_index (iterator->attribute_stack, i); /* Can't use index_fast :( */
- else
- iterator->end_index = MIN (iterator->end_index, attr->end_index);
- }
- }
-
- while (1)
- {
- PangoAttribute *attr;
-
- if (iterator->attr_index >= iterator->n_attrs)
- break;
-
- attr = g_ptr_array_index (iterator->attrs, iterator->attr_index);
-
- if (attr->start_index != iterator->start_index)
- break;
-
- if (attr->end_index > iterator->start_index)
- {
- if (G_UNLIKELY (!iterator->attribute_stack))
- iterator->attribute_stack = g_ptr_array_new ();
-
- g_ptr_array_add (iterator->attribute_stack, attr);
-
- iterator->end_index = MIN (iterator->end_index, attr->end_index);
- }
-
- iterator->attr_index++; /* NEXT! */
- }
-
- if (iterator->attr_index < iterator->n_attrs)
- {
- PangoAttribute *attr = g_ptr_array_index (iterator->attrs, iterator->attr_index);
-
- iterator->end_index = MIN (iterator->end_index, attr->start_index);
- }
-
- return TRUE;
-}
-
-/**
- * pango_attr_iterator_copy:
- * @iterator: a `PangoAttrIterator`
- *
- * Copy a `PangoAttrIterator`.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttrIterator`, which should be freed with
- * [method@Pango.AttrIterator.destroy]
- */
-PangoAttrIterator *
-pango_attr_iterator_copy (PangoAttrIterator *iterator)
-{
- PangoAttrIterator *copy;
-
- g_return_val_if_fail (iterator != NULL, NULL);
-
- copy = g_slice_new (PangoAttrIterator);
-
- *copy = *iterator;
-
- if (iterator->attribute_stack)
- copy->attribute_stack = g_ptr_array_copy (iterator->attribute_stack, NULL, NULL);
- else
- copy->attribute_stack = NULL;
-
- return copy;
-}
-
-void
-_pango_attr_iterator_destroy (PangoAttrIterator *iterator)
-{
- if (iterator->attribute_stack)
- g_ptr_array_free (iterator->attribute_stack, TRUE);
-}
-
-/**
- * pango_attr_iterator_destroy:
- * @iterator: a `PangoAttrIterator`
- *
- * Destroy a `PangoAttrIterator` and free all associated memory.
- */
-void
-pango_attr_iterator_destroy (PangoAttrIterator *iterator)
-{
- g_return_if_fail (iterator != NULL);
-
- _pango_attr_iterator_destroy (iterator);
- g_slice_free (PangoAttrIterator, iterator);
-}
-
-/**
- * pango_attr_iterator_get:
- * @iterator: a `PangoAttrIterator`
- * @type: the type of attribute to find
- *
- * Find the current attribute of a particular type
- * at the iterator location.
- *
- * When multiple attributes of the same type overlap,
- * the attribute whose range starts closest to the
- * current location is used.
- *
- * Return value: (nullable) (transfer none): the current
- * attribute of the given type, or %NULL if no attribute
- * of that type applies to the current location.
- */
-PangoAttribute *
-pango_attr_iterator_get (PangoAttrIterator *iterator,
- PangoAttrType type)
-{
- int i;
-
- g_return_val_if_fail (iterator != NULL, NULL);
-
- if (!iterator->attribute_stack)
- return NULL;
-
- for (i = iterator->attribute_stack->len - 1; i>= 0; i--)
- {
- PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
-
- if (attr->type == type)
- return attr;
- }
-
- return NULL;
-}
-
-/**
- * pango_attr_iterator_get_font:
- * @iterator: a `PangoAttrIterator`
- * @desc: a `PangoFontDescription` to fill in with the current
- * values. The family name in this structure will be set using
- * [method@Pango.FontDescription.set_family_static] using
- * values from an attribute in the `PangoAttrList` associated
- * with the iterator, so if you plan to keep it around, you
- * must call:
- * `pango_font_description_set_family (desc, pango_font_description_get_family (desc))`.
- * @language: (out) (optional): location to store language tag
- * for item, or %NULL if none is found.
- * @extra_attrs: (out) (optional) (element-type Pango.Attribute) (transfer full):
- * location in which to store a list of non-font attributes
- * at the the current position; only the highest priority
- * value of each attribute will be added to this list. In
- * order to free this value, you must call
- * [method@Pango.Attribute.destroy] on each member.
- *
- * Get the font and other attributes at the current
- * iterator position.
- */
-void
-pango_attr_iterator_get_font (PangoAttrIterator *iterator,
- PangoFontDescription *desc,
- PangoLanguage **language,
- GSList **extra_attrs)
-{
- PangoFontMask mask = 0;
- gboolean have_language = FALSE;
- gdouble scale = 0;
- gboolean have_scale = FALSE;
- int i;
-
- g_return_if_fail (iterator != NULL);
- g_return_if_fail (desc != NULL);
-
- if (language)
- *language = NULL;
-
- if (extra_attrs)
- *extra_attrs = NULL;
-
- if (!iterator->attribute_stack)
- return;
-
- for (i = iterator->attribute_stack->len - 1; i >= 0; i--)
- {
- const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
-
- switch ((int) attr->type)
- {
- case PANGO_ATTR_FONT_DESC:
- {
- PangoFontMask new_mask = pango_font_description_get_set_fields (attr->font_value) & ~mask;
- mask |= new_mask;
- pango_font_description_unset_fields (desc, new_mask);
- pango_font_description_merge_static (desc, attr->font_value, FALSE);
-
- break;
- }
- case PANGO_ATTR_FAMILY:
- if (!(mask & PANGO_FONT_MASK_FAMILY))
- {
- mask |= PANGO_FONT_MASK_FAMILY;
- pango_font_description_set_family (desc, attr->str_value);
- }
- break;
- case PANGO_ATTR_STYLE:
- if (!(mask & PANGO_FONT_MASK_STYLE))
- {
- mask |= PANGO_FONT_MASK_STYLE;
- pango_font_description_set_style (desc, attr->int_value);
- }
- break;
- case PANGO_ATTR_VARIANT:
- if (!(mask & PANGO_FONT_MASK_VARIANT))
- {
- mask |= PANGO_FONT_MASK_VARIANT;
- pango_font_description_set_variant (desc, attr->int_value);
- }
- break;
- case PANGO_ATTR_WEIGHT:
- if (!(mask & PANGO_FONT_MASK_WEIGHT))
- {
- mask |= PANGO_FONT_MASK_WEIGHT;
- pango_font_description_set_weight (desc, attr->int_value);
- }
- break;
- case PANGO_ATTR_STRETCH:
- if (!(mask & PANGO_FONT_MASK_STRETCH))
- {
- mask |= PANGO_FONT_MASK_STRETCH;
- pango_font_description_set_stretch (desc, attr->int_value);
- }
- break;
- case PANGO_ATTR_SIZE:
- if (!(mask & PANGO_FONT_MASK_SIZE))
- {
- mask |= PANGO_FONT_MASK_SIZE;
- pango_font_description_set_size (desc, attr->int_value);
- }
- break;
- case PANGO_ATTR_ABSOLUTE_SIZE:
- if (!(mask & PANGO_FONT_MASK_SIZE))
- {
- mask |= PANGO_FONT_MASK_SIZE;
- pango_font_description_set_absolute_size (desc, attr->int_value);
- }
- break;
- case PANGO_ATTR_SCALE:
- if (!have_scale)
- {
- have_scale = TRUE;
- scale = attr->double_value;
- }
- break;
- case PANGO_ATTR_LANGUAGE:
- if (language)
- {
- if (!have_language)
- {
- have_language = TRUE;
- *language = attr->lang_value;
- }
- }
- break;
- default:
- if (extra_attrs)
- {
- gboolean found = FALSE;
-
- /* Hack: special-case FONT_FEATURES, BASELINE_SHIFT and FONT_SCALE.
- * We don't want these to accumulate, not override each other,
- * so we never merge them.
- * This needs to be handled more systematically.
- */
- if (attr->type != PANGO_ATTR_FONT_FEATURES &&
- attr->type != PANGO_ATTR_BASELINE_SHIFT &&
- attr->type != PANGO_ATTR_FONT_SCALE)
- {
- GSList *tmp_list = *extra_attrs;
- while (tmp_list)
- {
- PangoAttribute *old_attr = tmp_list->data;
- if (attr->type == old_attr->type)
- {
- found = TRUE;
- break;
- }
-
- tmp_list = tmp_list->next;
- }
- }
-
- if (!found)
- *extra_attrs = g_slist_prepend (*extra_attrs, pango_attribute_copy (attr));
- }
- }
- }
-
- if (have_scale)
- {
- /* We need to use a local variable to ensure that the compiler won't
- * implicitly cast it to integer while the result is kept in registers,
- * leading to a wrong approximation in i386 (with 387 FPU)
- */
- volatile double size = scale * pango_font_description_get_size (desc);
-
- if (pango_font_description_get_size_is_absolute (desc))
- pango_font_description_set_absolute_size (desc, size);
- else
- pango_font_description_set_size (desc, size);
- }
-}
-
-/**
- * pango_attr_iterator_get_attrs:
- * @iterator: a `PangoAttrIterator`
- *
- * Gets a list of all attributes at the current position of the
- * iterator.
- *
- * Return value: (element-type Pango.Attribute) (transfer full):
- * a list of all attributes for the current range. To free
- * this value, call [method@Pango.Attribute.destroy] on each
- * value and g_slist_free() on the list.
- *
- * Since: 1.2
- */
-GSList *
-pango_attr_iterator_get_attrs (PangoAttrIterator *iterator)
-{
- GSList *attrs = NULL;
- int i;
-
- if (!iterator->attribute_stack ||
- iterator->attribute_stack->len == 0)
- return NULL;
-
- for (i = iterator->attribute_stack->len - 1; i >= 0; i--)
- {
- PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i);
- GSList *tmp_list2;
- gboolean found = FALSE;
-
- if (attr->type != PANGO_ATTR_FONT_DESC &&
- attr->type != PANGO_ATTR_BASELINE_SHIFT &&
- attr->type != PANGO_ATTR_FONT_SCALE)
- for (tmp_list2 = attrs; tmp_list2; tmp_list2 = tmp_list2->next)
- {
- PangoAttribute *old_attr = tmp_list2->data;
- if (attr->type == old_attr->type)
- {
- found = TRUE;
- break;
- }
- }
-
- if (!found)
- attrs = g_slist_prepend (attrs, pango_attribute_copy (attr));
- }
-
- return attrs;
-}
-
-gboolean
-pango_attr_iterator_advance (PangoAttrIterator *iterator,
- int index)
-{
- int start_range, end_range;
-
- pango_attr_iterator_range (iterator, &start_range, &end_range);
-
- while (index >= end_range)
- {
- if (!pango_attr_iterator_next (iterator))
- return FALSE;
- pango_attr_iterator_range (iterator, &start_range, &end_range);
- }
-
- if (start_range > index)
- g_warning ("pango_attr_iterator_advance(): iterator had already "
- "moved beyond the index");
-
- return TRUE;
-}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 9b679e95..0dc9146d 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -19,80 +19,60 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef __PANGO_ATTRIBUTES_H__
-#define __PANGO_ATTRIBUTES_H__
+#pragma once
#include <pango/pango-font.h>
#include <pango/pango-color.h>
-#include <glib-object.h>
+#include <pango/pango-attr.h>
G_BEGIN_DECLS
-typedef struct _PangoAttribute PangoAttribute;
-typedef struct _PangoAttrClass PangoAttrClass;
-
-typedef enum
-{
- PANGO_ATTR_VALUE_STRING,
- PANGO_ATTR_VALUE_INT,
- PANGO_ATTR_VALUE_BOOLEAN,
- PANGO_ATTR_VALUE_FLOAT,
- PANGO_ATTR_VALUE_COLOR,
- PANGO_ATTR_VALUE_LANGUAGE,
- PANGO_ATTR_VALUE_FONT_DESC,
- PANGO_ATTR_VALUE_POINTER
-} PangoAttrValueType;
-
#define PANGO_ATTR_TYPE(value) (PANGO_ATTR_VALUE_##value | (__COUNTER__ << 8))
-#define PANGO_ATTR_TYPE_VALUE_TYPE(type) ((PangoAttrValueType)((type) & 0xff))
-#define PANGO_ATTR_VALUE_TYPE(attr) PANGO_ATTR_TYPE_VALUE_TYPE ((attr)->type)
-
/**
* PangoAttrType:
* @PANGO_ATTR_INVALID: does not happen
- * @PANGO_ATTR_LANGUAGE: language ([struct@Pango.AttrLanguage])
- * @PANGO_ATTR_FAMILY: font family name list ([struct@Pango.AttrString])
- * @PANGO_ATTR_STYLE: font slant style ([struct@Pango.AttrInt])
- * @PANGO_ATTR_WEIGHT: font weight ([struct@Pango.AttrInt])
- * @PANGO_ATTR_VARIANT: font variant (normal or small caps) ([struct@Pango.AttrInt])
- * @PANGO_ATTR_STRETCH: font stretch ([struct@Pango.AttrInt])
- * @PANGO_ATTR_SIZE: font size in points scaled by %PANGO_SCALE ([struct@Pango.AttrInt])
- * @PANGO_ATTR_FONT_DESC: font description ([struct@Pango.AttrFontDesc])
- * @PANGO_ATTR_FOREGROUND: foreground color ([struct@Pango.AttrColor])
- * @PANGO_ATTR_BACKGROUND: background color ([struct@Pango.AttrColor])
- * @PANGO_ATTR_UNDERLINE: whether the text has an underline ([struct@Pango.AttrInt])
- * @PANGO_ATTR_STRIKETHROUGH: whether the text is struck-through ([struct@Pango.AttrInt])
- * @PANGO_ATTR_RISE: baseline displacement ([struct@Pango.AttrInt])
- * @PANGO_ATTR_SCALE: font size scale factor ([struct@Pango.AttrFloat])
- * @PANGO_ATTR_FALLBACK: whether fallback is enabled ([struct@Pango.AttrInt])
- * @PANGO_ATTR_LETTER_SPACING: letter spacing ([struct@PangoAttrInt])
- * @PANGO_ATTR_UNDERLINE_COLOR: underline color ([struct@Pango.AttrColor])
- * @PANGO_ATTR_STRIKETHROUGH_COLOR: strikethrough color ([struct@Pango.AttrColor])
- * @PANGO_ATTR_ABSOLUTE_SIZE: font size in pixels scaled by %PANGO_SCALE ([struct@Pango.AttrInt])
- * @PANGO_ATTR_GRAVITY: base text gravity ([struct@Pango.AttrInt])
- * @PANGO_ATTR_GRAVITY_HINT: gravity hint ([struct@Pango.AttrInt])
- * @PANGO_ATTR_FONT_FEATURES: OpenType font features ([struct@Pango.AttrFontFeatures]). Since 1.38
- * @PANGO_ATTR_FOREGROUND_ALPHA: foreground alpha ([struct@Pango.AttrInt]). Since 1.38
- * @PANGO_ATTR_BACKGROUND_ALPHA: background alpha ([struct@Pango.AttrInt]). Since 1.38
- * @PANGO_ATTR_ALLOW_BREAKS: whether breaks are allowed ([struct@Pango.AttrInt]). Since 1.44
- * @PANGO_ATTR_SHOW: how to render invisible characters ([struct@Pango.AttrInt]). Since 1.44
- * @PANGO_ATTR_INSERT_HYPHENS: whether to insert hyphens at intra-word line breaks ([struct@Pango.AttrInt]). Since 1.44
- * @PANGO_ATTR_OVERLINE: whether the text has an overline ([struct@Pango.AttrInt]). Since 1.46
- * @PANGO_ATTR_OVERLINE_COLOR: overline color ([struct@Pango.AttrColor]). Since 1.46
- * @PANGO_ATTR_LINE_HEIGHT: line height factor ([struct@Pango.AttrFloat]). Since: 1.50
- * @PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: line height ([struct@Pango.AttrInt]). Since: 1.50
- * @PANGO_ATTR_WORD: override segmentation to classify the range of the attribute as a single word ([struct@Pango.AttrInt]). Since 1.50
- * @PANGO_ATTR_SENTENCE: override segmentation to classify the range of the attribute as a single sentence ([struct@Pango.AttrInt]). Since 1.50
- * @PANGO_ATTR_BASELINE_SHIFT: baseline displacement ([struct@Pango.AttrInt]). Since 1.50
- * @PANGO_ATTR_FONT_SCALE: font-relative size change ([struct@Pango.AttrInt]). Since 1.50
- *
- * The `PangoAttrType` distinguishes between different types of attributes.
+ * @PANGO_ATTR_LANGUAGE: language
+ * @PANGO_ATTR_FAMILY: font family name
+ * @PANGO_ATTR_STYLE: font style
+ * @PANGO_ATTR_WEIGHT: font weight
+ * @PANGO_ATTR_VARIANT: font variant
+ * @PANGO_ATTR_STRETCH: font stretch
+ * @PANGO_ATTR_SIZE: font size in points scaled by `PANGO_SCALE`
+ * @PANGO_ATTR_FONT_DESC: font description
+ * @PANGO_ATTR_FOREGROUND: foreground color
+ * @PANGO_ATTR_BACKGROUND: background color
+ * @PANGO_ATTR_UNDERLINE: whether the text has an underline
+ * @PANGO_ATTR_STRIKETHROUGH: whether the text is struck-through
+ * @PANGO_ATTR_RISE: baseline displacement
+ * @PANGO_ATTR_SCALE: font size scale factor
+ * @PANGO_ATTR_FALLBACK: whether font fallback is enabled
+ * @PANGO_ATTR_LETTER_SPACING: letter spacing in Pango units
+ * @PANGO_ATTR_UNDERLINE_COLOR: underline color
+ * @PANGO_ATTR_STRIKETHROUGH_COLOR: strikethrough color
+ * @PANGO_ATTR_ABSOLUTE_SIZE: font size in pixels scaled by `PANGO_SCALE`
+ * @PANGO_ATTR_GRAVITY: base text gravity
+ * @PANGO_ATTR_GRAVITY_HINT: gravity hint
+ * @PANGO_ATTR_FONT_FEATURES: OpenType font features
+ * @PANGO_ATTR_FOREGROUND_ALPHA: foreground alpha
+ * @PANGO_ATTR_BACKGROUND_ALPHA: background alpha
+ * @PANGO_ATTR_ALLOW_BREAKS: whether line breaks are allowed
+ * @PANGO_ATTR_SHOW: how to render invisible characters
+ * @PANGO_ATTR_INSERT_HYPHENS: whether to insert hyphens at intra-word line breaks
+ * @PANGO_ATTR_OVERLINE: whether the text has an overline
+ * @PANGO_ATTR_OVERLINE_COLOR: overline color
+ * @PANGO_ATTR_LINE_HEIGHT: line height factor
+ * @PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: line height in Pango units
+ * @PANGO_ATTR_WORD: mark the range of the attribute as a single word
+ * @PANGO_ATTR_SENTENCE: mark the range of the attribute as a single sentence
+ * @PANGO_ATTR_BASELINE_SHIFT: baseline displacement
+ * @PANGO_ATTR_FONT_SCALE: font-relative size change
+ *
+ * The `PangoAttrType` enumeration contains predefined types for attributes.
*
* Along with the predefined values, it is possible to allocate additional
* values for custom attributes using [func@AttrType.register]. The predefined
- * values are given below. The type of structure used to store the attribute is
- * listed in parentheses after the description.
+ * values are given below.
*/
typedef enum
{
@@ -137,6 +117,34 @@ typedef enum
#undef PANGO_ATTR_TYPE
+
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_language_new (PangoLanguage *language);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_family_new (const char *family);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_foreground_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_background_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_size_new (int size);
+PANGO_AVAILABLE_IN_1_8
+PangoAttribute * pango_attr_size_new_absolute (int size);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_style_new (PangoStyle style);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_weight_new (PangoWeight weight);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_variant_new (PangoVariant variant);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_stretch_new (PangoStretch stretch);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_font_desc_new (const PangoFontDescription *desc);
+
/**
* PangoUnderline:
* @PANGO_UNDERLINE_NONE: no underline should be drawn
@@ -180,61 +188,20 @@ typedef enum {
PANGO_UNDERLINE_ERROR_LINE
} PangoUnderline;
-
-/**
- * PangoOverline:
- * @PANGO_OVERLINE_NONE: no overline should be drawn
- * @PANGO_OVERLINE_SINGLE: Draw a single line above the ink
- * extents of the text being underlined.
- *
- * The `PangoOverline` enumeration is used to specify whether text
- * should be overlined, and if so, the type of line.
- *
- * Since: 1.46
- */
-typedef enum {
- PANGO_OVERLINE_NONE,
- PANGO_OVERLINE_SINGLE
-} PangoOverline;
-
-/**
- * PangoShowFlags:
- * @PANGO_SHOW_NONE: No special treatment for invisible characters
- * @PANGO_SHOW_SPACES: Render spaces, tabs and newlines visibly
- * @PANGO_SHOW_LINE_BREAKS: Render line breaks visibly
- * @PANGO_SHOW_IGNORABLES: Render default-ignorable Unicode
- * characters visibly
- *
- * These flags affect how Pango treats characters that are normally
- * not visible in the output.
- *
- * Since: 1.44
- */
-typedef enum {
- PANGO_SHOW_NONE = 0,
- PANGO_SHOW_SPACES = 1 << 0,
- PANGO_SHOW_LINE_BREAKS = 1 << 1,
- PANGO_SHOW_IGNORABLES = 1 << 2
-} PangoShowFlags;
-
-/**
- * PangoTextTransform:
- * @PANGO_TEXT_TRANSFORM_NONE: Leave text unchanged
- * @PANGO_TEXT_TRANSFORM_LOWERCASE: Display letters and numbers as lowercase
- * @PANGO_TEXT_TRANSFORM_UPPERCASE: Display letters and numbers as uppercase
- * @PANGO_TEXT_TRANSFORM_CAPITALIZE: Display the first character of a word
- * in titlecase
- *
- * An enumeration that affects how Pango treats characters during shaping.
- *
- * Since: 1.50
- */
-typedef enum {
- PANGO_TEXT_TRANSFORM_NONE,
- PANGO_TEXT_TRANSFORM_LOWERCASE,
- PANGO_TEXT_TRANSFORM_UPPERCASE,
- PANGO_TEXT_TRANSFORM_CAPITALIZE,
-} PangoTextTransform;
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_underline_new (PangoUnderline underline);
+PANGO_AVAILABLE_IN_1_8
+PangoAttribute * pango_attr_underline_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_strikethrough_new (gboolean strikethrough);
+PANGO_AVAILABLE_IN_1_8
+PangoAttribute * pango_attr_strikethrough_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PANGO_AVAILABLE_IN_ALL
+PangoAttribute * pango_attr_rise_new (int rise);
/**
* PangoBaselineShift:
@@ -254,6 +221,9 @@ typedef enum {
PANGO_BASELINE_SHIFT_SUBSCRIPT,
} PangoBaselineShift;
+PANGO_AVAILABLE_IN_1_50
+PangoAttribute * pango_attr_baseline_shift_new (int shift);
+
/**
* PangoFontScale:
* @PANGO_FONT_SCALE_NONE: Leave the font size unchanged
@@ -273,147 +243,6 @@ typedef enum {
PANGO_FONT_SCALE_SMALL_CAPS,
} PangoFontScale;
-/**
- * PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING:
- *
- * Value for @start_index in `PangoAttribute` that indicates
- * the beginning of the text.
- *
- * Since: 1.24
- */
-#define PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING ((guint)0)
-
-/**
- * PANGO_ATTR_INDEX_TO_TEXT_END: (value 4294967295)
- *
- * Value for @end_index in `PangoAttribute` that indicates
- * the end of the text.
- *
- * Since: 1.24
- */
-#define PANGO_ATTR_INDEX_TO_TEXT_END ((guint)(G_MAXUINT + 0))
-
-/**
- * PangoAttribute:
- * @klass: the class structure holding information about the type of the attribute
- * @start_index: the start index of the range (in bytes).
- * @end_index: end index of the range (in bytes). The character at this index
- * is not included in the range.
- *
- * The `PangoAttribute` structure represents the common portions of all
- * attributes.
- *
- * Particular types of attributes include this structure as their initial
- * portion. The common portion of the attribute holds the range to which
- * the value in the type-specific part of the attribute applies and should
- * be initialized using [method@Pango.Attribute.init]. By default, an attribute
- * will have an all-inclusive range of [0,%G_MAXUINT].
- */
-struct _PangoAttribute
-{
- PangoAttrType type;
- guint start_index;
- guint end_index;
- union {
- char *str_value;
- int int_value;
- gboolean boolean_value;
- double double_value;
- PangoColor color_value;
- PangoLanguage *lang_value;
- PangoFontDescription *font_value;
- gpointer pointer_value;
- };
-};
-
-
-/**
- * PangoAttrFilterFunc:
- * @attribute: a Pango attribute
- * @user_data: user data passed to the function
- *
- * Type of a function filtering a list of attributes.
- *
- * Return value: %TRUE if the attribute should be selected for
- * filtering, %FALSE otherwise.
- */
-typedef gboolean (*PangoAttrFilterFunc) (PangoAttribute *attribute,
- gpointer user_data);
-
-/**
- * PangoAttrDataCopyFunc:
- * @user_data: user data to copy
- *
- * Type of a function that can duplicate user data for an attribute.
- *
- * Return value: new copy of @user_data.
- **/
-typedef gpointer (*PangoAttrDataCopyFunc) (gconstpointer user_data);
-
-typedef char * (*PangoAttrDataSerializeFunc) (gconstpointer user_data);
-
-PANGO_AVAILABLE_IN_ALL
-GType pango_attribute_get_type (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_ALL
-PangoAttrType pango_attr_type_register (PangoAttrDataCopyFunc copy,
- GDestroyNotify destroy,
- GEqualFunc equal,
- const char *name,
- PangoAttrDataSerializeFunc serialize);
-PANGO_AVAILABLE_IN_1_22
-const char * pango_attr_type_get_name (PangoAttrType type) G_GNUC_CONST;
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attribute_copy (const PangoAttribute *attr);
-PANGO_AVAILABLE_IN_ALL
-void pango_attribute_destroy (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_attribute_equal (const PangoAttribute *attr1,
- const PangoAttribute *attr2) G_GNUC_PURE;
-
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_language_new (PangoLanguage *language);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_family_new (const char *family);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_foreground_new (guint16 red,
- guint16 green,
- guint16 blue);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_background_new (guint16 red,
- guint16 green,
- guint16 blue);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_size_new (int size);
-PANGO_AVAILABLE_IN_1_8
-PangoAttribute * pango_attr_size_new_absolute (int size);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_style_new (PangoStyle style);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_weight_new (PangoWeight weight);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_variant_new (PangoVariant variant);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_stretch_new (PangoStretch stretch);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_font_desc_new (const PangoFontDescription *desc);
-
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_underline_new (PangoUnderline underline);
-PANGO_AVAILABLE_IN_1_8
-PangoAttribute * pango_attr_underline_color_new (guint16 red,
- guint16 green,
- guint16 blue);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_strikethrough_new (gboolean strikethrough);
-PANGO_AVAILABLE_IN_1_8
-PangoAttribute * pango_attr_strikethrough_color_new (guint16 red,
- guint16 green,
- guint16 blue);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_rise_new (int rise);
-PANGO_AVAILABLE_IN_1_50
-PangoAttribute * pango_attr_baseline_shift_new (int shift);
PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_font_scale_new (PangoFontScale scale);
PANGO_AVAILABLE_IN_ALL
@@ -434,174 +263,83 @@ PANGO_AVAILABLE_IN_1_38
PangoAttribute * pango_attr_background_alpha_new (guint16 alpha);
PANGO_AVAILABLE_IN_1_44
PangoAttribute * pango_attr_allow_breaks_new (gboolean allow_breaks);
-
PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_word_new (void);
PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_sentence_new (void);
-
PANGO_AVAILABLE_IN_1_44
PangoAttribute * pango_attr_insert_hyphens_new (gboolean insert_hyphens);
+
+/**
+ * PangoOverline:
+ * @PANGO_OVERLINE_NONE: no overline should be drawn
+ * @PANGO_OVERLINE_SINGLE: Draw a single line above the ink
+ * extents of the text being underlined.
+ *
+ * The `PangoOverline` enumeration is used to specify whether text
+ * should be overlined, and if so, the type of line.
+ *
+ * Since: 1.46
+ */
+typedef enum {
+ PANGO_OVERLINE_NONE,
+ PANGO_OVERLINE_SINGLE
+} PangoOverline;
+
PANGO_AVAILABLE_IN_1_46
PangoAttribute * pango_attr_overline_new (PangoOverline overline);
PANGO_AVAILABLE_IN_1_46
PangoAttribute * pango_attr_overline_color_new (guint16 red,
guint16 green,
guint16 blue);
+
+/**
+ * PangoShowFlags:
+ * @PANGO_SHOW_NONE: No special treatment for invisible characters
+ * @PANGO_SHOW_SPACES: Render spaces, tabs and newlines visibly
+ * @PANGO_SHOW_LINE_BREAKS: Render line breaks visibly
+ * @PANGO_SHOW_IGNORABLES: Render default-ignorable Unicode
+ * characters visibly
+ *
+ * These flags affect how Pango treats characters that are normally
+ * not visible in the output.
+ *
+ * Since: 1.44
+ */
+typedef enum {
+ PANGO_SHOW_NONE = 0,
+ PANGO_SHOW_SPACES = 1 << 0,
+ PANGO_SHOW_LINE_BREAKS = 1 << 1,
+ PANGO_SHOW_IGNORABLES = 1 << 2
+} PangoShowFlags;
+
PANGO_AVAILABLE_IN_1_44
PangoAttribute * pango_attr_show_new (PangoShowFlags flags);
PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_line_height_new (double factor);
PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_line_height_new_absolute (int height);
-PANGO_AVAILABLE_IN_1_50
-PangoAttribute * pango_attr_text_transform_new (PangoTextTransform transform);
-PANGO_AVAILABLE_IN_1_52
-PangoAttribute * pango_attr_custom_new (PangoAttrType type,
- gpointer user_data);
-
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_string (PangoAttribute *attribute,
- const char **value);
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_language (PangoAttribute *attribute,
- PangoLanguage **value);
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_int (PangoAttribute *attribute,
- int *value);
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_boolean (PangoAttribute *attribute,
- gboolean *value);
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_float (PangoAttribute *attribute,
- double *value);
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_color (PangoAttribute *attribute,
- PangoColor *value);
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_font_desc (PangoAttribute *attribute,
- PangoFontDescription **value);
-
-PANGO_AVAILABLE_IN_1_52
-gboolean pango_attribute_get_custom (PangoAttribute *attribute,
- gpointer *value);
-
-
-
-/* Attribute lists */
-
-typedef struct _PangoAttrList PangoAttrList;
-typedef struct _PangoAttrIterator PangoAttrIterator;
-
-#define PANGO_TYPE_ATTR_LIST pango_attr_list_get_type ()
/**
- * PangoAttrIterator:
- *
- * A `PangoAttrIterator` is used to iterate through a `PangoAttrList`.
- *
- * A new iterator is created with [method@Pango.AttrList.get_iterator].
- * Once the iterator is created, it can be advanced through the style
- * changes in the text using [method@Pango.AttrIterator.next]. At each
- * style change, the range of the current style segment and the attributes
- * currently in effect can be queried.
- */
-
-/**
- * PangoAttrList:
- *
- * A `PangoAttrList` represents a list of attributes that apply to a section
- * of text.
+ * PangoTextTransform:
+ * @PANGO_TEXT_TRANSFORM_NONE: Leave text unchanged
+ * @PANGO_TEXT_TRANSFORM_LOWERCASE: Display letters and numbers as lowercase
+ * @PANGO_TEXT_TRANSFORM_UPPERCASE: Display letters and numbers as uppercase
+ * @PANGO_TEXT_TRANSFORM_CAPITALIZE: Display the first character of a word
+ * in titlecase
*
- * The attributes in a `PangoAttrList` are, in general, allowed to overlap in
- * an arbitrary fashion. However, if the attributes are manipulated only through
- * [method@Pango.AttrList.change], the overlap between properties will meet
- * stricter criteria.
+ * An enumeration that affects how Pango treats characters during shaping.
*
- * Since the `PangoAttrList` structure is stored as a linear list, it is not
- * suitable for storing attributes for large amounts of text. In general, you
- * should not use a single `PangoAttrList` for more than one paragraph of text.
+ * Since: 1.50
*/
+typedef enum {
+ PANGO_TEXT_TRANSFORM_NONE,
+ PANGO_TEXT_TRANSFORM_LOWERCASE,
+ PANGO_TEXT_TRANSFORM_UPPERCASE,
+ PANGO_TEXT_TRANSFORM_CAPITALIZE,
+} PangoTextTransform;
-PANGO_AVAILABLE_IN_ALL
-GType pango_attr_list_get_type (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_ALL
-PangoAttrList * pango_attr_list_new (void);
-PANGO_AVAILABLE_IN_1_10
-PangoAttrList * pango_attr_list_ref (PangoAttrList *list);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_unref (PangoAttrList *list);
-PANGO_AVAILABLE_IN_ALL
-PangoAttrList * pango_attr_list_copy (PangoAttrList *list);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_insert (PangoAttrList *list,
- PangoAttribute *attr);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_insert_before (PangoAttrList *list,
- PangoAttribute *attr);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_change (PangoAttrList *list,
- PangoAttribute *attr);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_splice (PangoAttrList *list,
- PangoAttrList *other,
- int pos,
- int len);
-PANGO_AVAILABLE_IN_1_44
-void pango_attr_list_update (PangoAttrList *list,
- int pos,
- int remove,
- int add);
-
-PANGO_AVAILABLE_IN_1_2
-PangoAttrList * pango_attr_list_filter (PangoAttrList *list,
- PangoAttrFilterFunc func,
- gpointer data);
-
-PANGO_AVAILABLE_IN_1_44
-GSList * pango_attr_list_get_attributes (PangoAttrList *list);
-
-PANGO_AVAILABLE_IN_1_46
-gboolean pango_attr_list_equal (PangoAttrList *list,
- PangoAttrList *other_list);
-
-PANGO_AVAILABLE_IN_1_50
-char * pango_attr_list_to_string (PangoAttrList *list);
PANGO_AVAILABLE_IN_1_50
-PangoAttrList * pango_attr_list_from_string (const char *text);
-
-PANGO_AVAILABLE_IN_1_44
-GType pango_attr_iterator_get_type (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_ALL
-PangoAttrIterator * pango_attr_list_get_iterator (PangoAttrList *list);
-
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_iterator_range (PangoAttrIterator *iterator,
- int *start,
- int *end);
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_attr_iterator_next (PangoAttrIterator *iterator);
-PANGO_AVAILABLE_IN_ALL
-PangoAttrIterator * pango_attr_iterator_copy (PangoAttrIterator *iterator);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_iterator_destroy (PangoAttrIterator *iterator);
-PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_iterator_get (PangoAttrIterator *iterator,
- PangoAttrType type);
-PANGO_AVAILABLE_IN_ALL
-void pango_attr_iterator_get_font (PangoAttrIterator *iterator,
- PangoFontDescription *desc,
- PangoLanguage **language,
- GSList **extra_attrs);
-PANGO_AVAILABLE_IN_1_2
-GSList * pango_attr_iterator_get_attrs (PangoAttrIterator *iterator);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttribute, pango_attribute_destroy)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttrList, pango_attr_list_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttrIterator, pango_attr_iterator_destroy)
+PangoAttribute * pango_attr_text_transform_new (PangoTextTransform transform);
G_END_DECLS
-
-#endif /* __PANGO_ATTRIBUTES_H__ */
diff --git a/pango/pango-glyph-item.c b/pango/pango-glyph-item.c
index 7eb1737d..d128f7f8 100644
--- a/pango/pango-glyph-item.c
+++ b/pango/pango-glyph-item.c
@@ -24,7 +24,8 @@
#include "pango-glyph-item.h"
#include "pango-impl-utils.h"
-#include "pango-attributes-private.h"
+#include "pango-attr-list-private.h"
+#include "pango-attr-iterator-private.h"
#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
@@ -617,7 +618,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item,
/* Advance the attr iterator to the start of the item
*/
- _pango_attr_list_get_iterator (list, &iter);
+ pango_attr_list_init_iterator (list, &iter);
do
{
pango_attr_iterator_range (&iter, &range_start, &range_end);
@@ -713,7 +714,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item,
if (LTR (glyph_item))
result = g_slist_reverse (result);
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
return result;
}
diff --git a/pango/pango-item.h b/pango/pango-item.h
index f0eebc01..72f065f3 100644
--- a/pango/pango-item.h
+++ b/pango/pango-item.h
@@ -23,7 +23,8 @@
#define __PANGO_ITEM_H__
#include <pango/pango-types.h>
-#include <pango/pango-attributes.h>
+#include <pango/pango-attr-list.h>
+#include <pango/pango-attr-list.h>
G_BEGIN_DECLS
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 94b59427..d0cc812c 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -87,7 +87,8 @@
#include <hb-ot.h>
#include "pango-layout-private.h"
-#include "pango-attributes-private.h"
+#include "pango-attr-list-private.h"
+#include "pango-attr-iterator-private.h"
#include "pango-font-private.h"
@@ -3332,12 +3333,12 @@ ensure_tab_width (PangoLayout *layout)
{
PangoAttrIterator iter;
- _pango_attr_list_get_iterator (layout_attrs, &iter);
+ pango_attr_list_init_iterator (layout_attrs, &iter);
pango_attr_iterator_get_font (&iter, font_desc, &language, NULL);
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
}
- _pango_attr_list_init (&tmp_attrs);
+ pango_attr_list_init (&tmp_attrs);
attr = pango_attr_font_desc_new (font_desc);
pango_font_description_free (font_desc);
@@ -3356,7 +3357,7 @@ ensure_tab_width (PangoLayout *layout)
pango_attr_list_unref (layout_attrs);
layout_attrs = NULL;
}
- _pango_attr_list_destroy (&tmp_attrs);
+ pango_attr_list_destroy (&tmp_attrs);
item = items->data;
pango_shape_with_flags (" ", 8, " ", 8, &item->analysis, glyphs, shape_flags);
@@ -4707,7 +4708,7 @@ apply_attributes_to_items (GList *items,
if (!attrs)
return;
- _pango_attr_list_get_iterator (attrs, &iter);
+ pango_attr_list_init_iterator (attrs, &iter);
for (l = items; l; l = l->next)
{
@@ -4715,7 +4716,7 @@ apply_attributes_to_items (GList *items,
pango_item_apply_attrs (item, &iter);
}
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
}
static void
@@ -4786,7 +4787,7 @@ pango_layout_check_lines (PangoLayout *layout)
itemize_attrs = pango_attr_list_filter (attrs, affects_itemization, NULL);
if (itemize_attrs)
- _pango_attr_list_get_iterator (itemize_attrs, &iter);
+ pango_attr_list_init_iterator (itemize_attrs, &iter);
}
else
{
@@ -4954,7 +4955,7 @@ pango_layout_check_lines (PangoLayout *layout)
if (itemize_attrs)
{
pango_attr_list_unref (itemize_attrs);
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
}
pango_attr_list_unref (shape_attrs);
@@ -5495,7 +5496,7 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout,
PangoAttrIterator iter;
int start, end;
- _pango_attr_list_get_iterator (layout->attrs, &iter);
+ pango_attr_list_init_iterator (layout->attrs, &iter);
do
{
@@ -5527,7 +5528,7 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout,
}
while (pango_attr_iterator_next (&iter));
- _pango_attr_iterator_destroy (&iter);
+ pango_attr_iterator_clear (&iter);
}
font = pango_context_load_font (layout->context, font_desc);
diff --git a/pango/pango-markup.h b/pango/pango-markup.h
index 003ee51a..b30edb8d 100644
--- a/pango/pango-markup.h
+++ b/pango/pango-markup.h
@@ -22,7 +22,7 @@
#ifndef __PANGO_MARKUP_H__
#define __PANGO_MARKUP_H__
-#include <pango/pango-attributes.h>
+#include <pango/pango-attr-list.h>
G_BEGIN_DECLS
diff --git a/pango/pango.h b/pango/pango.h
index aa0b7975..6b379d4c 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -22,6 +22,9 @@
#ifndef __PANGO_H__
#define __PANGO_H__
+#include <pango/pango-attr.h>
+#include <pango/pango-attr-list.h>
+#include <pango/pango-attr-iterator.h>
#include <pango/pango-attributes.h>
#include <pango/pango-bidi-type.h>
#include <pango/pango-break.h>
diff --git a/pango/serializer.c b/pango/serializer.c
index 78bd59a3..773ab3d3 100644
--- a/pango/serializer.c
+++ b/pango/serializer.c
@@ -27,7 +27,8 @@
#include <pango/pango-enum-types.h>
#include <pango/pango-font-private.h>
#include <pango/pango-hbface.h>
-#include <pango/pango-attributes-private.h>
+#include <pango/pango-attributes.h>
+#include <pango/pango-attr-private.h>
#include <hb-ot.h>
#include "pango/json/gtkjsonparserprivate.h"