GNOME Bugzilla – Bug 511130
Extending standard attributes
Last modified: 2018-05-22 12:39:18 UTC
PangoAttribute is not a GType type and I seem to need to reinvent GType here... Basic way to summarize the missing feature is: pango hardcodes some attribute types in code, basically all the predefined attribute types. A user-define attribute never has a chance to be treated similar to PANGO_ATTR_SHAPE for example. I want to fix that. Concrete usecase for this is: currently PANGO_ATTR_SHAPE is very hard to use, much harder than it needs to be. I added pango_cairo_context_set_shape_renderer() which greatly simplifies that, so one doesn't have to implement a PangoRenderer to use shape attributes meaningfully anymore (ok, one didn't have to, see GtkTextView for example), but the biggest caveat still remains: It's hard for custom renders in libraries (like gdkpango) to add useful shape renderers (like rendering a GdkPixbuf) without taking full control of ATTR_SHAPE out of user's hand. Instead of bandaiding that around ATTR_SHAPE I want to fix it properly (to the extent possible by compatibility). Here is my proposal: - Currently PangoAttrType's are assigned to predefined attributes from 0 (in the PangoAttrType enum) and allocated from 1000 up for custom attributes, in pango_attr_type_register(). We logically divide that integer "type" value into two parts: lowest byte as base type, three other bytes as instance type. - New API for creating new instances of other attribute types. We can only support shallow one-level subtyping here but that's all we care about. Proposed API: PangoAttrType pango_attr_type_register_similar (const gchar *name, PangoAttrType similar_type); Not sure about the name... What this does is to set the lower byte of the returned attr type to the lower byte of the base_type. And a getter: PangoAttrType pango_attr_type_get_base_type (PangoAttrType attr_type); Base types are defined as those defined by Pango. An attribute registered using pango_attr_type_register() has base type PANGO_ATTR_INVALID. - New API for attribute type similarity checking. This checks that the lower byte of attribute types for equality, but this is just the implementation detail and private, publicly just a function: gboolean pango_attr_type_similar (PangoAttrType first_type, PangoAttrType second_type); And a convenience one for actual attributes: gboolean pango_attr_similar_to (PangoAttribute *attr, PangoAttrType other_type); Note that this test only means that the type of attr and other_type have the same base type. attr is not necessarily of type other_type. As I said, shallow typing only... - Change Pango internals to always check for attribute base type instead of exact type. For example, in pango-renderer.c, instead of this: switch (attr->klass->type) { case PANGO_ATTR_SHAPE: if (shape_attr) *shape_attr = (PangoAttrShape *)attr; break; ... } We'll have: switch (pango_attr_type_get_base_type (attr->klass->type)) { case PANGO_ATTR_SHAPE: if (shape_attr) *shape_attr = (PangoAttrShape *)attr; break; ... } - pango_cairo_context_set_shape_renderer() only sets shape renderer for ATTR_SHAPE. Add new API for setting shape renderer for custom shape attributes: void pango_cairo_context_set_shape_renderer_for_attr_type (PangoContext *context, PangoAttrType attr_type, PangoCairoShapeRendererFunc func, gpointer data, GDestroyNotify dnotify) { g_return_if_fail (pango_attr_type_get_base_type (attr_type) != PANGO_ATTR_SHAPE); ... } That's all. With all that, we can then add the following gdkpango API: PangoAttribute * gdk_pango_attribute_pixbuf_new (GdkPixbuf *pixbuf, int width, int height, ...); Then in gdk_pango_context_get(), register shape renderer for the type GDK_PANGO_ATTR_PIXBUF on the context being returned. This way they user is free to use ATTR_SHAPE as they wish. The only problem with this being that all shape renderers need to be set on all PangoContext's. That's not totally infeasible, but is a bit of a burden. To fix that, we can provide PangoCairoRenderer API for that too, when we subclass PangoRenderer in gdkpango. Owen, Matthias, comments?
Bug 116115 should be resolved at the same time. Late today, I'll go ahead and give this a try in for the next devel release.
It occurred to me that attribute extensions can be used to implement things like RGBA color attributes (say, for cairo backend only, or just as an extension of the RGB color attribtues) ala bug 413941. However, this just reveals that the flat inheritance scheme I described in this bug is suboptimal, as I wasn't thinking about the case of having extension attributes in pango and pango backends themselves.
Created attachment 122430 [details] [review] Unfinished patch I think I did the bitwise operators wrong.. I think I've got the base type on the wrong side of int. Also still need to find all the places that need to switch to use the new API.
Created attachment 122746 [details] [review] Updates (still unfinished) This adds the pango_cairo_context_set_shape_renderer_for_attr_type() API and other related changes.
Behdad, you suggested on IRC the other day of doing more than one level of attribute extending. Is that still something you're interested in doing? Was the idea that you have the base attribute in one word, then allow up to three levels of attribute extending in the other words?
Created attachment 122747 [details] [review] Minor cleanup
Uhh, I think I meant to say 'bytes' instead of 'words' in Comment #5. :)
Created attachment 125241 [details] [review] Updated patch Okay, getting back to this bug now. Here is an updated patch, and I added a unit test for the basic attribute inheritance system. It's not very thorough yet, but it tests to make sure that the basic stuff works. It creates attributes: "German" from PANGO_ATTR_TYPE_LANGUAGE "SwissGerman" from "German" "French" from PANGO_ATTR_TYPE_LANGUAGE Then it tests: German is a German German is a Language SwissGerman is a Language SwissGerman is a Language French is not a German That's obviously not very thorough, but it's something. And if you're interested I posted a git branch (based on git-mirror.gnome.org): http://github.com/bratsche/pango/tree/extended_attributes
SwissGerman is a Language SwissGerman is a Language Uhh, that was a typo. The second one was meant to say "SwissGerman is a German"
Looks great! The bitmask operations bother me a bit. "(attr_type & 0xffffff00) >> 8" definitely can simply be "attr_type >> 8". Otherwise it's doing exactly what it should be. I suggest we rename create_similar() to create_full(..., parent_type). And get_base_type() to get_parent_type(). I'll look into landing this when I get back to pango hacking. Thanks Cody!
Created attachment 125291 [details] [review] Bitmask fixes, function renames Hi Behdad, thanks very much for your comments! This patch I think fixes the things in your comments. Whenever you get back to Pango hacking, let me know if there's anything else I can do with this.
I deleted my old git branch, because it was based on a git-svn checkout, and I've posted a new git branch that is based on git.gnome.org/pango http://github.com/bratsche/pango/tree/master
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/pango/issues/119.