summaryrefslogtreecommitdiff
path: root/gdk/x11
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/x11')
-rw-r--r--gdk/x11/gdkdrawable-x11.c136
-rw-r--r--gdk/x11/gdkdrawable-x11.h10
-rw-r--r--gdk/x11/gdkgc-x11.c102
-rw-r--r--gdk/x11/gdkpixmap-x11.c9
-rw-r--r--gdk/x11/gdkprivate-x11.h16
-rw-r--r--gdk/x11/gdkwindow-x11.c9
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))