From 03d2aff5518b72652fab592ef3d72852ce3ae3ef Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 5 Feb 2022 19:18:57 +0100 Subject: Split pango-attributes.[hc] Split pango-attributes.[hc] into separate files for PangoAttribute, PangoAttrList, PangoAttrIterator, and the predefined attribute types. --- pango/break.c | 36 +- pango/ellipsize.c | 7 +- pango/itemize.c | 2 +- pango/meson.build | 6 + pango/pango-attr-iterator-private.h | 38 + pango/pango-attr-iterator.c | 518 ++++++++ pango/pango-attr-iterator.h | 68 ++ pango/pango-attr-list-private.h | 35 + pango/pango-attr-list.c | 1285 ++++++++++++++++++++ pango/pango-attr-list.h | 114 ++ pango/pango-attr-private.h | 24 + pango/pango-attr.c | 540 +++++++++ pango/pango-attr.h | 214 ++++ pango/pango-attributes-private.h | 55 - pango/pango-attributes.c | 2264 +---------------------------------- pango/pango-attributes.h | 538 +++------ pango/pango-glyph-item.c | 7 +- pango/pango-item.h | 3 +- pango/pango-layout.c | 23 +- pango/pango-markup.h | 2 +- pango/pango.h | 3 + pango/serializer.c | 3 +- 22 files changed, 3038 insertions(+), 2747 deletions(-) create mode 100644 pango/pango-attr-iterator-private.h create mode 100644 pango/pango-attr-iterator.c create mode 100644 pango/pango-attr-iterator.h create mode 100644 pango/pango-attr-list-private.h create mode 100644 pango/pango-attr-list.c create mode 100644 pango/pango-attr-list.h create mode 100644 pango/pango-attr-private.h create mode 100644 pango/pango-attr.c create mode 100644 pango/pango-attr.h delete mode 100644 pango/pango-attributes-private.h 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 @@ -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 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-attr-iterator-private.h b/pango/pango-attr-iterator-private.h new file mode 100644 index 00000000..b229cbad --- /dev/null +++ b/pango/pango-attr-iterator-private.h @@ -0,0 +1,38 @@ +/* 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 + +struct _PangoAttrIterator +{ + GPtrArray *attrs; /* From the list */ + guint n_attrs; /* Copied from the list */ + + GPtrArray *attribute_stack; + + guint attr_index; + guint start_index; + guint end_index; +}; + +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 + +#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 +#include + +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 + +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 + +#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 +#include + +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 + +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 + +#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 +#include +#include + +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-private.h b/pango/pango-attributes-private.h deleted file mode 100644 index b4c5b671..00000000 --- a/pango/pango-attributes-private.h +++ /dev/null @@ -1,55 +0,0 @@ -/* 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. - */ - -#ifndef __PANGO_ATTRIBUTES_PRIVATE_H__ -#define __PANGO_ATTRIBUTES_PRIVATE_H__ - -struct _PangoAttrIterator -{ - GPtrArray *attrs; /* From the list */ - guint n_attrs; /* Copied from the list */ - - GPtrArray *attribute_stack; - - guint attr_index; - guint start_index; - 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 - 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 #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 #include -#include +#include 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 -#include +#include +#include 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 #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 +#include 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 +#include +#include #include #include #include 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 #include #include -#include +#include +#include #include #include "pango/json/gtkjsonparserprivate.h" -- cgit v1.2.1