diff options
Diffstat (limited to 'gdk/x11')
-rw-r--r-- | gdk/x11/gdkdrawable-x11.c | 136 | ||||
-rw-r--r-- | gdk/x11/gdkdrawable-x11.h | 10 | ||||
-rw-r--r-- | gdk/x11/gdkgc-x11.c | 102 | ||||
-rw-r--r-- | gdk/x11/gdkpixmap-x11.c | 9 | ||||
-rw-r--r-- | gdk/x11/gdkprivate-x11.h | 16 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 9 |
6 files changed, 205 insertions, 77 deletions
diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c index f5589dcb0a..0ca8d12201 100644 --- a/gdk/x11/gdkdrawable-x11.c +++ b/gdk/x11/gdkdrawable-x11.c @@ -203,6 +203,70 @@ gdk_drawable_impl_x11_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +#ifdef HAVE_XFT +static Picture +gdk_x11_drawable_get_picture (GdkDrawable *drawable) +{ + GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); + + if (impl->picture == None) + { + GdkVisual *visual = gdk_drawable_get_visual (drawable); + XRenderPictFormat *format; + + if (!visual) + { + g_warning ("Using Xft rendering requires the drawable argument to\n" + "have a specified colormap. All windows have a colormap,\n" + "however, pixmaps only have colormap by default if they\n" + "were created with a non-NULL window argument. Otherwise\n" + "a colormap must be set on them with gdk_drawable_set_colormap"); + return None; + } + + format = XRenderFindVisualFormat (impl->xdisplay, GDK_VISUAL_XVISUAL (visual)); + impl->picture = XRenderCreatePicture (impl->xdisplay, impl->xid, format, 0, NULL); + } + + return impl->picture; +} + +static void +gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable, + GdkGC *gc) +{ + GdkGCX11 *gc_private = GDK_GC_X11 (gc); + GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); + Picture picture = gdk_x11_drawable_get_picture (drawable); + + if (gc_private->clip_region) + { + GdkRegionBox *boxes = gc_private->clip_region->rects; + gint n_boxes = gc_private->clip_region->numRects; + XRectangle *rects = g_new (XRectangle, n_boxes); + int i; + + for (i=0; i < n_boxes; i++) + { + rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT); + rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT); + rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x; + rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y; + } + + XRenderSetPictureClipRectangles (impl->xdisplay, picture, 0, 0, rects, n_boxes); + + g_free (rects); + } + else + { + XRenderPictureAttributes pa; + pa.clip_mask = None; + XRenderChangePicture (impl->xdisplay, picture, CPClipMask, &pa); + } +} +#endif + /***************************************************** * X11 specific implementations of generic functions * *****************************************************/ @@ -581,40 +645,6 @@ gdk_x11_draw_lines (GdkDrawable *drawable, g_free (tmp_points); } -#if HAVE_XFT -static void -update_xft_draw_clip (GdkGC *gc) -{ - GdkGCX11 *private = GDK_GC_X11 (gc); - int i; - - if (private->xft_draw) - { - if (private->clip_region) - { - GdkRegionBox *boxes = private->clip_region->rects; - Region region = XCreateRegion (); - - for (i=0; i<private->clip_region->numRects; i++) - { - XRectangle rect; - - rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT); - rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT); - rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x; - rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y; - XUnionRectWithRegion (&rect, region, region); - } - - XftDrawSetClip (private->xft_draw, region); - XDestroyRegion (region); - } - else - XftDrawSetClip (private->xft_draw, NULL); - } -} -#endif - static void gdk_x11_draw_glyphs (GdkDrawable *drawable, GdkGC *gc, @@ -630,39 +660,15 @@ gdk_x11_draw_glyphs (GdkDrawable *drawable, #if HAVE_XFT if (PANGO_XFT_IS_FONT (font)) { - GdkGCX11 *gc_x11 = GDK_GC_X11 (gc); - XftColor xft_color; - GdkColormap *cmap; - GdkColor color; - - cmap = gdk_gc_get_colormap (gc); + Picture src_picture; + Picture dest_picture; - _gdk_x11_gc_flush (gc); - - if (!gc_x11->xft_draw) - { - gc_x11->xft_draw = XftDrawCreate (impl->xdisplay, - impl->xid, - GDK_VISUAL_XVISUAL (gdk_colormap_get_visual (cmap)), - GDK_COLORMAP_XCOLORMAP (cmap)); - update_xft_draw_clip (gc); - } - - else - { - XftDrawChange (gc_x11->xft_draw, impl->xid); - update_xft_draw_clip (gc); - } - - gdk_colormap_query_color (cmap, gc_x11->fg_pixel, &color); - - xft_color.color.red = color.red; - xft_color.color.green = color.green; - xft_color.color.blue = color.blue; - xft_color.color.alpha = 0xffff; + src_picture = _gdk_x11_gc_get_fg_picture (gc); + + gdk_x11_drawable_update_picture_clip (drawable, gc); + dest_picture = gdk_x11_drawable_get_picture (drawable); - pango_xft_render (gc_x11->xft_draw, &xft_color, - font, glyphs, x, y); + pango_xft_picture_render (impl->xdisplay, src_picture, dest_picture, font, glyphs, x, y); } else #endif /* !HAVE_XFT */ diff --git a/gdk/x11/gdkdrawable-x11.h b/gdk/x11/gdkdrawable-x11.h index 7d20d50d52..aa681585d4 100644 --- a/gdk/x11/gdkdrawable-x11.h +++ b/gdk/x11/gdkdrawable-x11.h @@ -27,9 +27,15 @@ #ifndef __GDK_DRAWABLE_X11_H__ #define __GDK_DRAWABLE_X11_H__ +#include <config.h> + #include <gdk/gdkdrawable.h> #include <gdk/x11/gdkx.h> +#ifdef HAVE_XFT +#include <X11/extensions/Xrender.h> +#endif + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -57,6 +63,10 @@ struct _GdkDrawableImplX11 Window xid; Display *xdisplay; + +#ifdef HAVE_XFT + Picture picture; +#endif }; struct _GdkDrawableImplX11Class diff --git a/gdk/x11/gdkgc-x11.c b/gdk/x11/gdkgc-x11.c index ce3c60490e..f6c4da625c 100644 --- a/gdk/x11/gdkgc-x11.c +++ b/gdk/x11/gdkgc-x11.c @@ -26,10 +26,6 @@ #include <config.h> -#if HAVE_XFT -#include <pango/pangoxft.h> -#endif - #include "gdkgc.h" #include "gdkprivate-x11.h" #include "gdkregion-generic.h" @@ -112,13 +108,13 @@ gdk_gc_x11_finalize (GObject *object) if (x11_gc->clip_region) gdk_region_destroy (x11_gc->clip_region); - XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc)); - #if HAVE_XFT - if (x11_gc->xft_draw) - XftDrawDestroy (x11_gc->xft_draw); + if (x11_gc->fg_picture != None) + XRenderFreePicture (x11_gc->xdisplay, x11_gc->fg_picture); #endif + XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc)); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -757,3 +753,93 @@ gdk_x11_gc_get_xgc (GdkGC *gc) return gc_x11->xgc; } + +/* Various bits of the below are roughly cribbed from XFree86 + * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard + */ + +static XRenderPictFormat * +foreground_format (GdkGC *gc) +{ + XRenderPictFormat pf; + + pf.type = PictTypeDirect; + pf.depth = 32; + pf.direct.redMask = 0xff; + pf.direct.greenMask = 0xff; + pf.direct.blueMask = 0xff; + pf.direct.alphaMask = 0xff; + + return XRenderFindFormat (GDK_GC_XDISPLAY (gc), + (PictFormatType | + PictFormatDepth | + PictFormatRedMask | + PictFormatGreenMask | + PictFormatBlueMask | + PictFormatAlphaMask), + &pf, + 0); +} + +#ifdef HAVE_XFT +/** + * _gdk_x11_gc_get_fg_picture: + * @gc: a #GdkGC + * + * Gets a Xrender Picture object suitable for being the source + * drawable for drawing with the foreground the graphics context. + * (Currently, only foreground color is handled, but in the + * future we should handle tiles/stipples as well.) + * + * Return value: a Picture, owned by the GC; this cannot be + * used over subsequent modification of the GC. + **/ +Picture +_gdk_x11_gc_get_fg_picture (GdkGC *gc) +{ + GdkGCX11 *x11_gc; + GdkColormap *cmap = gdk_gc_get_colormap (gc); + gboolean new = FALSE; + GdkColor color; + + g_return_val_if_fail (GDK_IS_GC_X11 (gc), None); + + x11_gc = GDK_GC_X11 (gc); + + if (x11_gc->fg_picture == None) + { + XRenderPictureAttributes pa; + XRenderPictFormat *pix_format = foreground_format (gc); + + Pixmap pix = XCreatePixmap (x11_gc->xdisplay, _gdk_root_window, + 1, 1, pix_format->depth); + pa.repeat = True; + x11_gc->fg_picture = XRenderCreatePicture (x11_gc->xdisplay, + pix, + pix_format, + CPRepeat, &pa); + XFreePixmap (x11_gc->xdisplay, pix); + + new = TRUE; + } + + gdk_colormap_query_color (cmap, x11_gc->fg_pixel, &color); + + if (new || + x11_gc->fg_picture_color.red != color.red || + x11_gc->fg_picture_color.green != color.green || + x11_gc->fg_picture_color.blue != color.blue) + { + x11_gc->fg_picture_color.red = color.red; + x11_gc->fg_picture_color.green = color.green; + x11_gc->fg_picture_color.blue = color.blue; + x11_gc->fg_picture_color.alpha = 0xffff; + + XRenderFillRectangle (x11_gc->xdisplay, PictOpSrc, + x11_gc->fg_picture, &x11_gc->fg_picture_color, + 0, 0, 1, 1); + } + + return x11_gc->fg_picture; +} +#endif /* HAVE_XFT */ diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c index 15804ce8a4..ae50cc3375 100644 --- a/gdk/x11/gdkpixmap-x11.c +++ b/gdk/x11/gdkpixmap-x11.c @@ -122,6 +122,15 @@ gdk_pixmap_impl_x11_finalize (GObject *object) GdkPixmapImplX11 *impl = GDK_PIXMAP_IMPL_X11 (object); GdkPixmap *wrapper = GDK_PIXMAP (GDK_DRAWABLE_IMPL_X11 (impl)->wrapper); +#ifdef HAVE_XFT + { + GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl); + + if (draw_impl->picture) + XRenderFreePicture (draw_impl->xdisplay, draw_impl->picture); + } +#endif /* HAVE_XFT */ + if (!impl->is_foreign) XFreePixmap (GDK_PIXMAP_XDISPLAY (wrapper), GDK_PIXMAP_XID (wrapper)); diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 8b960974fb..6552ff5383 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -39,6 +39,10 @@ #include <config.h> +#if HAVE_XFT +#include <X11/extensions/Xrender.h> +#endif + #define GDK_TYPE_GC_X11 (_gdk_gc_x11_get_type ()) #define GDK_GC_X11(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_X11, GdkGCX11)) #define GDK_GC_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GC_X11, GdkGCX11Class)) @@ -60,10 +64,10 @@ struct _GdkGCX11 GdkRegion *clip_region; guint dirty_mask; - /* We can't conditionalize on HAVE_XFT here, so we simply always - * have this here as a gpointer. - */ - gpointer xft_draw; +#ifdef HAVE_XFT + Picture fg_picture; + XRenderColor fg_picture_color; +#endif gulong fg_pixel; }; @@ -95,6 +99,10 @@ gint gdk_send_xevent (Window window, GType _gdk_gc_x11_get_type (void); +#ifdef HAVE_XFT +Picture _gdk_x11_gc_get_fg_picture (GdkGC *gc); +#endif /* HAVE_XFT */ + GdkGC *_gdk_x11_gc_new (GdkDrawable *drawable, GdkGCValues *values, GdkGCValuesMask values_mask); diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index f6d6d89d90..49a6636943 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -738,6 +738,15 @@ _gdk_windowing_window_destroy (GdkWindow *window, if (private->extension_events != 0) gdk_input_window_destroy (window); +#ifdef HAVE_XFT + { + GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); + + if (draw_impl->picture) + XRenderFreePicture (draw_impl->xdisplay, draw_impl->picture); + } +#endif /* HAVE_XFT */ + if (private->window_type == GDK_WINDOW_FOREIGN) { if (!foreign_destroy && (private->parent != NULL)) |