From ee0197d50d923d435a87d9f621ea3f48c08d9684 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 6 Feb 2022 06:35:57 -0500 Subject: Add PangoAttrAffects Declare what part of the pipeline an attribute affects as part of the type. This lets us handle attribute filtering for that purpose in a generalized fashion. --- pango/pango-attr.c | 82 +++++++++++++++++++++--------------------------- pango/pango-attr.h | 50 +++++++++++++++++++++++++---- pango/pango-attributes.h | 74 +++++++++++++++++++++---------------------- pango/pango-layout.c | 45 ++------------------------ tests/testattributes.c | 12 ++++--- 5 files changed, 128 insertions(+), 135 deletions(-) diff --git a/pango/pango-attr.c b/pango/pango-attr.c index 0314bdcf..048cabb6 100644 --- a/pango/pango-attr.c +++ b/pango/pango-attr.c @@ -59,13 +59,15 @@ get_attr_type_nick (PangoAttrType type) /** * pango_attr_type_register: - * @copy: function to copy the data of an attribute + * @name: (nullable): an identifier for the type + * @value_type: the `PangoAttrValueType` for the attribute + * @affects: `PangoAttrAffects` flags for the attribute + * @copy: (nullable): function to copy the data of an attribute * of this type - * @destroy: function to free the data of an attribute + * @destroy: (nullable): function to free the data of an attribute * of this type - * @equal: function to compare the data of two attributes + * @equal: (nullable): 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 * @@ -74,7 +76,11 @@ get_attr_type_nick (PangoAttrType type) * The attribute type name can be accessed later * by using [func@Pango.AttrType.get_name]. * - * If @name and to @serialize are provided, they will be used + * The callbacks are only needed if @type is `PANGO_ATTR_VALUE_POINTER`, + * Pango knows how to handle other value types and will only use the + * callbacks for generic pointer values. + * + * If @name and @serialize are provided, they will be used * to serialize attributes of this type. * * To create attributes with the new type, use [func@Pango.attr_custom_new]. @@ -82,10 +88,12 @@ get_attr_type_nick (PangoAttrType type) * Return value: the attribute type ID */ guint -pango_attr_type_register (PangoAttrDataCopyFunc copy, +pango_attr_type_register (const char *name, + PangoAttrValueType value_type, + PangoAttrAffects affects, + PangoAttrDataCopyFunc copy, GDestroyNotify destroy, GEqualFunc equal, - const char *name, PangoAttrDataSerializeFunc serialize) { static guint current_id = MIN_CUSTOM; /* MT-safe */ @@ -93,7 +101,7 @@ pango_attr_type_register (PangoAttrDataCopyFunc copy, G_LOCK (attr_type); - class.type = PANGO_ATTR_VALUE_POINTER | (current_id << 8); + class.type = value_type | (affects << 8) | (current_id << 16); current_id++; class.copy = copy; @@ -139,7 +147,7 @@ pango_attr_type_get_name (guint type) { const char *result = NULL; - if ((type >> 8) < MIN_CUSTOM) + if ((type >> 16) < MIN_CUSTOM) return get_attr_type_nick (type); G_LOCK (attr_type); @@ -208,9 +216,8 @@ pango_attribute_copy (const PangoAttribute *attr) G_UNLOCK (attr_type); - g_assert (copy != NULL); - - result->pointer_value = copy (attr->pointer_value); + if (copy) + result->pointer_value = copy (attr->pointer_value); } break; @@ -266,9 +273,8 @@ pango_attribute_destroy (PangoAttribute *attr) G_UNLOCK (attr_type); - g_assert (destroy != NULL); - - destroy (attr->pointer_value); + if (destroy) + destroy (attr->pointer_value); } break; @@ -355,7 +361,10 @@ pango_attribute_equal (const PangoAttribute *attr1, g_assert (equal != NULL); - return equal (attr1->pointer_value, attr2->pointer_value); + if (equal) + return equal (attr1->pointer_value, attr2->pointer_value); + + return attr1->pointer_value == attr2->pointer_value; } default: @@ -364,52 +373,33 @@ pango_attribute_equal (const PangoAttribute *attr1, } /** - * pango_attr_custom_new: + * pango_attribute_new: * @type: the attribute type - * @user_data: data for the attribute * * Creates a new attribute for the given type. * * The type must have been registered with [func@Pango.register_attr_type] - * before. @user_data will be copied with the copy function that - * was given when the type was registered. + * before or be one of the `PangoAttrType` values. + * + * Pango will initialize @start_index and @end_index to an + * all-inclusive range of `[0,G_MAXUINT]`. + * + * The caller is responsible for filling the proper value field + * with the desired value. * * Return value: (transfer full): the newly allocated * `PangoAttribute`, which should be freed with * [method@Pango.Attribute.destroy] */ PangoAttribute * -pango_attr_custom_new (guint type, - gpointer user_data) +pango_attribute_new (guint type) { PangoAttribute *attr; - PangoAttrDataCopyFunc copy = NULL; - - g_return_val_if_fail (PANGO_ATTR_TYPE_VALUE_TYPE (type) == PANGO_ATTR_VALUE_POINTER, NULL); - - G_LOCK (attr_type); - - g_assert (attr_type != NULL); - - for (int i = 0; i < attr_type->len; i++) - { - PangoAttrClass *class = &g_array_index (attr_type, PangoAttrClass, i); - if (class->type == type) - { - copy = class->copy; - break; - } - } - - g_assert (copy != NULL); - - G_UNLOCK (attr_type); - attr = g_slice_new (PangoAttribute); + attr = g_slice_new0 (PangoAttribute); attr->type = type; attr->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING; attr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END; - attr->pointer_value = copy (user_data); return attr; } @@ -441,7 +431,7 @@ pango_attr_value_serialize (PangoAttribute *attr) if (serialize) return serialize (attr->pointer_value); - return NULL; + return g_strdup_printf ("%p", attr->pointer_value); } /* }}} */ diff --git a/pango/pango-attr.h b/pango/pango-attr.h index 7258d3ff..aa63960b 100644 --- a/pango/pango-attr.h +++ b/pango/pango-attr.h @@ -59,6 +59,27 @@ typedef enum PANGO_ATTR_VALUE_POINTER } PangoAttrValueType; +/** + * PangoAttrAffects: + * @PANGO_ATTR_AFFECTS_ITEMIZATION: the attribute affecs itemization + * @PANGO_ATTR_AFFECTS_BREAKING: the attribute affects `PangoLogAttr` determination + * @PANGO_ATTR_AFFECTS_SHAPING: the attribute affects shaping + * @PANGO_ATTR_AFFECTS_RENDERING: the attribute affects rendering + * + * Flags to indicate what part of Pangos processing pipeline is + * affected by an attribute. + * + * Marking an attribute with `PANGO_ATTR_AFFECTS_ITEMIZATION` ensures + * that the attribute values are constant across items. + */ +typedef enum +{ + PANGO_ATTR_AFFECTS_ITEMIZATION = 1 << 0, + PANGO_ATTR_AFFECTS_BREAKING = 1 << 1, + PANGO_ATTR_AFFECTS_SHAPING = 1 << 2, + PANGO_ATTR_AFFECTS_RENDERING = 1 << 3 +} PangoAttrAffects; + /** * PANGO_ATTR_TYPE_VALUE_TYPE: * @type: an attribute type @@ -67,6 +88,14 @@ typedef enum */ #define PANGO_ATTR_TYPE_VALUE_TYPE(type) ((PangoAttrValueType)((type) & 0xff)) +/** + * PANGO_ATTR_TYPE_AFFECTS: + * @type: an attribute type + * + * Extracts the `PangoAttrAffects` flags from an attribute type. + */ +#define PANGO_ATTR_TYPE_AFFECTS(type) ((PangoAttrAffects)(((type) >> 8) & 0xff)) + /** * PANGO_ATTR_VALUE_TYPE: * @attr: a `PangoAttribute` @@ -75,6 +104,14 @@ typedef enum */ #define PANGO_ATTR_VALUE_TYPE(attr) PANGO_ATTR_TYPE_VALUE_TYPE ((attr)->type) +/** + * PANGO_ATTR_AFFECTS: + * @attr: a `PangoAttribute` + * + * Obtains the `PangoAttrAffects` flags of a `PangoAttribute`. + */ +#define PANGO_ATTR_AFFECTS(attr) PANGO_ATTR_TYPE_AFFECTS ((attr)->type) + /** * PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING: * @@ -97,7 +134,7 @@ typedef enum /** * PangoAttribute: - * @klass: the class structure holding information about the type of the attribute + * @type: the type of the attribute * @start_index: the start index of the range (in bytes). * @end_index: end index of the range (in bytes). The character at this index * is not included in the range. @@ -116,7 +153,7 @@ typedef enum * The common portion of the attribute holds the range to which * the value in the type-specific part of the attribute applies. * By default, an attribute will have an all-inclusive range of - * [0,%G_MAXUINT]. + * `[0,G_MAXUINT]`. * * Which of the values is used depends on the value type of the * attribute, which can be obtained with `PANGO_ATTR_VALUE_TYPE()`. @@ -162,10 +199,12 @@ PANGO_AVAILABLE_IN_ALL GType pango_attribute_get_type (void) G_GNUC_CONST; PANGO_AVAILABLE_IN_ALL -guint pango_attr_type_register (PangoAttrDataCopyFunc copy, +guint pango_attr_type_register (const char *name, + PangoAttrValueType value_type, + PangoAttrAffects affects, + PangoAttrDataCopyFunc copy, GDestroyNotify destroy, GEqualFunc equal, - const char *name, PangoAttrDataSerializeFunc serialize); PANGO_AVAILABLE_IN_1_22 @@ -179,8 +218,7 @@ gboolean pango_attribute_equal (const PangoAttr const PangoAttribute *attr2) G_GNUC_PURE; PANGO_AVAILABLE_IN_1_52 -PangoAttribute * pango_attr_custom_new (guint type, - gpointer user_data); +PangoAttribute * pango_attribute_new (guint type); PANGO_AVAILABLE_IN_1_52 gboolean pango_attribute_get_string (PangoAttribute *attribute, diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index 0dc9146d..edd49fed 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -28,7 +28,7 @@ G_BEGIN_DECLS -#define PANGO_ATTR_TYPE(value) (PANGO_ATTR_VALUE_##value | (__COUNTER__ << 8)) +#define PANGO_ATTR_TYPE(value, affects) (PANGO_ATTR_VALUE_##value | (PANGO_ATTR_AFFECTS_##affects << 8) | (__COUNTER__ << 16)) /** * PangoAttrType: * @PANGO_ATTR_INVALID: does not happen @@ -77,42 +77,42 @@ G_BEGIN_DECLS typedef enum { 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), + PANGO_ATTR_LANGUAGE = PANGO_ATTR_TYPE (LANGUAGE, ITEMIZATION), + PANGO_ATTR_FAMILY = PANGO_ATTR_TYPE (STRING, ITEMIZATION), + PANGO_ATTR_STYLE = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_WEIGHT = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_VARIANT = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_STRETCH = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_SIZE = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_FONT_DESC = PANGO_ATTR_TYPE (FONT_DESC, ITEMIZATION), + PANGO_ATTR_FOREGROUND = PANGO_ATTR_TYPE (COLOR, RENDERING), + PANGO_ATTR_BACKGROUND = PANGO_ATTR_TYPE (COLOR, RENDERING), + PANGO_ATTR_UNDERLINE = PANGO_ATTR_TYPE (INT, RENDERING), + PANGO_ATTR_STRIKETHROUGH = PANGO_ATTR_TYPE (BOOLEAN, RENDERING), + PANGO_ATTR_RISE = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_SCALE = PANGO_ATTR_TYPE (FLOAT, ITEMIZATION), + PANGO_ATTR_FALLBACK = PANGO_ATTR_TYPE (BOOLEAN, ITEMIZATION), + PANGO_ATTR_LETTER_SPACING = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_UNDERLINE_COLOR = PANGO_ATTR_TYPE (COLOR, RENDERING), + PANGO_ATTR_STRIKETHROUGH_COLOR = PANGO_ATTR_TYPE (COLOR, RENDERING), + PANGO_ATTR_ABSOLUTE_SIZE = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_GRAVITY = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_GRAVITY_HINT = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_FONT_FEATURES = PANGO_ATTR_TYPE (STRING, SHAPING), + PANGO_ATTR_FOREGROUND_ALPHA = PANGO_ATTR_TYPE (INT, RENDERING), + PANGO_ATTR_BACKGROUND_ALPHA = PANGO_ATTR_TYPE (INT, RENDERING), + PANGO_ATTR_ALLOW_BREAKS = PANGO_ATTR_TYPE (BOOLEAN, BREAKING), + PANGO_ATTR_SHOW = PANGO_ATTR_TYPE (INT, SHAPING), + PANGO_ATTR_INSERT_HYPHENS = PANGO_ATTR_TYPE (BOOLEAN, SHAPING), + PANGO_ATTR_OVERLINE = PANGO_ATTR_TYPE (INT, RENDERING), + PANGO_ATTR_OVERLINE_COLOR = PANGO_ATTR_TYPE (COLOR, RENDERING), + PANGO_ATTR_LINE_HEIGHT = PANGO_ATTR_TYPE (FLOAT, ITEMIZATION), + PANGO_ATTR_ABSOLUTE_LINE_HEIGHT = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_TEXT_TRANSFORM = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_WORD = PANGO_ATTR_TYPE (BOOLEAN, BREAKING), + PANGO_ATTR_SENTENCE = PANGO_ATTR_TYPE (BOOLEAN, BREAKING), + PANGO_ATTR_BASELINE_SHIFT = PANGO_ATTR_TYPE (INT, ITEMIZATION), + PANGO_ATTR_FONT_SCALE = PANGO_ATTR_TYPE (INT, ITEMIZATION), } PangoAttrType; #undef PANGO_ATTR_TYPE diff --git a/pango/pango-layout.c b/pango/pango-layout.c index d0cc812c..2a92dbda 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -4648,54 +4648,15 @@ static gboolean affects_itemization (PangoAttribute *attr, gpointer data) { - switch ((int)attr->type) - { - /* These affect font selection */ - case PANGO_ATTR_LANGUAGE: - case PANGO_ATTR_FAMILY: - case PANGO_ATTR_STYLE: - case PANGO_ATTR_WEIGHT: - case PANGO_ATTR_VARIANT: - case PANGO_ATTR_STRETCH: - case PANGO_ATTR_SIZE: - case PANGO_ATTR_FONT_DESC: - case PANGO_ATTR_SCALE: - case PANGO_ATTR_FALLBACK: - case PANGO_ATTR_ABSOLUTE_SIZE: - case PANGO_ATTR_GRAVITY: - case PANGO_ATTR_GRAVITY_HINT: - case PANGO_ATTR_FONT_SCALE: - /* These need to be constant across runs */ - case PANGO_ATTR_LETTER_SPACING: - case PANGO_ATTR_RISE: - case PANGO_ATTR_BASELINE_SHIFT: - case PANGO_ATTR_LINE_HEIGHT: - case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT: - case PANGO_ATTR_TEXT_TRANSFORM: - return TRUE; - default: - return FALSE; - } + return (PANGO_ATTR_AFFECTS (attr) & PANGO_ATTR_AFFECTS_ITEMIZATION) != 0; } static gboolean affects_break_or_shape (PangoAttribute *attr, gpointer data) { - switch ((int)attr->type) - { - /* Affects breaks */ - case PANGO_ATTR_ALLOW_BREAKS: - case PANGO_ATTR_WORD: - case PANGO_ATTR_SENTENCE: - /* Affects shaping */ - case PANGO_ATTR_INSERT_HYPHENS: - case PANGO_ATTR_FONT_FEATURES: - case PANGO_ATTR_SHOW: - return TRUE; - default: - return FALSE; - } + return (PANGO_ATTR_AFFECTS (attr) & (PANGO_ATTR_AFFECTS_BREAKING | + PANGO_ATTR_AFFECTS_SHAPING)) != 0; } static void diff --git a/tests/testattributes.c b/tests/testattributes.c index be98cdd0..4e095b76 100644 --- a/tests/testattributes.c +++ b/tests/testattributes.c @@ -131,21 +131,25 @@ test_attributes_register (void) PangoAttrList *list; char *str; - type = pango_attr_type_register (copy_my_attribute_data, + type = pango_attr_type_register ("my-attribute", + PANGO_ATTR_VALUE_POINTER, + PANGO_ATTR_AFFECTS_RENDERING, + copy_my_attribute_data, destroy_my_attribute_data, my_attribute_data_equal, - "my-attribute", my_attribute_data_serialize); g_assert_cmpstr (pango_attr_type_get_name (type), ==, "my-attribute"); - attr = pango_attr_custom_new (type, (gpointer)0x42); + attr = pango_attribute_new (type); + attr->pointer_value = (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); + attr2 = pango_attribute_new (type); + attr2->pointer_value = (gpointer)0x43; ret = pango_attribute_equal (attr, attr2); g_assert_false (ret); -- cgit v1.2.1