From 04aae5f7ad1ab48248307b8995e558ad866afee5 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 30 Jan 2022 04:46:33 +0100 Subject: Redo attributes Do away with PangoAttribute subclassing, and turn the PangoAttribute struct into a union. Redo custom attribute registration to be more useful. --- pango/break.c | 12 +- pango/ellipsize.c | 2 +- pango/itemize.c | 18 +- pango/pango-attributes-private.h | 2 + pango/pango-attributes.c | 1386 +++++++++++++++----------------------- pango/pango-attributes.h | 308 +++------ pango/pango-item.c | 7 +- pango/pango-layout.c | 34 +- pango/pango-renderer.c | 22 +- pango/serializer.c | 241 +++---- pango/shape.c | 8 +- tests/markups/valid-19.expected | 2 +- tests/markups/valid-4.expected | 4 +- tests/test-itemize.c | 2 +- tests/test-shape.c | 4 +- tests/testattributes.c | 180 +++-- tests/testserialize.c | 8 +- 17 files changed, 937 insertions(+), 1303 deletions(-) diff --git a/pango/break.c b/pango/break.c index 05ec97c9..b31eca13 100644 --- a/pango/break.c +++ b/pango/break.c @@ -1801,7 +1801,7 @@ handle_allow_breaks (const char *text, if (!attr) continue; - if (!((PangoAttrInt*)attr)->value) + if (!attr->int_value) { int start, end; int start_pos, end_pos; @@ -2043,7 +2043,7 @@ handle_hyphens (const char *text, do { const PangoAttribute *attr = pango_attr_iterator_get (&iter, PANGO_ATTR_INSERT_HYPHENS); - if (attr && ((PangoAttrInt*)attr)->value == 0) + if (attr && attr->int_value == 0) { int start, end; int start_pos, end_pos; @@ -2100,13 +2100,13 @@ break_attrs (const char *text, { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_ALLOW_BREAKS) + if (attr->type == PANGO_ATTR_ALLOW_BREAKS) pango_attr_list_insert (&allow_breaks, pango_attribute_copy (attr)); - else if (attr->klass->type == PANGO_ATTR_WORD) + else if (attr->type == PANGO_ATTR_WORD) pango_attr_list_insert (&words, pango_attribute_copy (attr)); - else if (attr->klass->type == PANGO_ATTR_SENTENCE) + else if (attr->type == PANGO_ATTR_SENTENCE) pango_attr_list_insert (&sentences, pango_attribute_copy (attr)); - else if (attr->klass->type == PANGO_ATTR_INSERT_HYPHENS) + else if (attr->type == PANGO_ATTR_INSERT_HYPHENS) pango_attr_list_insert (&hyphens, pango_attribute_copy (attr)); } diff --git a/pango/ellipsize.c b/pango/ellipsize.c index d7b7fee0..13edd5a0 100644 --- a/pango/ellipsize.c +++ b/pango/ellipsize.c @@ -364,7 +364,7 @@ shape_ellipsis (EllipsizeState *state) /* Modify the fallback iter while it is inside the PangoAttrList; Don't try this at home */ - ((PangoAttrInt *)fallback)->value = TRUE; + fallback->int_value = TRUE; ellipsis_text = "..."; item = itemize_text (state, ellipsis_text, &attrs); diff --git a/pango/itemize.c b/pango/itemize.c index 935a3250..dab6eb7e 100644 --- a/pango/itemize.c +++ b/pango/itemize.c @@ -352,7 +352,7 @@ find_attribute (GSList *attr_list, GSList *node; for (node = attr_list; node; node = node->next) - if (((PangoAttribute *) node->data)->klass->type == type) + if (((PangoAttribute *) node->data)->type == type) return (PangoAttribute *) node->data; return NULL; @@ -394,13 +394,13 @@ update_attr_iterator (ItemizeState *state) state->lang = state->context->language; attr = find_attribute (state->extra_attrs, PANGO_ATTR_FALLBACK); - state->enable_fallback = (attr == NULL || ((PangoAttrInt *)attr)->value); + state->enable_fallback = (attr == NULL || attr->int_value); attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY); - state->gravity = attr == NULL ? PANGO_GRAVITY_AUTO : ((PangoAttrInt *)attr)->value; + state->gravity = attr == NULL ? PANGO_GRAVITY_AUTO : attr->int_value; attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY_HINT); - state->gravity_hint = attr == NULL ? state->context->gravity_hint : (PangoGravityHint)((PangoAttrInt *)attr)->value; + state->gravity_hint = attr == NULL ? state->context->gravity_hint : (PangoGravityHint)attr->int_value; state->changed |= FONT_CHANGED; if (state->lang != old_lang) @@ -1046,7 +1046,7 @@ collect_font_scale (PangoContext *context, { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_FONT_SCALE) + if (attr->type == PANGO_ATTR_FONT_SCALE) { if (attr->start_index == item->offset) { @@ -1060,7 +1060,7 @@ collect_font_scale (PangoContext *context, entry->attr = attr; *stack = g_list_prepend (*stack, entry); - switch (((PangoAttrInt *)attr)->value) + switch (attr->int_value) { case PANGO_FONT_SCALE_NONE: break; @@ -1121,7 +1121,7 @@ collect_font_scale (PangoContext *context, { ScaleItem *entry = l->data; *scale *= entry->scale; - if (((PangoAttrInt *)entry->attr)->value != PANGO_FONT_SCALE_SMALL_CAPS) + if (entry->attr->int_value != PANGO_FONT_SCALE_SMALL_CAPS) *is_small_caps = FALSE; retval = TRUE; } @@ -1302,8 +1302,8 @@ find_text_transform (const PangoAnalysis *analysis) { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_TEXT_TRANSFORM) - transform = (PangoTextTransform) ((PangoAttrInt*)attr)->value; + if (attr->type == PANGO_ATTR_TEXT_TRANSFORM) + transform = (PangoTextTransform) attr->int_value; } return transform; diff --git a/pango/pango-attributes-private.h b/pango/pango-attributes-private.h index 4c427695..b4c5b671 100644 --- a/pango/pango-attributes-private.h +++ b/pango/pango-attributes-private.h @@ -38,6 +38,7 @@ struct _PangoAttrList 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); @@ -51,3 +52,4 @@ gboolean pango_attr_iterator_advance (PangoAttrIterator *iterator, #endif + diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index b3b28f08..73fd5799 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -30,40 +30,87 @@ /* {{{ Generic attribute code */ G_LOCK_DEFINE_STATIC (attr_type); -static GHashTable *name_map = NULL; /* MT-safe */ +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: - * @name: an identifier for the type + * @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 (const gchar *name) +pango_attr_type_register (PangoAttrDataCopyFunc copy, + GDestroyNotify destroy, + GEqualFunc equal, + const char *name, + PangoAttrDataSerializeFunc serialize) { - static guint current_type = 0x1000000; /* MT-safe */ - guint type; + static guint current_id = MIN_CUSTOM; /* MT-safe */ + PangoAttrClass class; G_LOCK (attr_type); - type = current_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) - { - if (G_UNLIKELY (!name_map)) - name_map = g_hash_table_new (NULL, NULL); + class.name = g_intern_string (name); - g_hash_table_insert (name_map, GUINT_TO_POINTER (type), (gpointer) 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 type; + return class.type; } /** @@ -91,40 +138,26 @@ 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); - if (name_map) - result = g_hash_table_lookup (name_map, GUINT_TO_POINTER ((guint) 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_init: - * @attr: a `PangoAttribute` - * @klass: a `PangoAttrClass` - * - * Initializes @attr's klass to @klass, it's start_index to - * %PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING and end_index to - * %PANGO_ATTR_INDEX_TO_TEXT_END such that the attribute applies - * to the entire text by default. - * - * Since: 1.20 - */ -void -pango_attribute_init (PangoAttribute *attr, - const PangoAttrClass *klass) -{ - g_return_if_fail (attr != NULL); - g_return_if_fail (klass != NULL); - - attr->klass = klass; - attr->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING; - attr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END; -} - /** * pango_attribute_copy: * @attr: a `PangoAttribute` @@ -142,9 +175,51 @@ pango_attribute_copy (const PangoAttribute *attr) g_return_val_if_fail (attr != NULL, NULL); - result = attr->klass->copy (attr); - result->start_index = attr->start_index; - result->end_index = attr->end_index; + 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; } @@ -160,7 +235,51 @@ pango_attribute_destroy (PangoAttribute *attr) { g_return_if_fail (attr != NULL); - attr->klass->destroy (attr); + 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, @@ -187,297 +306,209 @@ pango_attribute_equal (const PangoAttribute *attr1, g_return_val_if_fail (attr1 != NULL, FALSE); g_return_val_if_fail (attr2 != NULL, FALSE); - if (attr1->klass->type != attr2->klass->type) + if (attr1->type != attr2->type) return FALSE; - return attr1->klass->equal (attr1, attr2); -} + switch (PANGO_ATTR_VALUE_TYPE (attr1)) + { + case PANGO_ATTR_VALUE_STRING: + return strcmp (attr1->str_value, attr2->str_value) == 0; -/* }}} */ -/* {{{ Attribute types */ -/* {{{ String attribute */ -static PangoAttribute *pango_attr_string_new (const PangoAttrClass *klass, - const char *str); + case PANGO_ATTR_VALUE_INT: + return attr1->int_value == attr2->int_value; -static PangoAttribute * -pango_attr_string_copy (const PangoAttribute *attr) -{ - return pango_attr_string_new (attr->klass, ((PangoAttrString *)attr)->value); -} + case PANGO_ATTR_VALUE_BOOLEAN: + return attr1->boolean_value == attr2->boolean_value; -static void -pango_attr_string_destroy (PangoAttribute *attr) -{ - PangoAttrString *sattr = (PangoAttrString *)attr; + case PANGO_ATTR_VALUE_FLOAT: + return attr1->double_value == attr2->double_value; - g_free (sattr->value); - g_slice_free (PangoAttrString, sattr); -} + case PANGO_ATTR_VALUE_COLOR: + return memcmp (&attr1->color_value, &attr2->color_value, sizeof (PangoColor)) == 0; -static gboolean -pango_attr_string_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - return strcmp (((PangoAttrString *)attr1)->value, ((PangoAttrString *)attr2)->value) == 0; -} + case PANGO_ATTR_VALUE_LANGUAGE: + return attr1->lang_value == attr2->lang_value; -static PangoAttribute * -pango_attr_string_new (const PangoAttrClass *klass, - const char *str) -{ - PangoAttrString *result = g_slice_new (PangoAttrString); - pango_attribute_init (&result->attr, klass); - result->value = g_strdup (str); + case PANGO_ATTR_VALUE_FONT_DESC: + return pango_font_description_equal (attr1->font_value, attr2->font_value); - return (PangoAttribute *)result; -} - /* }}} */ -/* {{{ Language attribute */ -static PangoAttribute * -pango_attr_language_copy (const PangoAttribute *attr) -{ - return pango_attr_language_new (((PangoAttrLanguage *)attr)->value); -} + case PANGO_ATTR_VALUE_POINTER: + { + GEqualFunc equal = NULL; -static void -pango_attr_language_destroy (PangoAttribute *attr) -{ - PangoAttrLanguage *lattr = (PangoAttrLanguage *)attr; + G_LOCK (attr_type); - g_slice_free (PangoAttrLanguage, lattr); -} + g_assert (attr_type != NULL); -static gboolean -pango_attr_language_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - return ((PangoAttrLanguage *)attr1)->value == ((PangoAttrLanguage *)attr2)->value; -} -/* }}}} */ -/* {{{ Color attribute */ -static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass, - guint16 red, - guint16 green, - guint16 blue); + 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; + } + } -static PangoAttribute * -pango_attr_color_copy (const PangoAttribute *attr) -{ - const PangoAttrColor *color_attr = (PangoAttrColor *)attr; + G_UNLOCK (attr_type); - return pango_attr_color_new (attr->klass, - color_attr->color.red, - color_attr->color.green, - color_attr->color.blue); -} + g_assert (equal != NULL); -static void -pango_attr_color_destroy (PangoAttribute *attr) -{ - PangoAttrColor *cattr = (PangoAttrColor *)attr; + return equal (attr1->pointer_value, attr2->pointer_value); + } - g_slice_free (PangoAttrColor, cattr); + default: + g_assert_not_reached (); + } } -static gboolean -pango_attr_color_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) +/* {{{ Builtin Attribute value types */ + +static inline PangoAttribute * +pango_attr_init (PangoAttrType type) { - const PangoAttrColor *color_attr1 = (const PangoAttrColor *)attr1; - const PangoAttrColor *color_attr2 = (const PangoAttrColor *)attr2; + PangoAttribute *attr; + + 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; - return (color_attr1->color.red == color_attr2->color.red && - color_attr1->color.blue == color_attr2->color.blue && - color_attr1->color.green == color_attr2->color.green); + return attr; } static PangoAttribute * -pango_attr_color_new (const PangoAttrClass *klass, - guint16 red, - guint16 green, - guint16 blue) +pango_attr_string_new (PangoAttrType type, + const char *value) { - PangoAttrColor *result = g_slice_new (PangoAttrColor); - pango_attribute_init (&result->attr, klass); - result->color.red = red; - result->color.green = green; - result->color.blue = blue; + PangoAttribute *attr; - return (PangoAttribute *)result; -} -/* }}}} */ -/* {{{ Integer attribute */ -static PangoAttribute *pango_attr_int_new (const PangoAttrClass *klass, - int value); + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_STRING, NULL); -static PangoAttribute * -pango_attr_int_copy (const PangoAttribute *attr) -{ - const PangoAttrInt *int_attr = (PangoAttrInt *)attr; + attr = pango_attr_init (type); + attr->str_value = g_strdup (value); - return pango_attr_int_new (attr->klass, int_attr->value); + return attr; } -static void -pango_attr_int_destroy (PangoAttribute *attr) +static PangoAttribute * +pango_attr_int_new (PangoAttrType type, + int value) { - PangoAttrInt *iattr = (PangoAttrInt *)attr; + PangoAttribute *attr; - g_slice_free (PangoAttrInt, iattr); -} + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_INT, NULL); -static gboolean -pango_attr_int_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - const PangoAttrInt *int_attr1 = (const PangoAttrInt *)attr1; - const PangoAttrInt *int_attr2 = (const PangoAttrInt *)attr2; + attr = pango_attr_init (type); + attr->int_value = value; - return (int_attr1->value == int_attr2->value); + return attr; } static PangoAttribute * -pango_attr_int_new (const PangoAttrClass *klass, - int value) +pango_attr_boolean_new (PangoAttrType type, + gboolean value) { - PangoAttrInt *result = g_slice_new (PangoAttrInt); - pango_attribute_init (&result->attr, klass); - result->value = value; + PangoAttribute *attr; - return (PangoAttribute *)result; -} -/* }}} */ -/* {{{ Float attribute */ -static PangoAttribute *pango_attr_float_new (const PangoAttrClass *klass, - double value); + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_BOOLEAN, NULL); -static PangoAttribute * -pango_attr_float_copy (const PangoAttribute *attr) -{ - const PangoAttrFloat *float_attr = (PangoAttrFloat *)attr; + attr = pango_attr_init (type); + attr->boolean_value = value; - return pango_attr_float_new (attr->klass, float_attr->value); + return attr; } -static void -pango_attr_float_destroy (PangoAttribute *attr) +static PangoAttribute * +pango_attr_float_new (PangoAttrType type, + double value) { - PangoAttrFloat *fattr = (PangoAttrFloat *)attr; + PangoAttribute *attr; - g_slice_free (PangoAttrFloat, fattr); -} + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_FLOAT, NULL); -static gboolean -pango_attr_float_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - const PangoAttrFloat *float_attr1 = (const PangoAttrFloat *)attr1; - const PangoAttrFloat *float_attr2 = (const PangoAttrFloat *)attr2; + attr = pango_attr_init (type); + attr->double_value = value; - return (float_attr1->value == float_attr2->value); + return attr; } static PangoAttribute * -pango_attr_float_new (const PangoAttrClass *klass, - double value) +pango_attr_color_new (PangoAttrType type, + guint16 red, + guint16 green, + guint16 blue) { - PangoAttrFloat *result = g_slice_new (PangoAttrFloat); - pango_attribute_init (&result->attr, klass); - result->value = value; + PangoAttribute *attr; + + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_COLOR, NULL); - return (PangoAttribute *)result; + attr = pango_attr_init (type); + attr->color_value.red = red; + attr->color_value.green = green; + attr->color_value.blue = blue; + + return attr; } -/* }}} */ -/* {{{ Size attribute */ -static PangoAttribute *pango_attr_size_new_internal (int size, - gboolean absolute); static PangoAttribute * -pango_attr_size_copy (const PangoAttribute *attr) +pango_attr_lang_new (PangoAttrType type, + PangoLanguage *value) { - const PangoAttrSize *size_attr = (PangoAttrSize *)attr; + PangoAttribute *attr; - if (attr->klass->type == PANGO_ATTR_ABSOLUTE_SIZE) - return pango_attr_size_new_absolute (size_attr->size); - else - return pango_attr_size_new (size_attr->size); -} + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_LANGUAGE, NULL); -static void -pango_attr_size_destroy (PangoAttribute *attr) -{ - PangoAttrSize *sattr = (PangoAttrSize *)attr; + attr = pango_attr_init (type); + attr->lang_value = value; - g_slice_free (PangoAttrSize, sattr); + return attr; } -static gboolean -pango_attr_size_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) +static PangoAttribute * +pango_attr_font_description_new (PangoAttrType type, + const PangoFontDescription *value) { - const PangoAttrSize *size_attr1 = (const PangoAttrSize *)attr1; - const PangoAttrSize *size_attr2 = (const PangoAttrSize *)attr2; + PangoAttribute *attr; - return size_attr1->size == size_attr2->size; -} + g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_FONT_DESC, NULL); -static PangoAttribute * -pango_attr_size_new_internal (int size, - gboolean absolute) -{ - PangoAttrSize *result; - - static const PangoAttrClass klass = { - PANGO_ATTR_SIZE, - pango_attr_size_copy, - pango_attr_size_destroy, - pango_attr_size_equal - }; - static const PangoAttrClass absolute_klass = { - PANGO_ATTR_ABSOLUTE_SIZE, - pango_attr_size_copy, - pango_attr_size_destroy, - pango_attr_size_equal - }; - - result = g_slice_new (PangoAttrSize); - pango_attribute_init (&result->attr, absolute ? &absolute_klass : &klass); - result->size = size; - result->absolute = absolute; - - return (PangoAttribute *)result; + attr = pango_attr_init (type); + attr->font_value = pango_font_description_copy (value); + + return attr; } /* }}} */ -/* {{{ Font description attribute */ -static PangoAttribute * -pango_attr_font_desc_copy (const PangoAttribute *attr) +/* }}} */ +/* {{{ Private API */ + +char * +pango_attr_value_serialize (PangoAttribute *attr) { - const PangoAttrFontDesc *desc_attr = (const PangoAttrFontDesc *)attr; + PangoAttrDataSerializeFunc serialize = NULL; - return pango_attr_font_desc_new (desc_attr->desc); -} + G_LOCK (attr_type); -static void -pango_attr_font_desc_destroy (PangoAttribute *attr) -{ - PangoAttrFontDesc *desc_attr = (PangoAttrFontDesc *)attr; + g_assert (attr_type != NULL); - pango_font_description_free (desc_attr->desc); - g_slice_free (PangoAttrFontDesc, desc_attr); -} + 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; + } + } -static gboolean -pango_attr_font_desc_equal (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - const PangoAttrFontDesc *desc_attr1 = (const PangoAttrFontDesc *)attr1; - const PangoAttrFontDesc *desc_attr2 = (const PangoAttrFontDesc *)attr2; + G_UNLOCK (attr_type); - return pango_font_description_get_set_fields (desc_attr1->desc) == - pango_font_description_get_set_fields (desc_attr2->desc) && - pango_font_description_equal (desc_attr1->desc, desc_attr2->desc); + if (serialize) + return serialize (attr->pointer_value); + + return NULL; } -/* }}} */ + /* }}} */ /* {{{ Public API */ @@ -494,16 +525,7 @@ pango_attr_font_desc_equal (const PangoAttribute *attr1, PangoAttribute * pango_attr_family_new (const char *family) { - static const PangoAttrClass klass = { - PANGO_ATTR_FAMILY, - pango_attr_string_copy, - pango_attr_string_destroy, - pango_attr_string_equal - }; - - g_return_val_if_fail (family != NULL, NULL); - - return pango_attr_string_new (&klass, family); + return pango_attr_string_new (PANGO_ATTR_FAMILY, family); } /** @@ -519,20 +541,7 @@ pango_attr_family_new (const char *family) PangoAttribute * pango_attr_language_new (PangoLanguage *language) { - PangoAttrLanguage *result; - - static const PangoAttrClass klass = { - PANGO_ATTR_LANGUAGE, - pango_attr_language_copy, - pango_attr_language_destroy, - pango_attr_language_equal - }; - - result = g_slice_new (PangoAttrLanguage); - pango_attribute_init (&result->attr, &klass); - result->value = language; - - return (PangoAttribute *)result; + return pango_attr_lang_new (PANGO_ATTR_LANGUAGE, language); } /** @@ -552,14 +561,7 @@ pango_attr_foreground_new (guint16 red, guint16 green, guint16 blue) { - static const PangoAttrClass klass = { - PANGO_ATTR_FOREGROUND, - pango_attr_color_copy, - pango_attr_color_destroy, - pango_attr_color_equal - }; - - return pango_attr_color_new (&klass, red, green, blue); + return pango_attr_color_new (PANGO_ATTR_FOREGROUND, red, green, blue); } /** @@ -579,14 +581,7 @@ pango_attr_background_new (guint16 red, guint16 green, guint16 blue) { - static const PangoAttrClass klass = { - PANGO_ATTR_BACKGROUND, - pango_attr_color_copy, - pango_attr_color_destroy, - pango_attr_color_equal - }; - - return pango_attr_color_new (&klass, red, green, blue); + return pango_attr_color_new (PANGO_ATTR_BACKGROUND, red, green, blue); } /** @@ -600,11 +595,12 @@ pango_attr_background_new (guint16 red, * [method@Pango.Attribute.destroy] */ PangoAttribute * -pango_attr_size_new (int size) +pango_attr_size_new (int value) { - return pango_attr_size_new_internal (size, FALSE); + return pango_attr_int_new (PANGO_ATTR_SIZE, value); } + /** * pango_attr_size_new_absolute: * @size: the font size, in %PANGO_SCALE-ths of a device unit @@ -620,7 +616,7 @@ pango_attr_size_new (int size) PangoAttribute * pango_attr_size_new_absolute (int size) { - return pango_attr_size_new_internal (size, TRUE); + return pango_attr_int_new (PANGO_ATTR_ABSOLUTE_SIZE, size); } /** @@ -636,14 +632,7 @@ pango_attr_size_new_absolute (int size) PangoAttribute * pango_attr_style_new (PangoStyle style) { - static const PangoAttrClass klass = { - PANGO_ATTR_STYLE, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)style); + return pango_attr_int_new (PANGO_ATTR_STYLE, (int)style); } /** @@ -659,14 +648,7 @@ pango_attr_style_new (PangoStyle style) PangoAttribute * pango_attr_weight_new (PangoWeight weight) { - static const PangoAttrClass klass = { - PANGO_ATTR_WEIGHT, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)weight); + return pango_attr_int_new (PANGO_ATTR_WEIGHT, (int)weight); } /** @@ -681,14 +663,7 @@ pango_attr_weight_new (PangoWeight weight) PangoAttribute * pango_attr_variant_new (PangoVariant variant) { - static const PangoAttrClass klass = { - PANGO_ATTR_VARIANT, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)variant); + return pango_attr_int_new (PANGO_ATTR_VARIANT, (int)variant); } /** @@ -702,16 +677,9 @@ pango_attr_variant_new (PangoVariant variant) * [method@Pango.Attribute.destroy] */ PangoAttribute * -pango_attr_stretch_new (PangoStretch stretch) +pango_attr_stretch_new (PangoStretch stretch) { - static const PangoAttrClass klass = { - PANGO_ATTR_STRETCH, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)stretch); + return pango_attr_int_new (PANGO_ATTR_STRETCH, (int)stretch); } /** @@ -730,18 +698,7 @@ pango_attr_stretch_new (PangoStretch stretch) PangoAttribute * pango_attr_font_desc_new (const PangoFontDescription *desc) { - static const PangoAttrClass klass = { - PANGO_ATTR_FONT_DESC, - pango_attr_font_desc_copy, - pango_attr_font_desc_destroy, - pango_attr_font_desc_equal - }; - - PangoAttrFontDesc *result = g_slice_new (PangoAttrFontDesc); - pango_attribute_init (&result->attr, &klass); - result->desc = pango_font_description_copy (desc); - - return (PangoAttribute *)result; + return pango_attr_font_description_new (PANGO_ATTR_FONT_DESC, desc); } /** @@ -757,14 +714,7 @@ pango_attr_font_desc_new (const PangoFontDescription *desc) PangoAttribute * pango_attr_underline_new (PangoUnderline underline) { - static const PangoAttrClass klass = { - PANGO_ATTR_UNDERLINE, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)underline); + return pango_attr_int_new (PANGO_ATTR_UNDERLINE, (int)underline); } /** @@ -789,14 +739,7 @@ pango_attr_underline_color_new (guint16 red, guint16 green, guint16 blue) { - static const PangoAttrClass klass = { - PANGO_ATTR_UNDERLINE_COLOR, - pango_attr_color_copy, - pango_attr_color_destroy, - pango_attr_color_equal - }; - - return pango_attr_color_new (&klass, red, green, blue); + return pango_attr_color_new (PANGO_ATTR_UNDERLINE_COLOR, red, green, blue); } /** @@ -812,14 +755,7 @@ pango_attr_underline_color_new (guint16 red, PangoAttribute * pango_attr_strikethrough_new (gboolean strikethrough) { - static const PangoAttrClass klass = { - PANGO_ATTR_STRIKETHROUGH, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)strikethrough); + return pango_attr_boolean_new (PANGO_ATTR_STRIKETHROUGH, (int)strikethrough); } /** @@ -844,14 +780,7 @@ pango_attr_strikethrough_color_new (guint16 red, guint16 green, guint16 blue) { - static const PangoAttrClass klass = { - PANGO_ATTR_STRIKETHROUGH_COLOR, - pango_attr_color_copy, - pango_attr_color_destroy, - pango_attr_color_equal - }; - - return pango_attr_color_new (&klass, red, green, blue); + return pango_attr_color_new (PANGO_ATTR_STRIKETHROUGH_COLOR, red, green, blue); } /** @@ -868,14 +797,7 @@ pango_attr_strikethrough_color_new (guint16 red, PangoAttribute * pango_attr_rise_new (int rise) { - static const PangoAttrClass klass = { - PANGO_ATTR_RISE, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)rise); + return pango_attr_int_new (PANGO_ATTR_RISE, (int)rise); } /** @@ -903,14 +825,7 @@ pango_attr_rise_new (int rise) PangoAttribute * pango_attr_baseline_shift_new (int rise) { - static const PangoAttrClass klass = { - PANGO_ATTR_BASELINE_SHIFT, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)rise); + return pango_attr_int_new (PANGO_ATTR_BASELINE_SHIFT, (int)rise); } /** @@ -933,14 +848,7 @@ pango_attr_baseline_shift_new (int rise) PangoAttribute * pango_attr_font_scale_new (PangoFontScale scale) { - static const PangoAttrClass klass = { - PANGO_ATTR_FONT_SCALE, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)scale); + return pango_attr_int_new (PANGO_ATTR_FONT_SCALE, (int)scale); } /** @@ -959,14 +867,7 @@ pango_attr_font_scale_new (PangoFontScale scale) PangoAttribute* pango_attr_scale_new (double scale_factor) { - static const PangoAttrClass klass = { - PANGO_ATTR_SCALE, - pango_attr_float_copy, - pango_attr_float_destroy, - pango_attr_float_equal - }; - - return pango_attr_float_new (&klass, scale_factor); + return pango_attr_float_new (PANGO_ATTR_SCALE, scale_factor); } /** @@ -990,14 +891,7 @@ pango_attr_scale_new (double scale_factor) PangoAttribute * pango_attr_fallback_new (gboolean enable_fallback) { - static const PangoAttrClass klass = { - PANGO_ATTR_FALLBACK, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal, - }; - - return pango_attr_int_new (&klass, (int)enable_fallback); + return pango_attr_boolean_new (PANGO_ATTR_FALLBACK, enable_fallback); } /** @@ -1016,14 +910,7 @@ pango_attr_fallback_new (gboolean enable_fallback) PangoAttribute * pango_attr_letter_spacing_new (int letter_spacing) { - static const PangoAttrClass klass = { - PANGO_ATTR_LETTER_SPACING, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, letter_spacing); + return pango_attr_int_new (PANGO_ATTR_LETTER_SPACING, letter_spacing); } /** @@ -1041,16 +928,9 @@ pango_attr_letter_spacing_new (int letter_spacing) PangoAttribute * pango_attr_gravity_new (PangoGravity gravity) { - static const PangoAttrClass klass = { - PANGO_ATTR_GRAVITY, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - g_return_val_if_fail (gravity != PANGO_GRAVITY_AUTO, NULL); - return pango_attr_int_new (&klass, (int)gravity); + return pango_attr_int_new (PANGO_ATTR_GRAVITY, (int)gravity); } /** @@ -1068,14 +948,7 @@ pango_attr_gravity_new (PangoGravity gravity) PangoAttribute * pango_attr_gravity_hint_new (PangoGravityHint hint) { - static const PangoAttrClass klass = { - PANGO_ATTR_GRAVITY_HINT, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)hint); + return pango_attr_int_new (PANGO_ATTR_GRAVITY_HINT, (int)hint); } /** @@ -1095,18 +968,11 @@ pango_attr_gravity_hint_new (PangoGravityHint hint) * Since: 1.38 */ PangoAttribute * -pango_attr_font_features_new (const gchar *features) +pango_attr_font_features_new (const char *features) { - static const PangoAttrClass klass = { - PANGO_ATTR_FONT_FEATURES, - pango_attr_string_copy, - pango_attr_string_destroy, - pango_attr_string_equal - }; - g_return_val_if_fail (features != NULL, NULL); - return pango_attr_string_new (&klass, features); + return pango_attr_string_new (PANGO_ATTR_FONT_FEATURES, features); } /** @@ -1124,14 +990,7 @@ pango_attr_font_features_new (const gchar *features) PangoAttribute * pango_attr_foreground_alpha_new (guint16 alpha) { - static const PangoAttrClass klass = { - PANGO_ATTR_FOREGROUND_ALPHA, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)alpha); + return pango_attr_int_new (PANGO_ATTR_FOREGROUND_ALPHA, (int)alpha); } /** @@ -1149,14 +1008,7 @@ pango_attr_foreground_alpha_new (guint16 alpha) PangoAttribute * pango_attr_background_alpha_new (guint16 alpha) { - static const PangoAttrClass klass = { - PANGO_ATTR_BACKGROUND_ALPHA, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)alpha); + return pango_attr_int_new (PANGO_ATTR_BACKGROUND_ALPHA, (int)alpha); } /** @@ -1177,14 +1029,7 @@ pango_attr_background_alpha_new (guint16 alpha) PangoAttribute * pango_attr_allow_breaks_new (gboolean allow_breaks) { - static const PangoAttrClass klass = { - PANGO_ATTR_ALLOW_BREAKS, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal, - }; - - return pango_attr_int_new (&klass, (int)allow_breaks); + return pango_attr_boolean_new (PANGO_ATTR_ALLOW_BREAKS, allow_breaks); } /** @@ -1206,14 +1051,7 @@ pango_attr_allow_breaks_new (gboolean allow_breaks) PangoAttribute * pango_attr_insert_hyphens_new (gboolean insert_hyphens) { - static const PangoAttrClass klass = { - PANGO_ATTR_INSERT_HYPHENS, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal, - }; - - return pango_attr_int_new (&klass, (int)insert_hyphens); + return pango_attr_boolean_new (PANGO_ATTR_INSERT_HYPHENS, insert_hyphens); } /** @@ -1232,14 +1070,7 @@ pango_attr_insert_hyphens_new (gboolean insert_hyphens) PangoAttribute * pango_attr_show_new (PangoShowFlags flags) { - static const PangoAttrClass klass = { - PANGO_ATTR_SHOW, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal, - }; - - return pango_attr_int_new (&klass, (int)flags); + return pango_attr_int_new (PANGO_ATTR_SHOW, (int)flags); } /** @@ -1259,14 +1090,7 @@ pango_attr_show_new (PangoShowFlags flags) PangoAttribute * pango_attr_word_new (void) { - static const PangoAttrClass klass = { - PANGO_ATTR_WORD, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal, - }; - - return pango_attr_int_new (&klass, 1); + return pango_attr_boolean_new (PANGO_ATTR_WORD, TRUE); } /** @@ -1286,14 +1110,7 @@ pango_attr_word_new (void) PangoAttribute * pango_attr_sentence_new (void) { - static const PangoAttrClass klass = { - PANGO_ATTR_SENTENCE, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal, - }; - - return pango_attr_int_new (&klass, 1); + return pango_attr_boolean_new (PANGO_ATTR_SENTENCE, TRUE); } /** @@ -1311,14 +1128,7 @@ pango_attr_sentence_new (void) PangoAttribute * pango_attr_overline_new (PangoOverline overline) { - static const PangoAttrClass klass = { - PANGO_ATTR_OVERLINE, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, (int)overline); + return pango_attr_int_new (PANGO_ATTR_OVERLINE, (int)overline); } /** @@ -1343,14 +1153,7 @@ pango_attr_overline_color_new (guint16 red, guint16 green, guint16 blue) { - static const PangoAttrClass klass = { - PANGO_ATTR_OVERLINE_COLOR, - pango_attr_color_copy, - pango_attr_color_destroy, - pango_attr_color_equal - }; - - return pango_attr_color_new (&klass, red, green, blue); + return pango_attr_color_new (PANGO_ATTR_OVERLINE_COLOR, red, green, blue); } /** @@ -1370,14 +1173,7 @@ pango_attr_overline_color_new (guint16 red, PangoAttribute * pango_attr_line_height_new (double factor) { - static const PangoAttrClass klass = { - PANGO_ATTR_LINE_HEIGHT, - pango_attr_float_copy, - pango_attr_float_destroy, - pango_attr_float_equal - }; - - return pango_attr_float_new (&klass, factor); + return pango_attr_float_new (PANGO_ATTR_LINE_HEIGHT, factor); } /** @@ -1396,14 +1192,7 @@ pango_attr_line_height_new (double factor) PangoAttribute * pango_attr_line_height_new_absolute (int height) { - static const PangoAttrClass klass = { - PANGO_ATTR_ABSOLUTE_LINE_HEIGHT, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, height); + return pango_attr_int_new (PANGO_ATTR_ABSOLUTE_LINE_HEIGHT, height); } /** @@ -1422,252 +1211,146 @@ pango_attr_line_height_new_absolute (int height) PangoAttribute * pango_attr_text_transform_new (PangoTextTransform transform) { - static const PangoAttrClass klass = { - PANGO_ATTR_TEXT_TRANSFORM, - pango_attr_int_copy, - pango_attr_int_destroy, - pango_attr_int_equal - }; - - return pango_attr_int_new (&klass, transform); + return pango_attr_int_new (PANGO_ATTR_TEXT_TRANSFORM, transform); } -/* }}} */ -/* {{{ Binding helpers */ /** - * pango_attribute_as_int: - * @attr: A `PangoAttribute` such as weight - * - * Returns the attribute cast to `PangoAttrInt`. + * pango_attr_custom_new: + * @type: the attribute type + * @user_data: data for the attribute * - * This is mainly useful for language bindings. + * Creates a new attribute for the given type. * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrInt`, - * or %NULL if it's not an integer attribute + * 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. * - * Since: 1.50 + * Return value: (transfer full): the newly allocated + * `PangoAttribute`, which should be freed with + * [method@Pango.Attribute.destroy] */ -PangoAttrInt * -pango_attribute_as_int (PangoAttribute *attr) +PangoAttribute * +pango_attr_custom_new (PangoAttrType type, + gpointer user_data) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_STYLE: - case PANGO_ATTR_WEIGHT: - case PANGO_ATTR_VARIANT: - case PANGO_ATTR_STRETCH: - case PANGO_ATTR_UNDERLINE: - case PANGO_ATTR_STRIKETHROUGH: - case PANGO_ATTR_RISE: - case PANGO_ATTR_FALLBACK: - case PANGO_ATTR_LETTER_SPACING: - case PANGO_ATTR_GRAVITY: - case PANGO_ATTR_GRAVITY_HINT: - case PANGO_ATTR_FOREGROUND_ALPHA: - case PANGO_ATTR_BACKGROUND_ALPHA: - case PANGO_ATTR_ALLOW_BREAKS: - case PANGO_ATTR_SHOW: - case PANGO_ATTR_INSERT_HYPHENS: - case PANGO_ATTR_OVERLINE: - case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: - case PANGO_ATTR_TEXT_TRANSFORM: - case PANGO_ATTR_WORD: - case PANGO_ATTR_SENTENCE: - case PANGO_ATTR_BASELINE_SHIFT: - case PANGO_ATTR_FONT_SCALE: - return (PangoAttrInt *)attr; + PangoAttrClass *class = NULL; + PangoAttribute *attr; - default: - return 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 *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; } -/** - * pango_attribute_as_float: - * @attr: A `PangoAttribute` such as scale - * - * Returns the attribute cast to `PangoAttrFloat`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrFloat`, - * or %NULL if it's not a floating point attribute - * - * Since: 1.50 - */ -PangoAttrFloat * -pango_attribute_as_float (PangoAttribute *attr) +/* }}} */ +/* {{{ Binding Helpers */ + +gboolean +pango_attribute_get_string (PangoAttribute *attribute, + const char **value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_SCALE: - case PANGO_ATTR_LINE_HEIGHT: - return (PangoAttrFloat *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_STRING) + return FALSE; - default: - return NULL; - } + *value = attribute->str_value; + return TRUE; } -/** - * pango_attribute_as_string: - * @attr: A `PangoAttribute` such as family - * - * Returns the attribute cast to `PangoAttrString`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrString`, - * or %NULL if it's not a string attribute - * - * Since: 1.50 - */ -PangoAttrString * -pango_attribute_as_string (PangoAttribute *attr) +gboolean +pango_attribute_get_language (PangoAttribute *attribute, + PangoLanguage **value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_FAMILY: - return (PangoAttrString *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_LANGUAGE) + return FALSE; - default: - return NULL; - } + *value = attribute->lang_value; + return TRUE; } -/** - * pango_attribute_as_size: - * @attr: A `PangoAttribute` representing a size - * - * Returns the attribute cast to `PangoAttrSize`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrSize`, - * or NULL if it's not a size attribute - * - * Since: 1.50 - */ -PangoAttrSize * -pango_attribute_as_size (PangoAttribute *attr) +gboolean +pango_attribute_get_int (PangoAttribute *attribute, + int *value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_SIZE: - case PANGO_ATTR_ABSOLUTE_SIZE: - return (PangoAttrSize *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_INT) + return FALSE; - default: - return NULL; - } + *value = attribute->int_value; + return TRUE; } -/** - * pango_attribute_as_color: - * @attr: A `PangoAttribute` such as foreground - * - * Returns the attribute cast to `PangoAttrColor`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrColor`, - * or %NULL if it's not a color attribute - * - * Since: 1.50 - */ -PangoAttrColor * -pango_attribute_as_color (PangoAttribute *attr) +gboolean +pango_attribute_get_boolean (PangoAttribute *attribute, + int *value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_FOREGROUND: - case PANGO_ATTR_BACKGROUND: - case PANGO_ATTR_UNDERLINE_COLOR: - case PANGO_ATTR_STRIKETHROUGH_COLOR: - case PANGO_ATTR_OVERLINE_COLOR: - return (PangoAttrColor *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_BOOLEAN) + return FALSE; - default: - return NULL; - } + *value = attribute->boolean_value; + return TRUE; } -/** - * pango_attribute_as_font_desc: - * @attr: A `PangoAttribute` representing a font description - * - * Returns the attribute cast to `PangoAttrFontDesc`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrFontDesc`, - * or %NULL if it's not a font description attribute - * - * Since: 1.50 - */ -PangoAttrFontDesc * -pango_attribute_as_font_desc (PangoAttribute *attr) +gboolean +pango_attribute_get_float (PangoAttribute *attribute, + double *value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_FONT_DESC: - return (PangoAttrFontDesc *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_FLOAT) + return FALSE; - default: - return NULL; - } + *value = attribute->double_value; + return TRUE; } -/** - * pango_attribute_as_font_features: - * @attr: A `PangoAttribute` representing font features - * - * Returns the attribute cast to `PangoAttrFontFeatures`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrFontFeatures`, - * or %NULL if it's not a font features attribute - * - * Since: 1.50 - */ -PangoAttrFontFeatures * -pango_attribute_as_font_features (PangoAttribute *attr) +gboolean +pango_attribute_get_color (PangoAttribute *attribute, + PangoColor *value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_FONT_FEATURES: - return (PangoAttrFontFeatures *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_COLOR) + return FALSE; - default: - return NULL; - } + *value = attribute->color_value; + return TRUE; } -/** - * pango_attribute_as_language: - * @attr: A `PangoAttribute` representing a language - * - * Returns the attribute cast to `PangoAttrLanguage`. - * - * This is mainly useful for language bindings. - * - * Returns: (nullable) (transfer none): The attribute as `PangoAttrLanguage`, - * or %NULL if it's not a language attribute - * - * Since: 1.50 - */ -PangoAttrLanguage * -pango_attribute_as_language (PangoAttribute *attr) +gboolean +pango_attribute_get_font_desc (PangoAttribute *attribute, + PangoFontDescription **value) { - switch ((int)attr->klass->type) - { - case PANGO_ATTR_LANGUAGE: - return (PangoAttrLanguage *)attr; + if (PANGO_ATTR_VALUE_TYPE (attribute) != PANGO_ATTR_VALUE_FONT_DESC) + return FALSE; - default: - return NULL; - } + *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; } /* }}} */ @@ -1729,17 +1412,18 @@ pango_attr_list_ref (PangoAttrList *list) void _pango_attr_list_destroy (PangoAttrList *list) { - guint i, p; +// 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); + //attr->klass->destroy (attr); } +#endif g_ptr_array_free (list->attributes, TRUE); } @@ -1934,7 +1618,7 @@ pango_attr_list_change (PangoAttrList *list, break; } - if (tmp_attr->klass->type != attr->klass->type) + if (tmp_attr->type != attr->type) continue; if (tmp_attr->end_index < start_index) @@ -2003,7 +1687,7 @@ pango_attr_list_change (PangoAttrList *list, if (tmp_attr->start_index > end_index) break; - if (tmp_attr->klass->type != attr->klass->type) + if (tmp_attr->type != attr->type) continue; if (tmp_attr->end_index <= attr->end_index || @@ -2400,19 +2084,6 @@ pango_attr_list_filter (PangoAttrList *list, * are quoted with "". */ -static const char * -get_attr_type_nick (PangoAttrType attr_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, attr_type); - g_type_class_unref (enum_class); - - return enum_value->value_nick; -} - static GType get_attr_value_type (PangoAttrType type) { @@ -2455,66 +2126,80 @@ static void attr_print (GString *str, PangoAttribute *attr) { - PangoAttrString *string; - PangoAttrLanguage *lang; - PangoAttrInt *integer; - PangoAttrFloat *flt; - PangoAttrFontDesc *font; - PangoAttrColor *color; - PangoAttrSize *size; - PangoAttrFontFeatures *features; - - g_string_append_printf (str, "%u %u ", attr->start_index, attr->end_index); - - g_string_append (str, get_attr_type_nick (attr->klass->type)); - - if (attr->klass->type == PANGO_ATTR_WEIGHT || - attr->klass->type == PANGO_ATTR_STYLE || - attr->klass->type == PANGO_ATTR_STRETCH || - attr->klass->type == PANGO_ATTR_VARIANT || - attr->klass->type == PANGO_ATTR_GRAVITY || - attr->klass->type == PANGO_ATTR_GRAVITY_HINT || - attr->klass->type == PANGO_ATTR_UNDERLINE || - attr->klass->type == PANGO_ATTR_OVERLINE || - attr->klass->type == PANGO_ATTR_BASELINE_SHIFT || - attr->klass->type == PANGO_ATTR_FONT_SCALE || - attr->klass->type == PANGO_ATTR_TEXT_TRANSFORM) - append_enum_value (str, get_attr_value_type (attr->klass->type), ((PangoAttrInt *)attr)->value); - else if (attr->klass->type == PANGO_ATTR_STRIKETHROUGH || - attr->klass->type == PANGO_ATTR_ALLOW_BREAKS || - attr->klass->type == PANGO_ATTR_INSERT_HYPHENS || - attr->klass->type == PANGO_ATTR_FALLBACK) - g_string_append (str, ((PangoAttrInt *)attr)->value ? " true" : " false"); - else if ((string = pango_attribute_as_string (attr)) != NULL) - g_string_append_printf (str, " %s", string->value); - else if ((lang = pango_attribute_as_language (attr)) != NULL) - g_string_append_printf (str, " %s", pango_language_to_string (lang->value)); - else if ((integer = pango_attribute_as_int (attr)) != NULL) - g_string_append_printf (str, " %d", integer->value); - else if ((flt = pango_attribute_as_float (attr)) != NULL) - { - char buf[20]; - g_ascii_formatd (buf, 20, "%f", flt->value); - g_string_append_printf (str, " %s", buf); - } - else if ((font = pango_attribute_as_font_desc (attr)) != NULL) - { - char *s = pango_font_description_to_string (font->desc); - g_string_append_printf (str, " \"%s\"", s); - g_free (s); - } - else if ((color = pango_attribute_as_color (attr)) != NULL) + 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)) { - char *s = pango_color_to_string (&color->color); - g_string_append_printf (str, " %s", s); - g_free (s); + 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 (); } - else if ((size = pango_attribute_as_size (attr)) != NULL) - g_string_append_printf (str, " %d", size->size); - else if ((features = pango_attribute_as_font_features (attr)) != NULL) - g_string_append_printf (str, " \"%s\"", features->features); - else - g_assert_not_reached (); } /** @@ -2728,11 +2413,14 @@ pango_attr_list_from_string (const char *text) break; case PANGO_ATTR_FAMILY: - endp = (char *)p + strcspn (p, ",\n"); - if (!is_valid_end_char (*endp)) goto fail; + 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: @@ -3150,7 +2838,7 @@ pango_attr_iterator_get (PangoAttrIterator *iterator, { PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i); - if (attr->klass->type == type) + if (attr->type == type) return attr; } @@ -3207,14 +2895,14 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, { const PangoAttribute *attr = g_ptr_array_index (iterator->attribute_stack, i); - switch ((int) attr->klass->type) + switch ((int) attr->type) { case PANGO_ATTR_FONT_DESC: { - PangoFontMask new_mask = pango_font_description_get_set_fields (((PangoAttrFontDesc *)attr)->desc) & ~mask; + 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, ((PangoAttrFontDesc *)attr)->desc, FALSE); + pango_font_description_merge_static (desc, attr->font_value, FALSE); break; } @@ -3222,56 +2910,56 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, if (!(mask & PANGO_FONT_MASK_FAMILY)) { mask |= PANGO_FONT_MASK_FAMILY; - pango_font_description_set_family (desc, ((PangoAttrString *)attr)->value); + 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, ((PangoAttrInt *)attr)->value); + 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, ((PangoAttrInt *)attr)->value); + 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, ((PangoAttrInt *)attr)->value); + 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, ((PangoAttrInt *)attr)->value); + 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, ((PangoAttrSize *)attr)->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, ((PangoAttrSize *)attr)->size); + pango_font_description_set_absolute_size (desc, attr->int_value); } break; case PANGO_ATTR_SCALE: if (!have_scale) { have_scale = TRUE; - scale = ((PangoAttrFloat *)attr)->value; + scale = attr->double_value; } break; case PANGO_ATTR_LANGUAGE: @@ -3280,7 +2968,7 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, if (!have_language) { have_language = TRUE; - *language = ((PangoAttrLanguage *)attr)->value; + *language = attr->lang_value; } } break; @@ -3294,15 +2982,15 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, * so we never merge them. * This needs to be handled more systematically. */ - if (attr->klass->type != PANGO_ATTR_FONT_FEATURES && - attr->klass->type != PANGO_ATTR_BASELINE_SHIFT && - attr->klass->type != PANGO_ATTR_FONT_SCALE) + 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->klass->type == old_attr->klass->type) + if (attr->type == old_attr->type) { found = TRUE; break; @@ -3363,13 +3051,13 @@ pango_attr_iterator_get_attrs (PangoAttrIterator *iterator) GSList *tmp_list2; gboolean found = FALSE; - if (attr->klass->type != PANGO_ATTR_FONT_DESC && - attr->klass->type != PANGO_ATTR_BASELINE_SHIFT && - attr->klass->type != PANGO_ATTR_FONT_SCALE) + 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->klass->type == old_attr->klass->type) + if (attr->type == old_attr->type) { found = TRUE; break; diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index 6ba09154..9b679e95 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -32,14 +32,21 @@ G_BEGIN_DECLS typedef struct _PangoAttribute PangoAttribute; typedef struct _PangoAttrClass PangoAttrClass; -typedef struct _PangoAttrString PangoAttrString; -typedef struct _PangoAttrLanguage PangoAttrLanguage; -typedef struct _PangoAttrInt PangoAttrInt; -typedef struct _PangoAttrSize PangoAttrSize; -typedef struct _PangoAttrFloat PangoAttrFloat; -typedef struct _PangoAttrColor PangoAttrColor; -typedef struct _PangoAttrFontDesc PangoAttrFontDesc; -typedef struct _PangoAttrFontFeatures PangoAttrFontFeatures; +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: @@ -89,45 +96,47 @@ typedef struct _PangoAttrFontFeatures PangoAttrFontFeatures; */ typedef enum { - PANGO_ATTR_INVALID, /* 0 is an invalid attribute type */ - PANGO_ATTR_LANGUAGE, /* PangoAttrLanguage */ - PANGO_ATTR_FAMILY, /* PangoAttrString */ - PANGO_ATTR_STYLE, /* PangoAttrInt */ - PANGO_ATTR_WEIGHT, /* PangoAttrInt */ - PANGO_ATTR_VARIANT, /* PangoAttrInt */ - PANGO_ATTR_STRETCH, /* PangoAttrInt */ - PANGO_ATTR_SIZE, /* PangoAttrSize */ - PANGO_ATTR_FONT_DESC, /* PangoAttrFontDesc */ - PANGO_ATTR_FOREGROUND, /* PangoAttrColor */ - PANGO_ATTR_BACKGROUND, /* PangoAttrColor */ - PANGO_ATTR_UNDERLINE, /* PangoAttrInt */ - PANGO_ATTR_STRIKETHROUGH, /* PangoAttrInt */ - PANGO_ATTR_RISE, /* PangoAttrInt */ - PANGO_ATTR_SCALE, /* PangoAttrFloat */ - PANGO_ATTR_FALLBACK, /* PangoAttrInt */ - PANGO_ATTR_LETTER_SPACING, /* PangoAttrInt */ - PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */ - PANGO_ATTR_STRIKETHROUGH_COLOR,/* PangoAttrColor */ - PANGO_ATTR_ABSOLUTE_SIZE, /* PangoAttrSize */ - PANGO_ATTR_GRAVITY, /* PangoAttrInt */ - PANGO_ATTR_GRAVITY_HINT, /* PangoAttrInt */ - PANGO_ATTR_FONT_FEATURES, /* PangoAttrFontFeatures */ - PANGO_ATTR_FOREGROUND_ALPHA, /* PangoAttrInt */ - PANGO_ATTR_BACKGROUND_ALPHA, /* PangoAttrInt */ - PANGO_ATTR_ALLOW_BREAKS, /* PangoAttrInt */ - PANGO_ATTR_SHOW, /* PangoAttrInt */ - PANGO_ATTR_INSERT_HYPHENS, /* PangoAttrInt */ - PANGO_ATTR_OVERLINE, /* PangoAttrInt */ - PANGO_ATTR_OVERLINE_COLOR, /* PangoAttrColor */ - PANGO_ATTR_LINE_HEIGHT, /* PangoAttrFloat */ - PANGO_ATTR_ABSOLUTE_LINE_HEIGHT, /* PangoAttrInt */ - PANGO_ATTR_TEXT_TRANSFORM, /* PangoAttrInt */ - PANGO_ATTR_WORD, /* PangoAttrInt */ - PANGO_ATTR_SENTENCE, /* PangoAttrInt */ - PANGO_ATTR_BASELINE_SHIFT, /* PangoAttrSize */ - PANGO_ATTR_FONT_SCALE, /* PangoAttrInt */ + PANGO_ATTR_INVALID, + PANGO_ATTR_LANGUAGE = PANGO_ATTR_TYPE (LANGUAGE), + PANGO_ATTR_FAMILY = PANGO_ATTR_TYPE (STRING), + PANGO_ATTR_STYLE = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_WEIGHT = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_VARIANT = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_STRETCH = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_SIZE = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_FONT_DESC = PANGO_ATTR_TYPE (FONT_DESC), + PANGO_ATTR_FOREGROUND = PANGO_ATTR_TYPE (COLOR), + PANGO_ATTR_BACKGROUND = PANGO_ATTR_TYPE (COLOR), + PANGO_ATTR_UNDERLINE = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_STRIKETHROUGH = PANGO_ATTR_TYPE (BOOLEAN), + PANGO_ATTR_RISE = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_SCALE = PANGO_ATTR_TYPE (FLOAT), + PANGO_ATTR_FALLBACK = PANGO_ATTR_TYPE (BOOLEAN), + PANGO_ATTR_LETTER_SPACING = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_UNDERLINE_COLOR = PANGO_ATTR_TYPE (COLOR), + PANGO_ATTR_STRIKETHROUGH_COLOR = PANGO_ATTR_TYPE (COLOR), + PANGO_ATTR_ABSOLUTE_SIZE = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_GRAVITY = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_GRAVITY_HINT = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_FONT_FEATURES = PANGO_ATTR_TYPE (STRING), + PANGO_ATTR_FOREGROUND_ALPHA = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_BACKGROUND_ALPHA = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_ALLOW_BREAKS = PANGO_ATTR_TYPE (BOOLEAN), + PANGO_ATTR_SHOW = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_INSERT_HYPHENS = PANGO_ATTR_TYPE (BOOLEAN), + PANGO_ATTR_OVERLINE = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_OVERLINE_COLOR = PANGO_ATTR_TYPE (COLOR), + PANGO_ATTR_LINE_HEIGHT = PANGO_ATTR_TYPE (FLOAT), + PANGO_ATTR_ABSOLUTE_LINE_HEIGHT = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_TEXT_TRANSFORM = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_WORD = PANGO_ATTR_TYPE (BOOLEAN), + PANGO_ATTR_SENTENCE = PANGO_ATTR_TYPE (BOOLEAN), + PANGO_ATTR_BASELINE_SHIFT = PANGO_ATTR_TYPE (INT), + PANGO_ATTR_FONT_SCALE = PANGO_ATTR_TYPE (INT), } PangoAttrType; +#undef PANGO_ATTR_TYPE + /** * PangoUnderline: * @PANGO_UNDERLINE_NONE: no underline should be drawn @@ -302,11 +311,22 @@ typedef enum { */ struct _PangoAttribute { - const PangoAttrClass *klass; + 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 @@ -330,157 +350,19 @@ typedef gboolean (*PangoAttrFilterFunc) (PangoAttribute *attribute, **/ typedef gpointer (*PangoAttrDataCopyFunc) (gconstpointer user_data); -/** - * PangoAttrClass: - * @type: the type ID for this attribute - * @copy: function to duplicate an attribute of this type - * (see [method@Pango.Attribute.copy]) - * @destroy: function to free an attribute of this type - * (see [method@Pango.Attribute.destroy]) - * @equal: function to check two attributes of this type for equality - * (see [method@Pango.Attribute.equal]) - * - * The `PangoAttrClass` structure stores the type and operations for - * a particular type of attribute. - * - * The functions in this structure should not be called directly. Instead, - * one should use the wrapper functions provided for `PangoAttribute`. - */ -struct _PangoAttrClass -{ - /*< public >*/ - PangoAttrType type; - PangoAttribute * (*copy) (const PangoAttribute *attr); - void (*destroy) (PangoAttribute *attr); - gboolean (*equal) (const PangoAttribute *attr1, const PangoAttribute *attr2); -}; - -/** - * PangoAttrString: - * @attr: the common portion of the attribute - * @value: the string which is the value of the attribute - * - * The `PangoAttrString` structure is used to represent attributes with - * a string value. - */ -struct _PangoAttrString -{ - PangoAttribute attr; - char *value; -}; -/** - * PangoAttrLanguage: - * @attr: the common portion of the attribute - * @value: the `PangoLanguage` which is the value of the attribute - * - * The `PangoAttrLanguage` structure is used to represent attributes that - * are languages. - */ -struct _PangoAttrLanguage -{ - PangoAttribute attr; - PangoLanguage *value; -}; -/** - * PangoAttrInt: - * @attr: the common portion of the attribute - * @value: the value of the attribute - * - * The `PangoAttrInt` structure is used to represent attributes with - * an integer or enumeration value. - */ -struct _PangoAttrInt -{ - PangoAttribute attr; - int value; -}; -/** - * PangoAttrFloat: - * @attr: the common portion of the attribute - * @value: the value of the attribute - * - * The `PangoAttrFloat` structure is used to represent attributes with - * a float or double value. - */ -struct _PangoAttrFloat -{ - PangoAttribute attr; - double value; -}; -/** - * PangoAttrColor: - * @attr: the common portion of the attribute - * @color: the `PangoColor` which is the value of the attribute - * - * The `PangoAttrColor` structure is used to represent attributes that - * are colors. - */ -struct _PangoAttrColor -{ - PangoAttribute attr; - PangoColor color; -}; - -/** - * PangoAttrSize: - * @attr: the common portion of the attribute - * @size: size of font, in units of 1/%PANGO_SCALE of a point (for - * %PANGO_ATTR_SIZE) or of a device unit (for %PANGO_ATTR_ABSOLUTE_SIZE) - * @absolute: whether the font size is in device units or points. - * This field is only present for compatibility with Pango-1.8.0 - * (%PANGO_ATTR_ABSOLUTE_SIZE was added in 1.8.1); and always will - * be %FALSE for %PANGO_ATTR_SIZE and %TRUE for %PANGO_ATTR_ABSOLUTE_SIZE. - * - * The `PangoAttrSize` structure is used to represent attributes which - * set font size. - */ -struct _PangoAttrSize -{ - PangoAttribute attr; - int size; - guint absolute : 1; -}; - -/** - * PangoAttrFontDesc: - * @attr: the common portion of the attribute - * @desc: the font description which is the value of this attribute - * - * The `PangoAttrFontDesc` structure is used to store an attribute that - * sets all aspects of the font description at once. - */ -struct _PangoAttrFontDesc -{ - PangoAttribute attr; - PangoFontDescription *desc; -}; - -/** - * PangoAttrFontFeatures: - * @attr: the common portion of the attribute - * @features: the features, as a string in CSS syntax - * - * The `PangoAttrFontFeatures` structure is used to represent OpenType - * font features as an attribute. - * - * Since: 1.38 - */ -struct _PangoAttrFontFeatures -{ - PangoAttribute attr; - gchar *features; -}; +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 (const char *name); +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_1_20 -void pango_attribute_init (PangoAttribute *attr, - const PangoAttrClass *klass); PANGO_AVAILABLE_IN_ALL PangoAttribute * pango_attribute_copy (const PangoAttribute *attr); PANGO_AVAILABLE_IN_ALL @@ -574,23 +456,37 @@ 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); + -PANGO_AVAILABLE_IN_1_50 -PangoAttrString * pango_attribute_as_string (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrLanguage * pango_attribute_as_language (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrInt * pango_attribute_as_int (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrSize * pango_attribute_as_size (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrFloat * pango_attribute_as_float (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrColor * pango_attribute_as_color (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrFontDesc * pango_attribute_as_font_desc (PangoAttribute *attr); -PANGO_AVAILABLE_IN_1_50 -PangoAttrFontFeatures * pango_attribute_as_font_features (PangoAttribute *attr); /* Attribute lists */ diff --git a/pango/pango-item.c b/pango/pango-item.c index 944bfe2d..ce809066 100644 --- a/pango/pango-item.c +++ b/pango/pango-item.c @@ -276,14 +276,13 @@ pango_analysis_collect_features (const PangoAnalysis *analysis, for (l = analysis->extra_attrs; l && *num_features < length; l = l->next) { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_FONT_FEATURES) + if (attr->type == PANGO_ATTR_FONT_FEATURES) { - PangoAttrFontFeatures *fattr = (PangoAttrFontFeatures *) attr; const gchar *feat; const gchar *end; int len; - feat = fattr->features; + feat = attr->str_value; while (feat != NULL && *num_features < length) { @@ -311,7 +310,7 @@ pango_analysis_collect_features (const PangoAnalysis *analysis, for (l = analysis->extra_attrs; l && *num_features < length; l = l->next) { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_LETTER_SPACING) + if (attr->type == PANGO_ATTR_LETTER_SPACING) { hb_tag_t tags[] = { HB_TAG('l','i','g','a'), diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 7d5ca3cd..94b59427 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -4647,7 +4647,7 @@ static gboolean affects_itemization (PangoAttribute *attr, gpointer data) { - switch ((int)attr->klass->type) + switch ((int)attr->type) { /* These affect font selection */ case PANGO_ATTR_LANGUAGE: @@ -4681,7 +4681,7 @@ static gboolean affects_break_or_shape (PangoAttribute *attr, gpointer data) { - switch ((int)attr->klass->type) + switch ((int)attr->type) { /* Affects breaks */ case PANGO_ATTR_ALLOW_BREAKS: @@ -5515,11 +5515,11 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, attr = pango_attr_iterator_get (&iter, PANGO_ATTR_LINE_HEIGHT); if (attr) - line_height_factor = ((PangoAttrFloat *)attr)->value; + line_height_factor = attr->double_value; attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ABSOLUTE_LINE_HEIGHT); if (attr) - absolute_line_height = ((PangoAttrInt *)attr)->value; + absolute_line_height = attr->int_value; break; } @@ -6572,14 +6572,14 @@ collect_baseline_shift (ParaBreakState *state, { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_RISE) + if (attr->type == PANGO_ATTR_RISE) { - int value = ((PangoAttrInt *)attr)->value; + int value = attr->int_value; *start_y_offset += value; *end_y_offset -= value; } - else if (attr->klass->type == PANGO_ATTR_BASELINE_SHIFT) + else if (attr->type == PANGO_ATTR_BASELINE_SHIFT) { if (attr->start_index == item->offset) { @@ -6590,7 +6590,7 @@ collect_baseline_shift (ParaBreakState *state, entry->attr = attr; state->baseline_shifts = g_list_prepend (state->baseline_shifts, entry); - value = ((PangoAttrInt *)attr)->value; + value = attr->int_value; if (value > 1024 || value < -1024) { @@ -6652,7 +6652,7 @@ collect_baseline_shift (ParaBreakState *state, if (attr->start_index == entry->attr->start_index && attr->end_index == entry->attr->end_index && - ((PangoAttrInt *)attr)->value == ((PangoAttrInt *)entry->attr)->value) + attr->int_value == entry->attr->int_value) { *end_x_offset -= entry->x_offset; *end_y_offset -= entry->y_offset; @@ -6779,10 +6779,10 @@ pango_layout_get_item_properties (PangoItem *item, { PangoAttribute *attr = tmp_list->data; - switch ((int) attr->klass->type) + switch ((int) attr->type) { case PANGO_ATTR_UNDERLINE: - switch (((PangoAttrInt *)attr)->value) + switch (attr->int_value) { case PANGO_UNDERLINE_NONE: break; @@ -6808,7 +6808,7 @@ pango_layout_get_item_properties (PangoItem *item, break; case PANGO_ATTR_OVERLINE: - switch (((PangoAttrInt *)attr)->value) + switch (attr->int_value) { case PANGO_OVERLINE_SINGLE: properties->oline_single = TRUE; @@ -6820,23 +6820,23 @@ pango_layout_get_item_properties (PangoItem *item, break; case PANGO_ATTR_STRIKETHROUGH: - properties->strikethrough = ((PangoAttrInt *)attr)->value; + properties->strikethrough = attr->int_value; break; case PANGO_ATTR_LETTER_SPACING: - properties->letter_spacing = ((PangoAttrInt *)attr)->value; + properties->letter_spacing = attr->int_value; break; case PANGO_ATTR_LINE_HEIGHT: - properties->line_height = ((PangoAttrFloat *)attr)->value; + properties->line_height = attr->double_value; break; case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: - properties->absolute_line_height = ((PangoAttrInt *)attr)->value; + properties->absolute_line_height = attr->int_value; break; case PANGO_ATTR_SHOW: - properties->showing_space = (((PangoAttrInt *)attr)->value & PANGO_SHOW_SPACES) != 0; + properties->showing_space = (attr->int_value & PANGO_SHOW_SPACES) != 0; break; default: diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c index 4e65f489..da052874 100644 --- a/pango/pango-renderer.c +++ b/pango/pango-renderer.c @@ -1411,46 +1411,46 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer, { PangoAttribute *attr = l->data; - switch ((int) attr->klass->type) + switch ((int) attr->type) { case PANGO_ATTR_UNDERLINE: - renderer->underline = ((PangoAttrInt *)attr)->value; + renderer->underline = attr->int_value; break; case PANGO_ATTR_OVERLINE: - renderer->priv->overline = ((PangoAttrInt *)attr)->value; + renderer->priv->overline = attr->int_value; break; case PANGO_ATTR_STRIKETHROUGH: - renderer->strikethrough = ((PangoAttrInt *)attr)->value; + renderer->strikethrough = attr->int_value; break; case PANGO_ATTR_FOREGROUND: - fg_color = &((PangoAttrColor *)attr)->color; + fg_color = &attr->color_value; break; case PANGO_ATTR_BACKGROUND: - bg_color = &((PangoAttrColor *)attr)->color; + bg_color = &attr->color_value; break; case PANGO_ATTR_UNDERLINE_COLOR: - underline_color = &((PangoAttrColor *)attr)->color; + underline_color = &attr->color_value; break; case PANGO_ATTR_OVERLINE_COLOR: - overline_color = &((PangoAttrColor *)attr)->color; + overline_color = &attr->color_value; break; case PANGO_ATTR_STRIKETHROUGH_COLOR: - strikethrough_color = &((PangoAttrColor *)attr)->color; + strikethrough_color = &attr->color_value; break; case PANGO_ATTR_FOREGROUND_ALPHA: - fg_alpha = ((PangoAttrInt *)attr)->value; + fg_alpha = attr->int_value; break; case PANGO_ATTR_BACKGROUND_ALPHA: - bg_alpha = ((PangoAttrInt *)attr)->value; + bg_alpha = attr->int_value; break; default: diff --git a/pango/serializer.c b/pango/serializer.c index ddd9de4c..78bd59a3 100644 --- a/pango/serializer.c +++ b/pango/serializer.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "pango/json/gtkjsonparserprivate.h" @@ -163,46 +164,49 @@ get_weight_name (int weight) return NULL; } -static const char *attr_type_names[] = { - "invalid", - "language", - "family", - "style", - "weight", - "variant", - "stretch", - "size", - "font-desc", - "foreground", - "background", - "underline", - "strikethrough", - "rise", - "scale", - "fallback", - "letter-spacing", - "underline-color", - "strikethrough-color", - "absolute-size", - "gravity", - "gravity-hint", - "font-features", - "foreground-alpha", - "background-alpha", - "allow-breaks", - "show", - "insert-hyphens", - "overline", - "overline-color", - "line-height", - "absolute-line-height", - "text-transform", - "word", - "sentence", - "baseline-shift", - "font-scale", - NULL -}; +static PangoAttrType +get_attr_type (const char *nick) +{ + GEnumClass *enum_class; + GEnumValue *enum_value = NULL; + + enum_class = g_type_class_ref (PANGO_TYPE_ATTR_TYPE); + for (int i = 0; i < enum_class->n_values; i++) + { + enum_value = &enum_class->values[i]; + if (strcmp (enum_value->value_nick, nick) == 0) + break; + enum_value = NULL; + } + g_type_class_unref (enum_class); + + if (enum_value) + return enum_value->value; + + return 0; +} + +static const char * +get_attr_type_name (PangoAttrType type) +{ + GEnumClass *enum_class; + GEnumValue *enum_value = NULL; + + enum_class = g_type_class_ref (PANGO_TYPE_ATTR_TYPE); + for (int i = 0; i < enum_class->n_values; i++) + { + enum_value = &enum_class->values[i]; + if (enum_value->value == type) + break; + enum_value = NULL; + } + g_type_class_unref (enum_class); + + if (enum_value) + return enum_value->value_nick; + + return NULL; +} static const char * get_script_name (PangoScript script) @@ -293,110 +297,106 @@ add_attribute (GtkJsonPrinter *printer, gtk_json_printer_add_integer (printer, "start", (int)attr->start_index); if (attr->end_index != PANGO_ATTR_INDEX_TO_TEXT_END) gtk_json_printer_add_integer (printer, "end", (int)attr->end_index); - gtk_json_printer_add_string (printer, "type", attr_type_names[attr->klass->type]); + gtk_json_printer_add_string (printer, "type", get_attr_type_name (attr->type)); - switch (attr->klass->type) + switch (PANGO_ATTR_VALUE_TYPE (attr)) { - default: - case PANGO_ATTR_INVALID: - g_assert_not_reached (); - case PANGO_ATTR_LANGUAGE: - gtk_json_printer_add_string (printer, "value", pango_language_to_string (((PangoAttrLanguage*)attr)->value)); - break; - case PANGO_ATTR_FAMILY: - case PANGO_ATTR_FONT_FEATURES: - gtk_json_printer_add_string (printer, "value", ((PangoAttrString*)attr)->value); - break; - case PANGO_ATTR_STYLE: - gtk_json_printer_add_string (printer, "value", style_names[((PangoAttrInt*)attr)->value]); + case PANGO_ATTR_VALUE_STRING: + gtk_json_printer_add_string (printer, "value", attr->str_value); break; - case PANGO_ATTR_VARIANT: - gtk_json_printer_add_string (printer, "value", variant_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_VALUE_INT: + switch ((int)attr->type) + { + case PANGO_ATTR_STYLE: + gtk_json_printer_add_string (printer, "value", style_names[attr->int_value]); + break; - case PANGO_ATTR_STRETCH: - gtk_json_printer_add_string (printer, "value", stretch_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_VARIANT: + gtk_json_printer_add_string (printer, "value", variant_names[attr->int_value]); + break; - case PANGO_ATTR_UNDERLINE: - gtk_json_printer_add_string (printer, "value", underline_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_STRETCH: + gtk_json_printer_add_string (printer, "value", stretch_names[attr->int_value]); + break; - case PANGO_ATTR_OVERLINE: - gtk_json_printer_add_string (printer, "value", overline_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_UNDERLINE: + gtk_json_printer_add_string (printer, "value", underline_names[attr->int_value]); + break; - case PANGO_ATTR_GRAVITY: - gtk_json_printer_add_string (printer, "value", gravity_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_OVERLINE: + gtk_json_printer_add_string (printer, "value", overline_names[attr->int_value]); + break; - case PANGO_ATTR_GRAVITY_HINT: - gtk_json_printer_add_string (printer, "value", gravity_hint_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_GRAVITY: + gtk_json_printer_add_string (printer, "value", gravity_names[attr->int_value]); + break; - case PANGO_ATTR_TEXT_TRANSFORM: - gtk_json_printer_add_string (printer, "value", text_transform_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_GRAVITY_HINT: + gtk_json_printer_add_string (printer, "value", gravity_hint_names[attr->int_value]); + break; - case PANGO_ATTR_FONT_SCALE: - gtk_json_printer_add_string (printer, "value", font_scale_names[((PangoAttrInt*)attr)->value]); - break; + case PANGO_ATTR_TEXT_TRANSFORM: + gtk_json_printer_add_string (printer, "value", text_transform_names[attr->int_value]); + break; - case PANGO_ATTR_WEIGHT: - { - const char *name = get_weight_name (((PangoAttrInt*)attr)->value); - if (name) - gtk_json_printer_add_string (printer, "value", name); - else - gtk_json_printer_add_integer (printer, "value", ((PangoAttrInt*)attr)->value); - } - break; + case PANGO_ATTR_FONT_SCALE: + gtk_json_printer_add_string (printer, "value", font_scale_names[attr->int_value]); + break; + + case PANGO_ATTR_WEIGHT: + { + const char *name = get_weight_name (attr->int_value); + if (name) + gtk_json_printer_add_string (printer, "value", name); + else + gtk_json_printer_add_integer (printer, "value", attr->int_value); + } + break; + + case PANGO_ATTR_BASELINE_SHIFT: + gtk_json_printer_add_string (printer, "value", baseline_shift_names[attr->int_value]); + break; + + default: + gtk_json_printer_add_integer (printer, "value", attr->int_value); + break; + } - case PANGO_ATTR_BASELINE_SHIFT: - gtk_json_printer_add_string (printer, "value", baseline_shift_names[((PangoAttrInt*)attr)->value]); break; + case PANGO_ATTR_VALUE_BOOLEAN: + gtk_json_printer_add_boolean (printer, "value", attr->boolean_value); + break; - case PANGO_ATTR_SIZE: - case PANGO_ATTR_RISE: - case PANGO_ATTR_LETTER_SPACING: - case PANGO_ATTR_ABSOLUTE_SIZE: - case PANGO_ATTR_FOREGROUND_ALPHA: - case PANGO_ATTR_BACKGROUND_ALPHA: - case PANGO_ATTR_SHOW: - case PANGO_ATTR_WORD: - case PANGO_ATTR_SENTENCE: - case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: - gtk_json_printer_add_integer (printer, "value", ((PangoAttrInt*)attr)->value); + case PANGO_ATTR_VALUE_LANGUAGE: + gtk_json_printer_add_string (printer, "value", pango_language_to_string (attr->lang_value)); break; - case PANGO_ATTR_FONT_DESC: - str = font_description_to_string (((PangoAttrFontDesc*)attr)->desc); + case PANGO_ATTR_VALUE_FONT_DESC: + str = font_description_to_string (attr->font_value); gtk_json_printer_add_string (printer, "value", str); g_free (str); break; - case PANGO_ATTR_FOREGROUND: - case PANGO_ATTR_BACKGROUND: - case PANGO_ATTR_UNDERLINE_COLOR: - case PANGO_ATTR_OVERLINE_COLOR: - case PANGO_ATTR_STRIKETHROUGH_COLOR: - str = pango_color_to_string (&((PangoAttrColor*)attr)->color); + case PANGO_ATTR_VALUE_COLOR: + str = pango_color_to_string (&attr->color_value); gtk_json_printer_add_string (printer, "value", str); g_free (str); break; - case PANGO_ATTR_STRIKETHROUGH: - case PANGO_ATTR_FALLBACK: - case PANGO_ATTR_ALLOW_BREAKS: - case PANGO_ATTR_INSERT_HYPHENS: - gtk_json_printer_add_boolean (printer, "value", ((PangoAttrInt*)attr)->value != 0); + case PANGO_ATTR_VALUE_FLOAT: + gtk_json_printer_add_number (printer, "value", attr->double_value); break; - case PANGO_ATTR_SCALE: - case PANGO_ATTR_LINE_HEIGHT: - gtk_json_printer_add_number (printer, "value", ((PangoAttrFloat*)attr)->value); + case PANGO_ATTR_VALUE_POINTER: + str = pango_attr_value_serialize (attr); + gtk_json_printer_add_string (printer, "value", str); + g_free (str); + break; + + default: + g_assert_not_reached (); } gtk_json_printer_end (printer); @@ -1158,7 +1158,7 @@ json_to_attribute (GtkJsonParser *parser) break; case ATTR_TYPE: - type = parser_select_string (parser, attr_type_names); + type = get_attr_type (gtk_json_parser_get_string (parser)); break; case ATTR_VALUE: @@ -1172,7 +1172,12 @@ json_to_attribute (GtkJsonParser *parser) while (gtk_json_parser_next (parser)); if (!attr && !gtk_json_parser_get_error (parser)) - gtk_json_parser_schema_error (parser, "Attribute missing \"value\""); + { + if (type == PANGO_ATTR_INVALID) + gtk_json_parser_schema_error (parser, "Invalid attribute \"type\""); + else + gtk_json_parser_schema_error (parser, "Attribute missing \"value\""); + } gtk_json_parser_end (parser); diff --git a/pango/shape.c b/pango/shape.c index 68d11eee..2f2472e7 100644 --- a/pango/shape.c +++ b/pango/shape.c @@ -276,8 +276,8 @@ find_show_flags (const PangoAnalysis *analysis) { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_SHOW) - flags |= ((PangoAttrInt*)attr)->value; + if (attr->type == PANGO_ATTR_SHOW) + flags |= attr->int_value; } return flags; @@ -293,8 +293,8 @@ find_text_transform (const PangoAnalysis *analysis) { PangoAttribute *attr = l->data; - if (attr->klass->type == PANGO_ATTR_TEXT_TRANSFORM) - transform = (PangoTextTransform) ((PangoAttrInt*)attr)->value; + if (attr->type == PANGO_ATTR_TEXT_TRANSFORM) + transform = (PangoTextTransform) attr->int_value; } return transform; diff --git a/tests/markups/valid-19.expected b/tests/markups/valid-19.expected index 5b84133f..9de3df07 100644 --- a/tests/markups/valid-19.expected +++ b/tests/markups/valid-19.expected @@ -4,7 +4,7 @@ test --- range 0 4 -0 4 family Times +0 4 family "Times" 0 4 weight bold 0 4 foreground #ffff00000000 0 4 letter-spacing 1024 diff --git a/tests/markups/valid-4.expected b/tests/markups/valid-4.expected index 345e8699..11ecfab1 100644 --- a/tests/markups/valid-4.expected +++ b/tests/markups/valid-4.expected @@ -31,9 +31,9 @@ range 38 41 38 41 baseline-shift superscript range 41 42 range 42 45 -42 54 family Monospace +42 54 family "Monospace" range 45 54 -42 54 family Monospace +42 54 family "Monospace" 45 54 underline single range 54 2147483647 diff --git a/tests/test-itemize.c b/tests/test-itemize.c index 267c1b62..fc87a959 100644 --- a/tests/test-itemize.c +++ b/tests/test-itemize.c @@ -57,7 +57,7 @@ static gboolean affects_itemization (PangoAttribute *attr, gpointer data) { - switch ((int)attr->klass->type) + switch ((int)attr->type) { /* These affect font selection */ case PANGO_ATTR_LANGUAGE: diff --git a/tests/test-shape.c b/tests/test-shape.c index bbfd91db..a3d4e8b7 100644 --- a/tests/test-shape.c +++ b/tests/test-shape.c @@ -63,7 +63,7 @@ static gboolean affects_itemization (PangoAttribute *attr, gpointer data) { - switch ((int)attr->klass->type) + switch ((int)attr->type) { /* These affect font selection */ case PANGO_ATTR_LANGUAGE: @@ -94,7 +94,7 @@ static gboolean affects_break_or_shape (PangoAttribute *attr, gpointer data) { - switch ((int)attr->klass->type) + switch ((int)attr->type) { /* Affects breaks */ case PANGO_ATTR_ALLOW_BREAKS: diff --git a/tests/testattributes.c b/tests/testattributes.c index 772578de..be98cdd0 100644 --- a/tests/testattributes.c +++ b/tests/testattributes.c @@ -36,7 +36,6 @@ static void test_attributes_basic (void) { PangoFontDescription *desc; - PangoRectangle rect = { 0, 0, 10, 10 }; test_copy (pango_attr_language_new (pango_language_from_string ("ja-JP"))); test_copy (pango_attr_family_new ("Times")); @@ -97,64 +96,110 @@ test_attributes_equal (void) pango_attribute_destroy (attr3); } +static gpointer +copy_my_attribute_data (gconstpointer data) +{ + return (gpointer)data; +} + +static void +destroy_my_attribute_data (gpointer data) +{ +} + +static gboolean +my_attribute_data_equal (gconstpointer data1, + gconstpointer data2) +{ + return data1 == data2; +} + +static char * +my_attribute_data_serialize (gconstpointer data) +{ + return g_strdup_printf ("%p", data); +} + static void test_attributes_register (void) { PangoAttrType type; - GEnumClass *class; + PangoAttribute *attr; + PangoAttribute *attr2; + gpointer value = NULL; + gboolean ret; + PangoAttrList *list; + char *str; + + type = pango_attr_type_register (copy_my_attribute_data, + destroy_my_attribute_data, + my_attribute_data_equal, + "my-attribute", + my_attribute_data_serialize); - type = pango_attr_type_register ("my-attribute"); g_assert_cmpstr (pango_attr_type_get_name (type), ==, "my-attribute"); - class = g_type_class_ref (PANGO_TYPE_ATTR_TYPE); - for (int i = 0; i < class->n_values; i++) - { - g_assert_cmpint (type, !=, class->values[i].value); - g_assert_null (pango_attr_type_get_name (class->values[i].value)); - } + attr = pango_attr_custom_new (type, (gpointer)0x42); + + ret = pango_attribute_get_custom (attr, &value); + g_assert_true (ret); + g_assert_true (value == (gpointer)0x42); + + attr2 = pango_attr_custom_new (type, (gpointer)0x43); - g_type_class_unref (class); + ret = pango_attribute_equal (attr, attr2); + g_assert_false (ret); + + list = pango_attr_list_new (); + pango_attr_list_insert (list, attr2); + + str = pango_attr_list_to_string (list); + g_assert_cmpstr (str, ==, "0 4294967295 my-attribute 0x43"); + g_free (str); + + pango_attr_list_unref (list); + + pango_attribute_destroy (attr); } static void test_binding (PangoAttribute *attr) { - enum { - INVALID, INT, LANGUAGE, STRING, SIZE, FONT_DESC, COLOR, SHAPE, FLOAT, FONT_FEATURES, - } attr_base[] = { - INVALID, LANGUAGE, STRING, INT, INT, INT, INT, SIZE, FONT_DESC, COLOR, - COLOR, INT, INT, INT, SHAPE, FLOAT, INT, INT, COLOR, COLOR, SIZE, - INT, INT, FONT_FEATURES, INT, INT, INT, INT, INT, INT, COLOR, FLOAT, - INT, INT, INT, INT, INT, INT - }; - - switch (attr_base[attr->klass->type]) + int int_value; + gboolean boolean_value; + PangoLanguage *lang_value; + const char *string; + PangoFontDescription *font_desc; + PangoColor color; + double double_value; + gpointer pointer_value; + + switch (PANGO_ATTR_VALUE_TYPE (attr)) { - case INT: - g_assert_nonnull (pango_attribute_as_int (attr)); + case PANGO_ATTR_VALUE_INT: + g_assert_true (pango_attribute_get_int (attr, &int_value)); break; - case LANGUAGE: - g_assert_nonnull (pango_attribute_as_language (attr)); + case PANGO_ATTR_VALUE_BOOLEAN: + g_assert_true (pango_attribute_get_boolean (attr, &boolean_value)); break; - case STRING: - g_assert_nonnull (pango_attribute_as_string (attr)); + case PANGO_ATTR_VALUE_LANGUAGE: + g_assert_true (pango_attribute_get_language (attr, &lang_value)); break; - case SIZE: - g_assert_nonnull (pango_attribute_as_size (attr)); + case PANGO_ATTR_VALUE_STRING: + g_assert_true (pango_attribute_get_string (attr, &string)); break; - case FONT_DESC: - g_assert_nonnull (pango_attribute_as_font_desc (attr)); + case PANGO_ATTR_VALUE_FONT_DESC: + g_assert_true (pango_attribute_get_font_desc (attr, &font_desc)); break; - case COLOR: - g_assert_nonnull (pango_attribute_as_color (attr)); + case PANGO_ATTR_VALUE_COLOR: + g_assert_true (pango_attribute_get_color (attr, &color)); break; - case FLOAT: - g_assert_nonnull (pango_attribute_as_float (attr)); + case PANGO_ATTR_VALUE_FLOAT: + g_assert_true (pango_attribute_get_float (attr, &double_value)); break; - case FONT_FEATURES: - g_assert_nonnull (pango_attribute_as_font_features (attr)); + case PANGO_ATTR_VALUE_POINTER: + g_assert_true (pango_attribute_get_custom (attr, &pointer_value)); break; - case INVALID: default: g_assert_not_reached (); } @@ -166,7 +211,6 @@ static void test_binding_helpers (void) { PangoFontDescription *desc; - PangoRectangle rect = { 0, 0, 10, 10 }; test_binding (pango_attr_language_new (pango_language_from_string ("ja-JP"))); test_binding (pango_attr_family_new ("Times")); @@ -451,7 +495,7 @@ test_list_change5 (void) attr = attribute_from_string ("5 15 style italic"); g_assert (attr->start_index == 5); g_assert (attr->end_index == 15); - g_assert (((PangoAttrInt *)attr)->value == PANGO_STYLE_ITALIC); + g_assert (attr->int_value == PANGO_STYLE_ITALIC); pango_attr_list_change (list, attr); assert_attr_list (list, "0 3 weight ultrabold\n" @@ -740,7 +784,7 @@ never_true (PangoAttribute *attribute, gpointer user_data) static gboolean just_weight (PangoAttribute *attribute, gpointer user_data) { - if (attribute->klass->type == PANGO_ATTR_WEIGHT) + if (attribute->type == PANGO_ATTR_WEIGHT) return TRUE; else return FALSE; @@ -877,7 +921,7 @@ test_iter_get_font (void) list = pango_attr_list_new (); attr = pango_attr_size_new (10 * PANGO_SCALE); pango_attr_list_insert (list, attr); - attr = attribute_from_string ("0 -1 family Times"); + attr = attribute_from_string ("0 -1 family \"Times\""); pango_attr_list_insert (list, attr); attr = attribute_from_string ("10 30 stretch condensed"); pango_attr_list_insert (list, attr); @@ -938,7 +982,7 @@ test_iter_get_attrs (void) list = pango_attr_list_new (); attr = pango_attr_size_new (10 * PANGO_SCALE); pango_attr_list_insert (list, attr); - attr = attribute_from_string ("0 -1 family Times"); + attr = attribute_from_string ("0 -1 family \"Times\""); pango_attr_list_insert (list, attr); attr = attribute_from_string ("10 30 stretch condensed"); pango_attr_list_insert (list, attr); @@ -951,24 +995,24 @@ test_iter_get_attrs (void) iter = pango_attr_list_get_iterator (list); assert_attr_iterator (iter, "0 -1 size 10240\n" - "0 -1 family Times\n"); + "0 -1 family \"Times\"\n"); pango_attr_iterator_next (iter); assert_attr_iterator (iter, "0 -1 size 10240\n" - "0 -1 family Times\n" + "0 -1 family \"Times\"\n" "10 30 stretch 2\n" "10 20 language ja-jp\n"); pango_attr_iterator_next (iter); assert_attr_iterator (iter, "0 -1 size 10240\n" - "0 -1 family Times\n" + "0 -1 family \"Times\"\n" "10 30 stretch 2\n" "20 -1 rise 100\n" "20 -1 fallback 0\n"); pango_attr_iterator_next (iter); assert_attr_iterator (iter, "0 -1 size 10240\n" - "0 -1 family Times\n" + "0 -1 family \"Times\"\n" "20 -1 rise 100\n" "20 -1 fallback 0\n"); @@ -985,7 +1029,7 @@ test_list_update (void) PangoAttrList *list; list = pango_attr_list_from_string ("0 200 rise 100\n" - "5 15 family Times\n" + "5 15 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback 0\n" "30 60 stretch 2\n"); @@ -993,7 +1037,7 @@ test_list_update (void) pango_attr_list_update (list, 8, 10, 20); assert_attr_list (list, "0 210 rise 100\n" - "5 8 family Times\n" + "5 8 family \"Times\"\n" "28 110 fallback false\n" "40 70 stretch condensed\n"); @@ -1020,11 +1064,11 @@ test_list_update3 (void) { PangoAttrList *list; - list = pango_attr_list_from_string ("5 4294967285 family Times\n"); + list = pango_attr_list_from_string ("5 4294967285 family \"Times\"\n"); pango_attr_list_update (list, 8, 10, 30); - assert_attr_list (list, "5 -1 family Times\n"); + assert_attr_list (list, "5 -1 family \"Times\"\n"); pango_attr_list_unref (list); } @@ -1105,28 +1149,28 @@ test_insert (void) PangoAttribute *attr; list = pango_attr_list_from_string ("0 200 rise 100\n" - "5 15 family Times\n" + "5 15 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback 0\n" "30 60 stretch 2\n"); - attr = attribute_from_string ("10 25 family Times"); + attr = attribute_from_string ("10 25 family \"Times\""); pango_attr_list_change (list, attr); assert_attr_list (list, "0 200 rise 100\n" - "5 25 family Times\n" + "5 25 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback false\n" "30 60 stretch condensed\n"); - attr = attribute_from_string ("11 25 family Futura"); + attr = attribute_from_string ("11 25 family \"Futura\""); pango_attr_list_insert (list, attr); assert_attr_list (list, "0 200 rise 100\n" - "5 25 family Times\n" + "5 25 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback false\n" - "11 25 family Futura\n" + "11 25 family \"Futura\"\n" "30 60 stretch condensed\n"); pango_attr_list_unref (list); @@ -1139,21 +1183,21 @@ test_insert2 (void) PangoAttribute *attr; list = pango_attr_list_from_string ("0 200 rise 100\n" - "5 15 family Times\n" + "5 15 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback 0\n" - "20 30 family Times\n" - "30 40 family Futura\n" + "20 30 family \"Times\"\n" + "30 40 family \"Futura\"\n" "30 60 stretch 2\n"); - attr = attribute_from_string ("10 35 family Times"); + attr = attribute_from_string ("10 35 family \"Times\""); pango_attr_list_change (list, attr); assert_attr_list (list, "0 200 rise 100\n" - "5 35 family Times\n" + "5 35 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback false\n" - "35 40 family Futura\n" + "35 40 family \"Futura\"\n" "30 60 stretch condensed\n"); pango_attr_list_unref (list); @@ -1175,7 +1219,7 @@ test_merge (void) PangoAttrList *list2; list = pango_attr_list_from_string ("0 200 rise 100\n" - "5 15 family Times\n" + "5 15 family \"Times\"\n" "10 11 size 10240\n" "11 100 fallback 0\n" "30 60 stretch 2\n"); @@ -1187,7 +1231,7 @@ test_merge (void) pango_attr_list_filter (list2, attr_list_merge_filter, list); assert_attr_list (list, "0 200 rise 100\n" - "5 15 family Times\n" + "5 15 family \"Times\"\n" "10 13 size 10240\n" "11 100 fallback false\n" "13 15 size 11264\n" @@ -1253,25 +1297,25 @@ print_tags_for_attributes (PangoAttrIterator *iter, if (attr) g_string_append_printf (s, "%d %d rise %d\n", attr->start_index, attr->end_index, - ((PangoAttrInt*)attr)->value); + attr->int_value); attr = pango_attr_iterator_get (iter, PANGO_ATTR_SIZE); if (attr) g_string_append_printf (s, "%d %d size %d\n", attr->start_index, attr->end_index, - ((PangoAttrInt*)attr)->value); + attr->int_value); attr = pango_attr_iterator_get (iter, PANGO_ATTR_SCALE); if (attr) g_string_append_printf (s, "%d %d scale %f\n", attr->start_index, attr->end_index, - ((PangoAttrFloat*)attr)->value); + attr->double_value); attr = pango_attr_iterator_get (iter, PANGO_ATTR_ALLOW_BREAKS); if (attr) g_string_append_printf (s, "%d %d allow_breaks %d\n", attr->start_index, attr->end_index, - ((PangoAttrInt*)attr)->value); + attr->int_value); } static void diff --git a/tests/testserialize.c b/tests/testserialize.c index e480da31..f8a7bca3 100644 --- a/tests/testserialize.c +++ b/tests/testserialize.c @@ -36,7 +36,7 @@ test_serialize_attr_list (void) "0 100 font-desc \"Cantarell, Sans, Italic Ultra-Light 64\", 10 11 weight 100", "0 -1 size 10", "0 1 weight 700, 2 4 weight book", - "0 200 rise 100\n5 15 family Times\n10 11 size 10240\n11 100 fallback 0\n30 60 stretch 2\n", + "0 200 rise 100\n5 15 family \"Times\"\n10 11 size 10240\n11 100 fallback 0\n30 60 stretch 2\n", "" }; const char *roundtripped[] = { @@ -47,7 +47,7 @@ test_serialize_attr_list (void) "0 100 font-desc \"Cantarell,Sans Ultra-Light Italic 64\"\n10 11 weight thin", "0 4294967295 size 10", "0 1 weight bold\n2 4 weight book", - "0 200 rise 100\n5 15 family Times\n10 11 size 10240\n11 100 fallback false\n30 60 stretch condensed", + "0 200 rise 100\n5 15 family \"Times\"\n10 11 size 10240\n11 100 fallback false\n30 60 stretch condensed", "" }; const char *invalid[] = { @@ -366,7 +366,7 @@ test_serialize_layout_invalid (void) " }\n" " ]\n" "}\n", - PANGO_LAYOUT_DESERIALIZE_INVALID_VALUE + PANGO_LAYOUT_DESERIALIZE_MISSING_VALUE }, { "{\n" @@ -382,7 +382,7 @@ test_serialize_layout_invalid (void) "{\n" " \"attributes\" : [\n" " {\n" - " \"type\" : \"alignment\",\n" + " \"type\" : \"background\",\n" " \"value\" : \"nonsense\"\n" " }\n" " ]\n" -- cgit v1.2.1