Over the last few days I've gotten around to finishing up GTK+ support for PangoRenderer and adding rotation support to GtkLabel. My initial plans (http://mail.gnome.org/archives/gtk-i18n-list/2004-July/msg00014.html) called for having a class structure in GTK+ like: PangoRenderer PangoXftRenderer /\ /\ || || || || GdkPangoRenderer --impl----> GdkX11Renderer /\ || || GtkTextViewRenderer It turns out that this "has a" relationship where GdkPangoRenderer chains directly to GdkX11Renderer doesn't work very well, because it bypasses the GdkDrawable vtable. And if you bypass the GdkDrawable vtable all the wrapper drawable, automatic double buffering, etc, becomes a real nuisance. So, what I ended up doing was adding 'draw_glyphs_transformed' and 'draw_trapezoids' virtual functions to the drawable vtable. draw_trapezoids has a default implementation in terms of draw_pixbuf(), which was needed for the non-RENDER case on X, and also should make getting this going on other backends easier. There is still a GdkX11Renderer subclass of PangoXftRenderer, but it's only used to implement draw_glyphs_transformed(); the complicated chaining of property changes between the two renderers is now gone. This allowed me to remove the 'color_set' virtual function from PangoRenderer vtable and simplify that a bit. Since we added Xft support to GTK+, we haven't supported tile or stipples for text. With these patches that lack crept into the backgrounds and underlines for the text as well since we are are now drawing them with XRenderCompositeTrapezoids(). So, I went ahead and fixed tile and stipple support for the render-based codepath. In the render code path insensitive text now displays precisely as intended -- embossed for the default colors, and stippled when the foreground or background is set. I also added a demo to GTK+ demo showing drawing rotated antialiased text with GDK using a tile image. Which was neat, until it started triggering a bug in RENDER and using random bits of the root window instead of the right tile. Tile and stipples are not currently supported in the fallback case, doing this for text is basically impossible because Xft doesn't expose any way of getting at the bits; perhaps fixing this is best left until after the Cairo switch. The GtkLabel API for rotated labels is really simple: void gtk_label_set_angle (GtkLabel *label, gdouble angle); gdouble gtk_label_get_angle (GtkLabel *label); And a corresponding 'angle' property. gtk_label_set_angle takes any angle in degrees, but canonicalizes it to the [0,360] range of the property. I also converted GtkTextView to use PangoRenderer. It turned out that what gtktextdisplay.c was doing to match PangoAttrShape attributes to embedded widgets or pixbuf was really inconvenient once PangoRenderer was introduced: it was keeping a linked list of widgets, and pixbufs and matching that up by order... something that didn't even work properly for objects embedded within a right-to-left or bidi line. So, I introduced: typedef gpointer (*PangoAttrDataCopyFunc) (gconstpointer data); PangoAttribute *pango_attr_shape_new_with_data (const PangoRectangle *ink_rect, const PangoRectangle *logical_rect, gpointer data, PangoAttrDataCopyFunc copy_func, GDestroyNotify destroy_func); to allow storing user data on a PangoAttrShape for doing the back association, which works out much more nicely. Unfortunately, the linked list for association is in the semi-public API ... struct _GtkTextLineDisplay { [...] GSList *shaped_objects; [...] } So I couldn't remove it. The code currently still adds the objects to the list for maximum compatbility, but the list is otherwise unused. I'm pretty happy about the current state of this. I've landed the Pango changes into CVS. The only possibly open API issue with the GTK+ part is that gdk_pango_renderer_new() and gdk_pango_renderer_get_default() take a screen parameter. While this was needed in the original design, the screen parameter is currently superfluous and could be removed. I'm of two minds about that, while removing it would make things a little simpler for users, it does leave the door open for caching of screen specific resources. Also, for gdk_pango_renderer_get_default() it fits the pattern of keeping global resources per-screen or per-display and thus freed on display close. The main remaining issue for getting the GTK+ changes into CVS is Win32 support. Possible steps in that direction: - Simply implement drawable.draw_glyphs_transformed by calling drawable.draw_glyphs. That would at least keep what works currently working, but rotated text wouldn't work. Approximate time - 10 minutes. - Implement support in PangoWin32Font for loading fonts with transformation matrices and implement pango_win32_render_transformed(). This is sufficient to get rotated text working. Approximate time - 2-3 hours(?) - Implement a PangoWin32Renderer. Not really needed for GDK, but would clean up duplicated code and provide some new capabilities. Approximate time - 2-3 hours(???) - Implement drawable.draw_trapezoids using GDI (and/or GDI+) rather than the fallback code to improve efficiency and get tiles/stipples working. Approximate time - unknown. Note the saturated-add-then-composite semantic of draw_trapezoids, which is needed to prevent seams. Attached are ChangeLog, header file snippets for new API, and the entire patch (compressed). The patch includes docs and testgtk and gtk-demo additions.
Sat Nov 20 15:13:51 2004 Owen Taylor <otaylor redhat com> * gdk/gdkpango.[ch]: Add GdkPangoRenderer, a subclass of PangoRenderer targeting GDK drawables. Use to implement the old gdk_draw_layout() and friends. * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkwindow.c gdk/gdkpixmap.c: Add gdk_draw_glyphs_transformed() gdk_draw_trapezoids() and the corresponding members of GdkDrawableClass. Add a fallback implementation of gdk_draw_trapezoids() in terms of pixbufs. * gdk/gdkwindowing.h gdk/x11/gdkg-x11.h: Add _gdk_windowing_gc_get_foreground() to enable the fallback trapezoid implementation. * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkdisplay-x11.h: Implement draw_glyph_transformed, draw_trapezoids. * gdk/x11/gdkdrawable-x11.[ch]: Add _gdk_x11_drawable_draw_xtrapezoids, _gdk_x11_drawable_draw_xft_glyphs for use of GdkX11Renderer. * gdk/x11/gdkgc-x11.c gdk/x11/gdkprivate-x11.h: Implement GDK_TILED, GDK_STIPPLED, GDK_OPAQUE_STIPPLED in the RENDER codepath. * gdk/gdkpango-x11.c: Add GdkX11Renderer... a subclass of PangoXftRenderer that does tiles/stipples and fallback rendering of trapezoids without the RENDER extension. * gdk/gdkpango-x11.c gdk/x11/gdkscreen-x11.[ch] _gdk_x11_renderer_get: Add _gdk_x11_renderer_get() to get a singleton GdkX11Renderer for the screen. * gdk/x11/gdkdrawable-x11.c (get_impl_drawable): Fix a None/NULL confusion. * gtk/gtklabel.[ch] gtk/gtk.symbols: Add gtk_label_set/get_angle(), and an ::angle property. * gtk/gtklabel.c: Remove #if 0'd dead code gtk_label_paint_word(). * gtk/gtktextdisplay.c: Switch to using a GtkTextRenderer subclass of GdkPangoRenderer for drawing. * gtk/gtktextlayout.[ch] gtk/gtktextdisplay.c: Switch to using gtk_attr_shape_new_with_data() to store backreferences to embedded pixmaps and widgets. Leave line_display->shaped_objects around for backwords compatibility. * gdk/gdkpango.[ch] (gdk_pango_context_set_colormap): Describe as deprecated, remove implementation. * gtk/gtkwidget.c (gtk_widget_create_pango_context): Remove call to gdk_pango_context_set_colormap. * demos/gtk-demo/Makefile.am demos/gtk-demo/rotated_text.c: Add a demo showing drawing rotated text. * tests/testgtk.c: Add a rotated-label test, and also a rotated drawing test (differs from demos/gtk-demo/rotated_text by also using a tile)
typedef struct _GdkPangoRenderer GdkPangoRenderer; typedef struct _GdkPangoRendererClass GdkPangoRendererClass; struct _GdkPangoRenderer { PangoRenderer parent_instance; GdkPangoRendererPrivate *priv; }; struct _GdkPangoRendererClass { PangoRendererClass parent_class; }; PangoRenderer *gdk_pango_renderer_new (GdkScreen *screen); PangoRenderer *gdk_pango_renderer_get_default (GdkScreen *screen); void gdk_pango_renderer_set_drawable (GdkPangoRenderer *gdk_renderer, GdkDrawable *drawable); void gdk_pango_renderer_set_gc (GdkPangoRenderer *gdk_renderer, GdkGC *gc); void gdk_pango_renderer_set_stipple (GdkPangoRenderer *gdk_renderer, PangoRenderPart part, GdkBitmap *stipple); void gdk_pango_renderer_set_override_color (GdkPangoRenderer *gdk_renderer, PangoRenderPart part, const GdkColor *color); struct _GdkDrawableClass { GObjectClass parent_class; [...] void (*draw_glyphs_transformed) (GdkDrawable *drawable, GdkGC *gc, PangoMatrix *matrix, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs); void (*draw_trapezoids) (GdkDrawable *drawable, GdkGC *gc, GdkTrapezoid *trapezoids, gint n_trapezoids); [..] } void gdk_draw_glyphs_transformed (GdkDrawable *drawable, GdkGC *gc, PangoMatrix *matrix, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs); void gdk_draw_trapezoids (GdkDrawable *drawable, GdkGC *gc, GdkTrapezoid *trapezoids, gint n_trapezoids); void gtk_label_set_angle (GtkLabel *label, gdouble angle); gdouble gtk_label_get_angle (GtkLabel *label);
Attachment:
gdk-pango-renderer.diff.gz
Description: GNU Zip compressed data
Attachment:
signature.asc
Description: This is a digitally signed message part