http://mail.gnome.org/archives/performance-list/2006-October/msg00063.html From: Xan Lópe To: ext Matt Hoosier Cc: performance-list gnome org Subject: Re: [patch] Remove pangocairo from Gtk+ 2.8.20 Date: Mon, 30 Oct 2006 14:31:56 +0200 Hi, I've upgraded your patch against GTK+ 2.10.6, and we are getting great performance figures compared to GTK+ 2.10.6 with pangocairo too (basically at the level of GTK+ 2.6.10 again). Right now I'm working on a python/cairo script to get some nice graphics from a torture test session with several GTK+s, hope to get it ready soon. Index: gtk+-2.10.6/configure.in =================================================================== --- gtk+-2.10.6.orig/configure.in 2006-10-30 12:59:28.000000000 +0000 +++ gtk+-2.10.6/configure.in 2006-10-30 12:59:30.000000000 +0000 @@ -1435,7 +1435,7 @@ if test "x$gdktarget" = "xwin32"; then PANGO_PACKAGES="pangowin32 pangocairo" else - PANGO_PACKAGES="pango pangocairo" + PANGO_PACKAGES="pango pangocairo pangoxft" fi AC_MSG_CHECKING(Pango flags) Index: gtk+-2.10.6/gdk/gdkaliasdef.c =================================================================== --- gtk+-2.10.6.orig/gdk/gdkaliasdef.c 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/gdkaliasdef.c 2006-10-30 12:59:30.000000000 +0000 @@ -1799,9 +1799,6 @@ #undef gdk_pango_context_get extern __typeof (gdk_pango_context_get) gdk_pango_context_get __attribute((alias("IA__gdk_pango_context_get"), visibility("default"))); -#undef gdk_pango_context_get_for_screen -extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default"))); - #ifndef GDK_DISABLE_DEPRECATED #undef gdk_pango_context_set_colormap extern __typeof (gdk_pango_context_set_colormap) gdk_pango_context_set_colormap __attribute((alias("IA__gdk_pango_context_set_colormap"), visibility("default"))); @@ -1836,6 +1833,13 @@ #endif #endif +#if IN_HEADER(__GDK_PANGO_H__) +#if IN_FILE(__GDK_PANGO_X11_C__) +#undef gdk_pango_context_get_for_screen +extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default"))); + +#endif +#endif #if IN_HEADER(__GDK_PIXBUF_H__) #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) #undef gdk_pixbuf_get_from_drawable Index: gtk+-2.10.6/gdk/gdkalias.h =================================================================== --- gtk+-2.10.6.orig/gdk/gdkalias.h 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/gdkalias.h 2006-10-30 12:59:30.000000000 +0000 @@ -1796,9 +1796,6 @@ extern __typeof (gdk_pango_context_get) IA__gdk_pango_context_get __attribute((visibility("hidden"))); #define gdk_pango_context_get IA__gdk_pango_context_get -extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden"))); -#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen - #ifndef GDK_DISABLE_DEPRECATED extern __typeof (gdk_pango_context_set_colormap) IA__gdk_pango_context_set_colormap __attribute((visibility("hidden"))); #define gdk_pango_context_set_colormap IA__gdk_pango_context_set_colormap @@ -1833,6 +1830,13 @@ #endif #endif +#if IN_HEADER(__GDK_PANGO_H__) +#if IN_FILE(__GDK_PANGO_X11_C__) +extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden"))); +#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen + +#endif +#endif #if IN_HEADER(__GDK_PIXBUF_H__) #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) extern __typeof (gdk_pixbuf_get_from_drawable) IA__gdk_pixbuf_get_from_drawable __attribute((visibility("hidden"))); Index: gtk+-2.10.6/gdk/gdkdraw.c =================================================================== --- gtk+-2.10.6.orig/gdk/gdkdraw.c 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/gdkdraw.c 2006-10-30 12:59:30.000000000 +0000 @@ -909,9 +909,9 @@ { g_return_if_fail (GDK_IS_DRAWABLE (drawable)); g_return_if_fail (GDK_IS_GC (gc)); - - real_draw_glyphs (drawable, gc, NULL, font, - x, y, glyphs); + + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs); } /** @@ -949,8 +949,9 @@ g_return_if_fail (GDK_IS_DRAWABLE (drawable)); g_return_if_fail (GDK_IS_GC (gc)); - real_draw_glyphs (drawable, gc, matrix, font, - x / PANGO_SCALE, y / PANGO_SCALE, glyphs); + if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed) + GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed (drawable, gc, matrix, + font, x, y, glyphs); } /** @@ -974,28 +975,12 @@ GdkTrapezoid *trapezoids, gint n_trapezoids) { - cairo_t *cr; - int i; - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); g_return_if_fail (GDK_IS_GC (gc)); g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL); - cr = gdk_cairo_create (drawable); - _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE); - - for (i = 0; i < n_trapezoids; i++) - { - cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1); - cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1); - cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2); - cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y2); - cairo_close_path (cr); - } - - cairo_fill (cr); - - cairo_destroy (cr); + GDK_DRAWABLE_GET_CLASS (drawable)->draw_trapezoids (drawable, gc, + trapezoids, n_trapezoids); } /** Index: gtk+-2.10.6/gdk/gdkpango.c =================================================================== --- gtk+-2.10.6.orig/gdk/gdkpango.c 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/gdkpango.c 2006-10-30 12:59:30.000000000 +0000 @@ -50,19 +50,34 @@ GdkBitmap *stipple[MAX_RENDER_PART + 1]; gboolean embossed; - cairo_t *cr; - PangoRenderPart last_part; + /* When switching between the normal and shadow copies when + * drawing shadows we can get unexpected recursion into the + * drawing functions; the 'in_emboss' flag guards against that. + */ + gboolean in_emboss; /* Current target */ GdkDrawable *drawable; GdkGC *base_gc; gboolean gc_changed; + + /* Cached GC, derived from base_gc */ + GdkGC *gc; + PangoColor gc_color; + gboolean gc_color_set; + GdkBitmap *gc_stipple; + + /* we accumulate trapezoids for the same PangoRenderPart */ + GArray *trapezoids; + PangoRenderPart trapezoid_part; }; static PangoAttrType gdk_pango_attr_stipple_type; static PangoAttrType gdk_pango_attr_embossed_type; +static void flush_trapezoids (GdkPangoRenderer *gdk_renderer); + enum { PROP_0, PROP_SCREEN @@ -77,6 +92,10 @@ GdkPangoRendererPrivate *priv = gdk_renderer->priv; int i; + if (priv->gc) + g_object_unref (priv->gc); + if (priv->gc_stipple) + g_object_unref (priv->gc_stipple); if (priv->base_gc) g_object_unref (priv->base_gc); if (priv->drawable) @@ -86,6 +105,8 @@ if (priv->stipple[i]) g_object_unref (priv->stipple[i]); + g_array_free (priv->trapezoids, TRUE); + G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object); } @@ -112,25 +133,6 @@ return object; } -/* Adjusts matrix and color for the renderer to draw the secondary - * "shadow" copy for embossed text */ -static void -emboss_context (cairo_t *cr) -{ - cairo_matrix_t tmp_matrix; - - /* The gymnastics here to adjust the matrix are because we want - * to offset by +1,+1 in device-space, not in user-space, - * so we can't just draw the layout at x + 1, y + 1 - */ - cairo_get_matrix (cr, &tmp_matrix); - tmp_matrix.x0 += 1.0; - tmp_matrix.y0 += 1.0; - cairo_set_matrix (cr, &tmp_matrix); - - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); -} - static inline gboolean color_equal (PangoColor *c1, PangoColor *c2) { @@ -146,74 +148,154 @@ return FALSE; } -static cairo_t * -get_cairo_context (GdkPangoRenderer *gdk_renderer, - PangoRenderPart part) +/* Adjusts matrix and color for the renderer to draw the secondar + * "shadow" copy for embossed text */ +static void +emboss_renderer (PangoRenderer *renderer, + PangoRenderPart part, + PangoMatrix **save_matrix, + PangoColor **save_color) +{ + GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; + static const PangoColor white = { 0xffff, 0xffff, 0xffff }; + PangoMatrix tmp_matrix = PANGO_MATRIX_INIT; + + priv->in_emboss = TRUE; + + *save_color = pango_renderer_get_color (renderer, part); + if (*save_color) + *save_color = pango_color_copy (*save_color); + + *save_matrix = renderer->matrix; + if (*save_matrix) + { + *save_matrix = pango_matrix_copy (*save_matrix); + tmp_matrix = **save_matrix; + } + + /* The gymnastics here to adjust the matrix are because we want + * to offset by +1,+1 in device-space, not in user-space, + * so we can't just draw the layout at x + 1, y + 1 + */ + tmp_matrix.x0 += 1; + tmp_matrix.y0 += 1; + + pango_renderer_set_matrix (renderer, &tmp_matrix); + pango_renderer_set_color (renderer, part, &white); +} + +/* Restores from emboss_renderer() */ +static void +unemboss_renderer (PangoRenderer *renderer, + PangoRenderPart part, + PangoMatrix **save_matrix, + PangoColor **save_color) +{ + GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; + pango_renderer_set_matrix (renderer, *save_matrix); + pango_renderer_set_color (renderer, part, *save_color); + + if (*save_matrix) + pango_matrix_free (*save_matrix); + if (*save_color) + pango_color_free (*save_color); + + priv->in_emboss = FALSE; +} + +/* Gets the GC for drawing @part. This make involve copying the base GC + * for the renderer, in which case we keep a one-GC cache. */ +static GdkGC * +get_gc (GdkPangoRenderer *gdk_renderer, + PangoRenderPart part) { PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer); + PangoColor *color; + GdkBitmap *stipple; GdkPangoRendererPrivate *priv = gdk_renderer->priv; - if (!priv->cr) + color = pango_renderer_get_color (renderer, part); + + if (part <= MAX_RENDER_PART) + stipple = priv->stipple[part]; + else + stipple = NULL; + + if (!color && !stipple) /* nothing override, use base_gc */ + return priv->base_gc; + else { - const PangoMatrix *matrix; + gboolean new_stipple = FALSE; + gboolean new_color = FALSE; - priv->cr = gdk_cairo_create (priv->drawable); + if (stipple != priv->gc_stipple) + new_stipple = TRUE; - matrix = pango_renderer_get_matrix (renderer); - if (matrix) + if ((priv->gc_color_set && !color) || + (!priv->gc_color_set && color) || + priv->gc_color.red != color->red || + priv->gc_color.green != color->green || + priv->gc_color.blue != color->blue) + new_color = TRUE; + + if (!priv->gc) { - cairo_matrix_t cairo_matrix; - - cairo_matrix_init (&cairo_matrix, - matrix->xx, matrix->yx, - matrix->xy, matrix->yy, - matrix->x0, matrix->y0); - cairo_set_matrix (priv->cr, &cairo_matrix); + priv->gc = gdk_gc_new (priv->drawable); + gdk_gc_copy (priv->gc, priv->base_gc); + } + else if (new_color && priv->gc_color_set && !color) + { + /* We have to recopy the original GC onto the cached GC + * to get the default color */ + new_stipple = TRUE; + gdk_gc_copy (priv->gc, priv->base_gc); + } + else if (new_stipple && priv->gc_stipple && !stipple) + { + /* Similarly, we need to make a new copy to restore to the + * default stipple state (the caller may have set a stipple + * on the GC, and even if not, gdk_gc_set_stipple (gc, NULL) + * doesn't work currently to restore to the default X stipple) */ + new_color = TRUE; + gdk_gc_copy (priv->gc, priv->base_gc); } - } - - if (part != priv->last_part) - { - PangoColor *pango_color; - GdkColor *color; - GdkColor tmp_color; - gboolean changed; - pango_color = pango_renderer_get_color (renderer, part); - - if (priv->last_part != -1) - changed = priv->gc_changed || - priv->stipple[priv->last_part] != priv->stipple[part] || - !color_equal (pango_color, - pango_renderer_get_color (renderer, priv->last_part)); - else - changed = TRUE; - - if (changed) + if (new_color) { - if (pango_color) + if (color) { - tmp_color.red = pango_color->red; - tmp_color.green = pango_color->green; - tmp_color.blue = pango_color->blue; + GdkColor gdk_color; + + gdk_color.red = color->red; + gdk_color.green = color->green; + gdk_color.blue = color->blue; - color = &tmp_color; + gdk_gc_set_rgb_fg_color (priv->gc, &gdk_color); + + priv->gc_color = *color; + priv->gc_color_set = TRUE; } else - color = NULL; + priv->gc_color_set = FALSE; + } - _gdk_gc_update_context (priv->base_gc, - priv->cr, - color, - priv->stipple[part], - priv->gc_changed); + if (new_stipple) + { + if (priv->gc_stipple) + g_object_unref (priv->gc_stipple); + + if (stipple) + { + gdk_gc_set_stipple (priv->gc, stipple); + gdk_gc_set_fill (priv->gc, GDK_STIPPLED); + priv->gc_stipple = g_object_ref (stipple); + } + else + priv->gc_stipple = NULL; } - priv->last_part = part; - priv->gc_changed = FALSE; + return priv->gc; } - - return priv->cr; } static void @@ -225,133 +307,78 @@ { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); GdkPangoRendererPrivate *priv = gdk_renderer->priv; - cairo_t *cr; - cr = get_cairo_context (gdk_renderer, - PANGO_RENDER_PART_FOREGROUND); + flush_trapezoids (gdk_renderer); - if (priv->embossed) + if (!priv->in_emboss && priv->embossed) { - cairo_save (cr); - emboss_context (cr); - cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); - pango_cairo_show_glyph_string (cr, font, glyphs); - cairo_restore (cr); - } - - cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE); - pango_cairo_show_glyph_string (cr, font, glyphs); -} - -/* Draws an error underline that looks like one of: - * H E H - * /\ /\ /\ /\ /\ - - * A/ \ / \ / \ A/ \ / \ | - * \ \ / \ / /D \ \ / \ | - * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square - * \ /\ F / \ F /\ \ | - * \ / \ / \ / \ \G | - * \ / \ / \ / \ / | - * \/ \/ \/ \/ - - * B B - * |----| - * unit_width = (HEIGHT_SQUARES - 1) * square - * - * The x, y, width, height passed in give the desired bounding box; - * x/width are adjusted to make the underline a integer number of units - * wide. - */ -#define HEIGHT_SQUARES 2.5 + PangoMatrix *save_matrix; + PangoColor *save_color; -/* Cut-and-pasted between here and pango/pango/pangocairo-render.c */ + emboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); + gdk_draw_glyphs_transformed (priv->drawable, + get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), + renderer->matrix, font, x, y, glyphs); + unemboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); + } + + gdk_draw_glyphs_transformed (priv->drawable, + get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), + renderer->matrix, font, x, y, glyphs); +} + +/* Outputs any pending trapezoids, we do this when the part or + * part color changes, when we are about to draw text, etc. */ static void -draw_error_underline (cairo_t *cr, - double x, - double y, - double width, - double height) -{ - double square = height / HEIGHT_SQUARES; - double unit_width = (HEIGHT_SQUARES - 1) * square; - int width_units = (width + unit_width / 2) / unit_width; - double y_top, y_bottom; - int i; +flush_trapezoids (GdkPangoRenderer *gdk_renderer) +{ + GdkPangoRendererPrivate *priv = gdk_renderer->priv; - x += (width - width_units * unit_width) / 2; - width = width_units * unit_width; + if (!priv->trapezoids || priv->trapezoids->len == 0) + return; - y_top = y; - y_bottom = y + height; - - /* Bottom of squiggle */ - cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */ - for (i = 0; i < width_units; i += 2) - { - double x_middle = x + (i + 1) * unit_width; - double x_right = x + (i + 2) * unit_width; - - cairo_line_to (cr, x_middle, y_bottom); /* B */ - - if (i + 1 == width_units) - /* Nothing */; - else if (i + 2 == width_units) - cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */ - else - cairo_line_to (cr, x_right, y_top + square); /* C */ - } - - /* Top of squiggle */ - for (i -= 2; i >= 0; i -= 2) - { - double x_left = x + i * unit_width; - double x_middle = x + (i + 1) * unit_width; - double x_right = x + (i + 2) * unit_width; - - if (i + 1 == width_units) - cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */ - else { - if (i + 2 == width_units) - cairo_line_to (cr, x_right, y_top); /* E */ - cairo_line_to (cr, x_middle, y_bottom - square); /* F */ - } - - cairo_line_to (cr, x_left, y_top); /* H */ - } + gdk_draw_trapezoids (priv->drawable, + get_gc (gdk_renderer, priv->trapezoid_part), + (GdkTrapezoid *)priv->trapezoids->data, + priv->trapezoids->len); - cairo_close_path (cr); - cairo_fill (cr); + g_array_set_size (priv->trapezoids, 0); } +/* Draws a single trapezoid ... we don't draw it immediately, but rather + * cache it to join together with other trapezoids that form part of the + * same logical shape */ static void -gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, - PangoRenderPart part, - int x, - int y, - int width, - int height) +gdk_pango_renderer_draw_trapezoid (PangoRenderer *renderer, + PangoRenderPart part, + double y1, + double x11, + double x21, + double y2, + double x12, + double x22) { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - cairo_t *cr; - - cr = get_cairo_context (gdk_renderer, part); - - if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) - { - cairo_save (cr); - emboss_context (cr); - cairo_rectangle (cr, - (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, - (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + GdkTrapezoid trap; - cairo_fill (cr); - cairo_restore (cr); - } + if (!gdk_renderer->priv->trapezoids) + gdk_renderer->priv->trapezoids = g_array_new (FALSE, FALSE, + sizeof (GdkTrapezoid)); + + if (gdk_renderer->priv->trapezoids->len > 0 && + gdk_renderer->priv->trapezoid_part != part) + flush_trapezoids (gdk_renderer); + + gdk_renderer->priv->trapezoid_part = part; + + trap.y1 = y1; + trap.x11 = x11 / 2; + trap.x21 = x21; + trap.y2 = y2; + trap.x12 = x12; + trap.x22 = x22; - cairo_rectangle (cr, - (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, - (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); - cairo_fill (cr); + g_array_append_val (gdk_renderer->priv->trapezoids, trap); } static void @@ -363,23 +390,51 @@ { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); GdkPangoRendererPrivate *priv = gdk_renderer->priv; - cairo_t *cr; - - cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE); - - if (priv->embossed) + + if (!priv->in_emboss && priv->embossed) { - cairo_save (cr); - emboss_context (cr); - draw_error_underline (cr, - (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, - (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); - cairo_restore (cr); + PangoMatrix *save_matrix; + PangoColor *save_color; + + emboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); + PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, + x, y, width, height); + unemboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); } - draw_error_underline (cr, - (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, - (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, + x, y, width, height); +} + +/* We can't handle embossing at the level of trapezoids, because when an + * underline is split into multiple trapezoids, the normal and shadow + * trapezoids will be drawn mixed together. Instead, we have to emboss + * and entire rectangle or error underline + */ +static void +gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, + PangoRenderPart part, + int x, + int y, + int width, + int height) +{ + GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); + GdkPangoRendererPrivate *priv = gdk_renderer->priv; + + if (!priv->in_emboss && priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) + { + PangoMatrix *save_matrix; + PangoColor *save_color; + + emboss_renderer (renderer, part, &save_matrix, &save_color); + PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, + x, y, width, height); + unemboss_renderer (renderer, part, &save_matrix, &save_color); + } + + PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, + x, y, width, height); } static void @@ -388,8 +443,8 @@ { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - if (gdk_renderer->priv->last_part == part) - gdk_renderer->priv->last_part = (PangoRenderPart)-1; + if (part == gdk_renderer->priv->trapezoid_part) + flush_trapezoids (gdk_renderer); } static void @@ -410,13 +465,8 @@ { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - if (priv->cr) - { - cairo_destroy (priv->cr); - priv->cr = NULL; - } - priv->last_part = (PangoRenderPart)-1; + + flush_trapezoids (gdk_renderer); } static void @@ -515,7 +565,6 @@ GDK_TYPE_PANGO_RENDERER, GdkPangoRendererPrivate); - renderer->priv->last_part = (PangoRenderPart)-1; renderer->priv->gc_changed = TRUE; } @@ -527,6 +576,7 @@ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs; + renderer_class->draw_trapezoid = gdk_pango_renderer_draw_trapezoid; renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle; renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline; renderer_class->part_changed = gdk_pango_renderer_part_changed; @@ -647,6 +697,8 @@ priv = gdk_renderer->priv; + flush_trapezoids (gdk_renderer); + if (priv->drawable != drawable) { if (priv->drawable) @@ -681,6 +733,8 @@ priv = gdk_renderer->priv; + flush_trapezoids (gdk_renderer); + if (priv->base_gc != gc) { if (priv->base_gc) @@ -689,6 +743,20 @@ if (priv->base_gc) g_object_ref (priv->base_gc); + if (priv->gc) + { + g_object_unref (priv->gc); + priv->gc = NULL; + } + + priv->gc_color_set = FALSE; + + if (priv->gc_stipple) + { + g_object_unref (priv->gc_stipple); + priv->gc_stipple = NULL; + } + priv->gc_changed = TRUE; } } @@ -1414,50 +1482,5 @@ return gdk_pango_context_get_for_screen (gdk_screen_get_default ()); } -/** - * gdk_pango_context_get_for_screen: - * @screen: the #GdkScreen for which the context is to be created. - * - * Creates a #PangoContext for @screen. - * - * The context must be freed when you're finished with it. - * - * When using GTK+, normally you should use gtk_widget_get_pango_context() - * instead of this function, to get the appropriate context for - * the widget you intend to render text onto. - * - * The newly created context will have the default font options - * (see #cairo_font_options_t) for the screen; if these options - * change it will not be updated. Using gtk_widget_get_pango_context() - * is more convenient if you want to keep a context around and track - * changes to the screen's font rendering settings. - * - * Return value: a new #PangoContext for @screen - * - * Since: 2.2 - **/ -PangoContext * -gdk_pango_context_get_for_screen (GdkScreen *screen) -{ - PangoFontMap *fontmap; - PangoContext *context; - const cairo_font_options_t *options; - double dpi; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); - - fontmap = pango_cairo_font_map_get_default (); - - context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); - - options = gdk_screen_get_font_options (screen); - pango_cairo_context_set_font_options (context, options); - - dpi = gdk_screen_get_resolution (screen); - pango_cairo_context_set_resolution (context, dpi); - - return context; -} - #define __GDK_PANGO_C__ #include "gdkaliasdef.c" Index: gtk+-2.10.6/gdk/gdk.symbols =================================================================== --- gtk+-2.10.6.orig/gdk/gdk.symbols 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/gdk.symbols 2006-10-30 12:59:30.000000000 +0000 @@ -861,7 +861,6 @@ gdk_pango_attr_embossed_new gdk_pango_attr_stipple_new gdk_pango_context_get -gdk_pango_context_get_for_screen #ifndef GDK_DISABLE_DEPRECATED gdk_pango_context_set_colormap #endif @@ -877,6 +876,12 @@ #endif #endif +#if IN_HEADER(__GDK_PANGO_H__) +#if IN_FILE(__GDK_PANGO_X11_C__) +gdk_pango_context_get_for_screen +#endif +#endif + #if IN_HEADER(__GDK_PIXBUF_H__) #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) gdk_pixbuf_get_from_drawable Index: gtk+-2.10.6/gdk/gdkwindow.c =================================================================== --- gtk+-2.10.6.orig/gdk/gdkwindow.c 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/gdkwindow.c 2006-10-30 12:59:30.000000000 +0000 @@ -1834,9 +1834,14 @@ } else { - method->cr = cairo_create (paint->surface); + /*method->cr = cairo_create (paint->surface); - gdk_cairo_set_source_color (method->cr, &private->bg_color); + gdk_cairo_set_source_color (method->cr, &private->bg_color);*/ + GdkGC *gc = _gdk_drawable_get_scratch_gc (paint->pixmap, FALSE); + + gdk_gc_set_foreground (gc, &(private->bg_color)); + + method->gc = g_object_ref (gc); } } Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.c 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c 2006-10-30 12:59:30.000000000 +0000 @@ -190,7 +190,8 @@ display_x11->leader_window_title_set = FALSE; display_x11->have_render = GDK_UNKNOWN; - + display_x11->have_render_with_trapezoids = GDK_UNKNOWN; + #ifdef HAVE_XFIXES if (XFixesQueryExtension (display_x11->xdisplay, &display_x11->xfixes_event_base, Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.h 2006-10-30 12:58:29.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h 2006-10-30 12:59:30.000000000 +0000 @@ -78,6 +78,7 @@ gboolean use_xshm; gboolean have_shm_pixmaps; GdkTristate have_render; + GdkTristate have_render_with_trapezoids; gboolean have_xfixes; gint xfixes_event_base; Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c 2006-10-30 12:59:30.000000000 +0000 @@ -26,6 +26,8 @@ #include +#include + #include "gdkx.h" #include "gdkregion-generic.h" @@ -106,7 +108,21 @@ GdkGC *gc, GdkPoint *points, gint npoints); - + +static void gdk_x11_draw_glyphs (GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs); +static void gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable, + GdkGC *gc, + PangoMatrix *matrix, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs); + static void gdk_x11_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, @@ -129,6 +145,11 @@ gint x_dither, gint y_dither); +static void gdk_x11_draw_trapezoids (GdkDrawable *drawable, + GdkGC *gc, + GdkTrapezoid *trapezoids, + gint n_trapezoids); + static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable); static void gdk_x11_set_colormap (GdkDrawable *drawable, @@ -163,8 +184,11 @@ drawable_class->draw_points = gdk_x11_draw_points; drawable_class->draw_segments = gdk_x11_draw_segments; drawable_class->draw_lines = gdk_x11_draw_lines; + drawable_class->draw_glyphs = gdk_x11_draw_glyphs; + drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed; drawable_class->draw_image = gdk_x11_draw_image; drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf; + drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids; drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface; @@ -327,6 +351,72 @@ return x11display->have_render == GDK_YES; } +gboolean +_gdk_x11_have_render_with_trapezoids (GdkDisplay *display) +{ + Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); + GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); + + if (x11display->have_render_with_trapezoids == GDK_UNKNOWN) + { + x11display->have_render_with_trapezoids = GDK_NO; + if (_gdk_x11_have_render (display)) + { + /* + * Require protocol >= 0.4 for CompositeTrapezoids support. + */ + int major_version, minor_version; + +#define XRENDER_TETRAPEZOIDS_MAJOR 0 +#define XRENDER_TETRAPEZOIDS_MINOR 4 + + if (XRenderQueryVersion (xdisplay, &major_version, + &minor_version)) + if ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) && + (minor_version >= XRENDER_TETRAPEZOIDS_MINOR)) + x11display->have_render_with_trapezoids = GDK_YES; + } + } + + return x11display->have_render_with_trapezoids == GDK_YES; +} + +static XftDraw * +gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable) +{ + GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); + + if (impl->xft_draw == NULL) + { + GdkColormap *colormap = gdk_drawable_get_colormap (drawable); + + if (colormap) + { + GdkVisual *visual; + + visual = gdk_colormap_get_visual (colormap); + + impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid, + GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap)); + } + else if (gdk_drawable_get_depth (drawable) == 1) + { + impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid); + } + else + { + 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 NULL; + } + } + + return impl->xft_draw; +} + static Picture gdk_x11_drawable_get_picture (GdkDrawable *drawable) { @@ -393,6 +483,57 @@ } } +static void +gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable, + GdkGC *gc) +{ + XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable); + GdkRegion *clip_region = _gdk_gc_get_clip_region (gc); + + if (gc && clip_region) + { + GdkRegionBox *boxes = clip_region->rects; + gint n_boxes = clip_region->numRects; +#if 0 /* Until XftDrawSetClipRectangles is there */ + 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; + } + XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes); + + g_free (rects); +#else + Region xregion = XCreateRegion (); + int i; + + for (i=0; i < n_boxes; 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, xregion, xregion); + } + + XftDrawSetClip (xft_draw, xregion); + XDestroyRegion (xregion); +#endif + } + else + { + XftDrawSetClip (xft_draw, NULL); + } +} + /***************************************************** * X11 specific implementations of generic functions * *****************************************************/ @@ -780,6 +921,45 @@ } static void +gdk_x11_draw_glyphs (GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs) +{ + gdk_x11_draw_glyphs_transformed (drawable, gc, NULL, + font, + x * PANGO_SCALE, + y * PANGO_SCALE, + glyphs); +} + +static void +gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable, + GdkGC *gc, + PangoMatrix *matrix, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs) +{ + GdkDrawableImplX11 *impl; + PangoRenderer *renderer; + + impl = GDK_DRAWABLE_IMPL_X11 (drawable); + + g_return_if_fail (PANGO_XFT_IS_FONT (font)); + + renderer = _gdk_x11_renderer_get (drawable, gc); + if (matrix) + pango_renderer_set_matrix (renderer, matrix); + pango_renderer_draw_glyphs (renderer, font, glyphs, x, y); + if (matrix) + pango_renderer_set_matrix (renderer, NULL); +} + +static void gdk_x11_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, @@ -1444,6 +1624,47 @@ } static void +gdk_x11_draw_trapezoids (GdkDrawable *drawable, + GdkGC *gc, + GdkTrapezoid *trapezoids, + gint n_trapezoids) +{ + GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; + GdkDisplay *display = gdk_screen_get_display (screen); + XTrapezoid *xtrapezoids; + gint i; + + if (!_gdk_x11_have_render_with_trapezoids (display)) + { + GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper; + GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_trapezoids (wrapper, gc, + trapezoids, n_trapezoids); + return; + } + + xtrapezoids = g_new (XTrapezoid, n_trapezoids); + + for (i = 0; i < n_trapezoids; i++) + { + xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1); + xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2); + xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11); + xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1); + xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12); + xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2); + xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21); + xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1); + xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22); + xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2); + } + + _gdk_x11_drawable_draw_xtrapezoids (drawable, gc, + xtrapezoids, n_trapezoids); + + g_free (xtrapezoids); +} + +static void gdk_x11_cairo_surface_destroy (void *data) { GdkDrawableImplX11 *impl = data; @@ -1498,5 +1719,89 @@ return impl->cairo_surface; } +void +_gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable, + GdkGC *gc, + XTrapezoid *xtrapezoids, + int n_trapezoids) +{ + GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; + GdkDisplay *display = gdk_screen_get_display (screen); + GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); + + XftDraw *draw; + + if (!_gdk_x11_have_render_with_trapezoids (display)) + { + /* This is the case of drawing the borders of the unknown glyph box + * without render on the display, we need to feed it back to + * fallback code. Not efficient, but doesn't matter. + */ + GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids); + int i; + + for (i = 0; i < n_trapezoids; i++) + { + trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top); + trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom); + trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x); + trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x); + trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x); + trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x); + } + + gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids); + g_free (trapezoids); + + return; + } + + gdk_x11_drawable_update_xft_clip (drawable, gc); + draw = gdk_x11_drawable_get_xft_draw (drawable); + + if (!x11display->mask_format) + x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay, + PictStandardA8); + + XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver, + _gdk_x11_gc_get_fg_picture (gc), + XftDrawPicture (draw), + x11display->mask_format, + - gc->ts_x_origin, - gc->ts_y_origin, + xtrapezoids, n_trapezoids); +} + +void +_gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable, + GdkGC *gc, + XftFont *xft_font, + XftGlyphSpec *glyphs, + gint n_glyphs) +{ + GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; + GdkDisplay *display = gdk_screen_get_display (screen); + GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); + XftDraw *draw; + + gdk_x11_drawable_update_xft_clip (drawable, gc); + draw = gdk_x11_drawable_get_xft_draw (drawable); + + if (_gdk_x11_have_render (display)) + { + XftGlyphSpecRender (x11display->xdisplay, PictOpOver, + _gdk_x11_gc_get_fg_picture (gc), + xft_font, + XftDrawPicture (draw), + - gc->ts_x_origin, - gc->ts_y_origin, + glyphs, n_glyphs); + } + else + { + XftColor color; + + _gdk_gc_x11_get_fg_xft_color (gc, &color); + XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs); + } +} #define __GDK_DRAWABLE_X11_C__ #include "gdkaliasdef.c" Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.h 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h 2006-10-30 12:59:30.000000000 +0000 @@ -33,6 +33,7 @@ #include #include +#include G_BEGIN_DECLS @@ -68,6 +69,8 @@ Window xid; GdkScreen *screen; + XftDraw *xft_draw; + Picture picture; cairo_surface_t *cairo_surface; }; @@ -92,7 +95,15 @@ /* Note that the following take GdkDrawableImplX11, not the wrapper drawable */ void _gdk_x11_drawable_finish (GdkDrawable *drawable); void _gdk_x11_drawable_update_size (GdkDrawable *drawable); - +void _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable, + GdkGC *gc, + XTrapezoid *xtrapezoids, + int n_trapezoids); +void _gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable, + GdkGC *gc, + XftFont *xft_font, + XftGlyphSpec *glyphs, + gint n_glyphs); G_END_DECLS #endif /* __GDK_DRAWABLE_X11_H__ */ Index: gtk+-2.10.6/gdk/x11/gdkgc-x11.c =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkgc-x11.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkgc-x11.c 2006-10-30 12:59:30.000000000 +0000 @@ -80,7 +80,10 @@ gdk_gc_x11_finalize (GObject *object) { GdkGCX11 *x11_gc = GDK_GC_X11 (object); - + + if (x11_gc->fg_picture != None) + XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture); + XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc)); G_OBJECT_CLASS (_gdk_gc_x11_parent_class)->finalize (object); @@ -110,7 +113,7 @@ private->dirty_mask = 0; private->have_clip_mask = FALSE; - + private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; private->depth = gdk_drawable_get_depth (drawable); @@ -339,6 +342,18 @@ } static void +clear_fg_picture (GdkGC *gc) +{ + GdkGCX11 *x11_gc = GDK_GC_X11 (gc); + + if (x11_gc->fg_picture != None) + { + XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture); + x11_gc->fg_picture = None; + } +} + +static void gdk_x11_gc_set_values (GdkGC *gc, GdkGCValues *values, GdkGCValuesMask values_mask) @@ -367,6 +382,29 @@ x11_gc->have_clip_mask = values->clip_mask != NULL; } + if (values_mask & GDK_GC_BACKGROUND) + { + if (_gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED) + clear_fg_picture (gc); + } + + if (values_mask & GDK_GC_FILL) + { + clear_fg_picture (gc); + } + + if (values_mask & GDK_GC_STIPPLE) + { + if (_gdk_gc_get_fill (gc) == GDK_STIPPLED || _gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED) + clear_fg_picture (gc); + } + + if (values_mask & GDK_GC_TILE) + { + if (_gdk_gc_get_fill (gc) == GDK_TILED) + clear_fg_picture (gc); + } + gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask); XChangeGC (GDK_GC_XDISPLAY (gc), @@ -642,6 +680,8 @@ x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask; x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region; x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask; + + clear_fg_picture (dst_gc); } /** @@ -701,5 +741,359 @@ 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); +} + +static Picture +make_fg_tile_picture (GdkGC *gc) +{ + GdkGCX11 *x11_gc = GDK_GC_X11 (gc); + GdkVisual *visual = gdk_drawable_get_visual (_gdk_gc_get_tile (gc)); + XRenderPictFormat *format = NULL; + + if (visual) + { + format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc), + GDK_VISUAL_XVISUAL (visual)); + } + else if (x11_gc->depth == 1) + { + format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc), + PictStandardA1); + } + + if (format) + { + XRenderPictureAttributes pa; + pa.repeat = True; + + return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), + GDK_PIXMAP_XID (_gdk_gc_get_tile (gc)), + format, + CPRepeat, &pa); + } + + return None; +} + +static Picture +make_stipple_picture (GdkGC *gc) +{ + XRenderPictFormat *format = NULL; + XRenderPictureAttributes pa; + + format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc), + PictStandardA1); + + pa.repeat = True; + return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), + GDK_PIXMAP_XID (_gdk_gc_get_stipple (gc)), + format, + CPRepeat, &pa); +} + +static Picture +make_color_picture (GdkGC *gc, + XRenderColor *color) +{ + GdkGCX11 *x11_gc = GDK_GC_X11 (gc); + XRenderPictureAttributes pa; + XRenderPictFormat *pix_format = foreground_format (gc); + Pixmap pix; + Picture picture; + + if (!pix_format) + return None; + + pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), + GDK_SCREEN_XROOTWIN (x11_gc->screen), + 1, 1, pix_format->depth); + pa.repeat = True; + picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), + pix, + pix_format, + CPRepeat, &pa); + XFreePixmap (GDK_GC_XDISPLAY (gc), pix); + + XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, + picture, color, + 0, 0, 1, 1); + + return picture; +} + +static void +get_bg_color (GdkGC *gc, + XRenderColor *render_color) +{ + GdkColormap *cmap; + + cmap = gdk_gc_get_colormap (gc); + + if (cmap) + { + GdkColor color; + + gdk_colormap_query_color (cmap, _gdk_gc_get_bg_pixel (gc), &color); + + render_color->alpha = 0xffff; + render_color->red = color.red; + render_color->green = color.green; + render_color->blue = color.blue; + } + else /* Not worth warning, just use black */ + { + render_color->alpha = 0xffff; + render_color->red = 0; + render_color->green = 0; + render_color->blue = 0; + } +} + +/** + * _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. + * + * 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; + gboolean new = FALSE; + XftColor xftcolor; + GdkFill fill; + int width, height; + + g_return_val_if_fail (GDK_IS_GC_X11 (gc), None); + + if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc))) + return None; + + x11_gc = GDK_GC_X11 (gc); + + fill = GDK_SOLID; + width = 1; + height = 1; + + switch (_gdk_gc_get_fill (gc)) + { + case GDK_SOLID: + break; + case GDK_TILED: + if (_gdk_gc_get_tile (gc)) + { + if (!x11_gc->fg_picture) + x11_gc->fg_picture = make_fg_tile_picture (gc); + + if (x11_gc->fg_picture != None) + return x11_gc->fg_picture; + } + break; + case GDK_STIPPLED: + case GDK_OPAQUE_STIPPLED: + if (_gdk_gc_get_stipple (gc)) + { + gdk_drawable_get_size (_gdk_gc_get_stipple (gc), &width, &height); + fill = _gdk_gc_get_fill (gc); + } + break; + } + + if (x11_gc->fg_picture == None) + { + XRenderPictureAttributes pa; + XRenderPictFormat *pix_format = foreground_format (gc); + Pixmap pix; + + if (!pix_format) + return None; + + pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), + GDK_SCREEN_XROOTWIN (x11_gc->screen), + width, height, pix_format->depth); + pa.repeat = True; + x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), + pix, + pix_format, + CPRepeat, &pa); + XFreePixmap (GDK_GC_XDISPLAY (gc), pix); + + new = TRUE; + } + + _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor); + + if (x11_gc->fg_picture_color.alpha != 0xffff || + x11_gc->fg_picture_color.red != xftcolor.color.red || + x11_gc->fg_picture_color.green != xftcolor.color.green || + x11_gc->fg_picture_color.blue != xftcolor.color.blue) + { + x11_gc->fg_picture_color.alpha = 0xffff; + x11_gc->fg_picture_color.red = xftcolor.color.red; + x11_gc->fg_picture_color.green = xftcolor.color.green; + x11_gc->fg_picture_color.blue = xftcolor.color.blue; + + new = TRUE; + } + + switch (fill) + { + case GDK_SOLID: + XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, + x11_gc->fg_picture, &x11_gc->fg_picture_color, + 0, 0, width, height); + break; + case GDK_STIPPLED: + { + Picture stipple_picture = make_stipple_picture (gc); + + XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, + x11_gc->fg_picture, &x11_gc->fg_picture_color, + 0, 0, width, height); + XRenderComposite (GDK_GC_XDISPLAY (gc), + PictOpInReverse, + stipple_picture, None, x11_gc->fg_picture, + 0, 0, 0, 0, 0, 0, width, height); + + XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture); + } + break; + case GDK_OPAQUE_STIPPLED: + { + XRenderColor bg_color; + + Picture stipple_picture = make_stipple_picture (gc); + Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color); + + get_bg_color (gc, &bg_color); + + XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, + x11_gc->fg_picture, &bg_color, + 0, 0, width, height); + XRenderComposite (GDK_GC_XDISPLAY (gc), + PictOpOver, + fg_picture, stipple_picture, x11_gc->fg_picture, + 0, 0, 0, 0, 0, 0, width, height); + + XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture); + XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture); + } + break; + case GDK_TILED: + g_assert_not_reached (); /* handled above */ + break; + } + + return x11_gc->fg_picture; +} + +/** + * _gdk_gc_x11_get_fg_xft_color: + * @gc: a #GdkGC + * @xftcolor: location to store the color + * + * Gets the foreground color of the GC as a XftColor. + **/ +void +_gdk_gc_x11_get_fg_xft_color (GdkGC *gc, + XftColor *xftcolor) +{ + GdkGCX11 *x11_gc; + GdkColormap *cmap; + GdkColor color; + + g_return_if_fail (GDK_IS_GC_X11 (gc)); + + x11_gc = GDK_GC_X11 (gc); + + cmap = gdk_gc_get_colormap (gc); + + xftcolor->pixel = _gdk_gc_get_fg_pixel (gc); + + if (cmap) + { + gdk_colormap_query_color (cmap, xftcolor->pixel, &color); + xftcolor->color.alpha = 0xffff; + xftcolor->color.red = color.red; + xftcolor->color.green = color.green; + xftcolor->color.blue = color.blue; + } + else if (x11_gc->depth == 1) + { + /* Drawing with Xft on a bitmap is a bit bizzare; it + * takes alpha >= 0x8000 to mean 'set to 1' and + * alpha < 0x8000 to mean 'set to 0'. + */ + if (xftcolor->pixel) + { + xftcolor->color.red = 0xffff; + xftcolor->color.green = 0xffff; + xftcolor->color.blue = 0xffff; + xftcolor->color.alpha = 0xffff; + } + else + { + xftcolor->color.red = 0; + xftcolor->color.green = 0; + xftcolor->color.blue = 0; + xftcolor->color.alpha = 0; + } + } + else + { + g_warning ("Using Xft rendering requires the GC argument to have a\n" + "specified colormap. If the GC was created for a drawable\n" + "with a colormap, the colormap will be set on the GC\n" + "automatically. Otherwise, a colormap must be set on it with" + "gdk_gc_set_colormap"); + } +} + +void +_gdk_windowing_gc_get_foreground (GdkGC *gc, + GdkColor *color) +{ + GdkColormap *cmap; + + g_return_if_fail (GDK_IS_GC_X11 (gc)); + + color->pixel = _gdk_gc_get_fg_pixel (gc); + + cmap = gdk_gc_get_colormap (gc); + + if (cmap) + gdk_colormap_query_color (cmap, _gdk_gc_get_fg_pixel (gc), color); + else + g_warning ("No colormap in _gdk_windowing_gc_get_foreground"); +} #define __GDK_GC_X11_C__ #include "gdkaliasdef.c" Index: gtk+-2.10.6/gdk/x11/gdkprivate-x11.h =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkprivate-x11.h 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkprivate-x11.h 2006-10-30 12:59:30.000000000 +0000 @@ -63,6 +63,9 @@ guint have_clip_region : 1; guint have_clip_mask : 1; guint depth : 8; + + Picture fg_picture; + XRenderColor fg_picture_color; }; struct _GdkGCX11Class @@ -102,6 +105,11 @@ GType _gdk_gc_x11_get_type (void); gboolean _gdk_x11_have_render (GdkDisplay *display); +gboolean _gdk_x11_have_render_with_trapezoids (GdkDisplay *display); + +Picture _gdk_x11_gc_get_fg_picture (GdkGC *gc); +void _gdk_gc_x11_get_fg_xft_color (GdkGC *gc, + XftColor *xftcolor); GdkGC *_gdk_x11_gc_new (GdkDrawable *drawable, GdkGCValues *values, Index: gtk+-2.10.6/gdk/x11/gdkwindow-x11.c =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkwindow-x11.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkwindow-x11.c 2006-10-30 12:59:30.000000000 +0000 @@ -1114,7 +1114,8 @@ { GdkWindowObject *private = (GdkWindowObject *)window; GdkToplevelX11 *toplevel; - + GdkDrawableImplX11 *draw_impl; + g_return_if_fail (GDK_IS_WINDOW (window)); _gdk_selection_window_destroyed (window); @@ -1126,6 +1127,11 @@ if (toplevel) gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel); + draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); + + if (draw_impl->xft_draw) + XftDrawDestroy (draw_impl->xft_draw); + _gdk_x11_drawable_finish (private->impl); if (!recursing && !foreign_destroy) Index: gtk+-2.10.6/gdk/x11/Makefile.am =================================================================== --- gtk+-2.10.6.orig/gdk/x11/Makefile.am 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/Makefile.am 2006-10-30 12:59:30.000000000 +0000 @@ -37,6 +37,7 @@ gdkinput.c \ gdkkeys-x11.c \ gdkmain-x11.c \ + gdkpango-x11.c \ gdkpixmap-x11.c \ gdkpixmap-x11.h \ gdkproperty-x11.c \ Index: gtk+-2.10.6/gtk/gtkcalendar.c =================================================================== --- gtk+-2.10.6.orig/gtk/gtkcalendar.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gtk/gtkcalendar.c 2006-10-30 12:59:30.000000000 +0000 @@ -1821,7 +1821,7 @@ } } - + /**************************************** * Repainting * ****************************************/ @@ -1831,7 +1831,7 @@ { GtkWidget *widget = GTK_WIDGET (calendar); GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); - cairo_t *cr; + GdkGC *gc; char buffer[255]; int x, y; gint header_width; @@ -1849,7 +1849,7 @@ else year_left = !priv->year_before; - cr = gdk_cairo_create (priv->header_win); + gc = calendar->gc; header_width = widget->allocation.width - 2 * widget->style->xthickness; @@ -1902,9 +1902,9 @@ - (max_year_width - logical_rect.width)/2); - gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar))); - cairo_move_to (cr, x, y); - pango_cairo_show_layout (cr, layout); + gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar))); + gdk_draw_layout (priv->header_win, gc, x, y, layout); + /* Draw month */ g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]); @@ -1924,19 +1924,19 @@ else x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2; - cairo_move_to (cr, x, y); - pango_cairo_show_layout (cr, layout); - + gdk_draw_layout (priv->header_win, gc, x, y, layout); + + gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar))); + g_object_unref (layout); - cairo_destroy (cr); } static void calendar_paint_day_names (GtkCalendar *calendar) { GtkWidget *widget = GTK_WIDGET (calendar); + GdkGC *gc; GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); - cairo_t *cr; char buffer[255]; int day,i; int day_width, cal_width; @@ -1946,8 +1946,7 @@ gint focus_padding; gint focus_width; - cr = gdk_cairo_create (priv->day_name_win); - + gc = calendar->gc; gtk_widget_style_get (GTK_WIDGET (widget), "focus-line-width", &focus_width, "focus-padding", &focus_padding, @@ -1961,22 +1960,19 @@ * Draw rectangles as inverted background for the labels. */ - gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); - cairo_rectangle (cr, - CALENDAR_MARGIN, CALENDAR_MARGIN, - cal_width-CALENDAR_MARGIN * 2, - priv->day_name_h - CALENDAR_MARGIN); - cairo_fill (cr); - + gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); + gdk_draw_rectangle (priv->day_name_win, gc, TRUE, + CALENDAR_MARGIN, CALENDAR_MARGIN, + cal_width-CALENDAR_MARGIN * 2, + priv->day_name_h - CALENDAR_MARGIN); + if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - { - cairo_rectangle (cr, - CALENDAR_MARGIN, - priv->day_name_h - CALENDAR_YSEP, - priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN, - CALENDAR_YSEP); - cairo_fill (cr); - } + gdk_draw_rectangle (priv->day_name_win, gc, TRUE, + CALENDAR_MARGIN, + priv->day_name_h - CALENDAR_YSEP, + priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN, + CALENDAR_YSEP); + /* * Write the labels @@ -1984,7 +1980,7 @@ layout = gtk_widget_create_pango_layout (widget, NULL); - gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget)); + gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); for (i = 0; i < 7; i++) { if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) @@ -1997,19 +1993,18 @@ pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - cairo_move_to (cr, - (CALENDAR_MARGIN + - + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? - (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0)) - : 0) - + day_wid_sep * i - + (day_width - logical_rect.width)/2), - CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y); - pango_cairo_show_layout (cr, layout); + gdk_draw_layout (priv->day_name_win, gc, + (CALENDAR_MARGIN + + + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? + (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0)) + : 0) + + day_wid_sep * i + + (day_width - logical_rect.width)/2), + CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y, + layout); } g_object_unref (layout); - cairo_destroy (cr); } static void @@ -2017,7 +2012,7 @@ { GtkWidget *widget = GTK_WIDGET (calendar); GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); - cairo_t *cr; + GdkGC *gc; gint row, week = 0, year; gint x_loc; char buffer[32]; @@ -2027,7 +2022,7 @@ gint focus_padding; gint focus_width; - cr = gdk_cairo_create (priv->week_win); + gc = calendar->gc; gtk_widget_style_get (GTK_WIDGET (widget), "focus-line-width", &focus_width, @@ -2038,20 +2033,20 @@ * Draw a rectangle as inverted background for the labels. */ - gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); + gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); if (priv->day_name_win) - cairo_rectangle (cr, - CALENDAR_MARGIN, - 0, - priv->week_width - CALENDAR_MARGIN, - priv->main_h - CALENDAR_MARGIN); + gdk_draw_rectangle (priv->week_win, gc, TRUE, + CALENDAR_MARGIN, + 0, + priv->week_width - CALENDAR_MARGIN, + priv->main_h - CALENDAR_MARGIN); else - cairo_rectangle (cr, - CALENDAR_MARGIN, - CALENDAR_MARGIN, - priv->week_width - CALENDAR_MARGIN, - priv->main_h - 2 * CALENDAR_MARGIN); - cairo_fill (cr); + gdk_draw_rectangle (priv->week_win, gc, TRUE, + CALENDAR_MARGIN, + CALENDAR_MARGIN, + priv->week_width - CALENDAR_MARGIN, + priv->main_h - 2 * CALENDAR_MARGIN); + /* * Write the labels @@ -2059,7 +2054,7 @@ layout = gtk_widget_create_pango_layout (widget, NULL); - gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget)); + gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); day_height = calendar_row_height (calendar); for (row = 0; row < 6; row++) { @@ -2095,12 +2090,10 @@ - logical_rect.width - CALENDAR_XSEP - focus_padding - focus_width); - cairo_move_to (cr, x_loc, y_loc); - pango_cairo_show_layout (cr, layout); + gdk_draw_layout (priv->week_win, gc, x_loc, y_loc, layout); } g_object_unref (layout); - cairo_destroy (cr); } static void @@ -2149,7 +2142,7 @@ { GtkWidget *widget = GTK_WIDGET (calendar); GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); - cairo_t *cr; + GdkGC *gc; GdkColor *text_color; gchar buffer[32]; gint day; @@ -2162,7 +2155,7 @@ g_return_if_fail (row < 6); g_return_if_fail (col < 7); - cr = gdk_cairo_create (priv->main_win); + gc = calendar->gc; day = calendar->day[row][col]; @@ -2170,11 +2163,11 @@ if (calendar->day_month[row][col] == MONTH_PREV) { - text_color = PREV_MONTH_COLOR (widget); + gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar))); } else if (calendar->day_month[row][col] == MONTH_NEXT) { - text_color = NEXT_MONTH_COLOR (widget); + gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar))); } else { @@ -2188,16 +2181,16 @@ #endif if (calendar->selected_day == day) { - gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); - gdk_cairo_rectangle (cr, &day_rect); - cairo_fill (cr); + gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (GTK_WIDGET (calendar))); + gdk_draw_rectangle (priv->main_win, gc, TRUE, day_rect.x, day_rect.y, + day_rect.width, day_rect.height); } if (calendar->selected_day == day) - text_color = SELECTED_FG_COLOR (widget); + gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar))); else if (calendar->marked_date[day-1]) - text_color = MARKED_COLOR (widget); + gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar))); else - text_color = NORMAL_DAY_COLOR (widget); + gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar))); } /* Translators: this defines whether the day numbers should use @@ -2219,16 +2212,13 @@ x_loc -= logical_rect.width; y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2; - gdk_cairo_set_source_color (cr, text_color); - cairo_move_to (cr, x_loc, y_loc); - pango_cairo_show_layout (cr, layout); + gdk_draw_layout (priv->main_win, gc, + x_loc, y_loc, layout); if (calendar->marked_date[day-1] && calendar->day_month[row][col] == MONTH_CURRENT) - { - cairo_move_to (cr, x_loc - 1, y_loc); - pango_cairo_show_layout (cr, layout); - } + gdk_draw_layout (priv->main_win, gc, + x_loc-1, y_loc, layout); if (GTK_WIDGET_HAS_FOCUS (calendar) && calendar->focus_row == row && calendar->focus_col == col) @@ -2253,7 +2243,6 @@ } g_object_unref (layout); - cairo_destroy (cr); } static void Index: gtk+-2.10.6/gtk/gtkentry.c =================================================================== --- gtk+-2.10.6.orig/gtk/gtkentry.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gtk/gtkentry.c 2006-10-30 12:59:30.000000000 +0000 @@ -3333,7 +3333,6 @@ if (GTK_WIDGET_DRAWABLE (entry)) { PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); - cairo_t *cr; gint x, y; gint start_pos, end_pos; @@ -3341,56 +3340,60 @@ get_layout_position (entry, &x, &y); - cr = gdk_cairo_create (entry->text_area); - - cairo_move_to (cr, x, y); - gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); - pango_cairo_show_layout (cr, layout); - + gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], + x, y, + layout); + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) { gint *ranges; gint n_ranges, i; PangoRectangle logical_rect; - GdkColor *selection_color, *text_color; + GdkGC *selection_gc, *text_gc; GtkBorder inner_border; - + GdkRegion *clip_region; + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); if (GTK_WIDGET_HAS_FOCUS (entry)) { - selection_color = &widget->style->base [GTK_STATE_SELECTED]; - text_color = &widget->style->text [GTK_STATE_SELECTED]; + selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; + text_gc = widget->style->text_gc [GTK_STATE_SELECTED]; } else { - selection_color = &widget->style->base [GTK_STATE_ACTIVE]; - text_color = &widget->style->text [GTK_STATE_ACTIVE]; + selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; + text_gc = widget->style->text_gc [GTK_STATE_ACTIVE]; } - + + clip_region = gdk_region_new (); _gtk_entry_effective_inner_border (entry, &inner_border); for (i = 0; i < n_ranges; ++i) - cairo_rectangle (cr, - inner_border.left - entry->scroll_offset + ranges[2 * i], - y, - ranges[2 * i + 1], - logical_rect.height); + { + GdkRectangle rect; - cairo_clip (cr); - - gdk_cairo_set_source_color (cr, selection_color); - cairo_paint (cr); + rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i]; + rect.y = y; + rect.width = ranges[2 * i + 1]; + rect.height = logical_rect.height; + + gdk_draw_rectangle (entry->text_area, selection_gc, TRUE, + rect.x, rect.y, rect.width, rect.height); - cairo_move_to (cr, x, y); - gdk_cairo_set_source_color (cr, text_color); - pango_cairo_show_layout (cr, layout); + gdk_region_union_with_rect (clip_region, &rect); + } + gdk_gc_set_clip_region (text_gc, clip_region); + gdk_draw_layout (entry->text_area, text_gc, + x, y, + layout); + gdk_gc_set_clip_region (text_gc, NULL); + + gdk_region_destroy (clip_region); g_free (ranges); } - - cairo_destroy (cr); } } Index: gtk+-2.10.6/gtk/gtkwidget.c =================================================================== --- gtk+-2.10.6.orig/gtk/gtkwidget.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gtk/gtkwidget.c 2006-10-30 12:59:30.000000000 +0000 @@ -5445,7 +5445,8 @@ GdkScreen *screen; update_pango_context (widget, context); - +/* TODO: Figure out the proper way to handle this in a pangoxft setting + screen = gtk_widget_get_screen_unchecked (widget); if (screen) { @@ -5453,7 +5454,7 @@ gdk_screen_get_resolution (screen)); pango_cairo_context_set_font_options (context, gdk_screen_get_font_options (screen)); - } + }*/ } } Index: gtk+-2.10.6/gdk/x11/gdkpango-x11.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkpango-x11.c 2006-10-30 12:59:30.000000000 +0000 @@ -0,0 +1,174 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "gdkx.h" +#include "gdkdisplay-x11.h" +#include "gdkpango.h" +#include +#include +#include "gdkalias.h" + +#include + +typedef struct _GdkX11Renderer GdkX11Renderer; +typedef struct _GdkX11RendererClass GdkX11RendererClass; + +#define GDK_TYPE_X11_RENDERER (_gdk_x11_renderer_get_type()) +#define GDK_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_RENDERER, GdkX11Renderer)) +#define GDK_IS_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_RENDERER)) +#define GDK_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_RENDERER, GdkX11RendererClass)) +#define GDK_IS_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_RENDERER)) +#define GDK_X11_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_RENDERER, GdkX11RendererClass)) + +#define MAX_RENDER_PART PANGO_RENDER_PART_STRIKETHROUGH + +struct _GdkX11Renderer +{ + PangoXftRenderer parent_instance; + + XRenderPictFormat *mask_format; + + GdkDrawable *drawable; + GdkGC *gc; +}; + +struct _GdkX11RendererClass +{ + PangoXftRendererClass parent_class; +}; + +G_DEFINE_TYPE (GdkX11Renderer, _gdk_x11_renderer, PANGO_TYPE_XFT_RENDERER) + +static void +gdk_x11_renderer_finalize (GObject *object) +{ + G_OBJECT_CLASS (_gdk_x11_renderer_parent_class)->finalize (object); +} + +static void +gdk_x11_renderer_composite_trapezoids (PangoXftRenderer *xftrenderer, + PangoRenderPart part, + XTrapezoid *trapezoids, + int n_trapezoids) +{ + /* Because we only use this renderer for "draw_glyphs()" calls, we + * won't hit this code path much. However, it is hit for drawing + * the "unknown glyph" hex squares. We can safely ignore the part, + */ + GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer); + + _gdk_x11_drawable_draw_xtrapezoids (x11_renderer->drawable, + x11_renderer->gc, + trapezoids, n_trapezoids); + +} + +static void +gdk_x11_renderer_composite_glyphs (PangoXftRenderer *xftrenderer, + XftFont *xft_font, + XftGlyphSpec *glyphs, + gint n_glyphs) +{ + GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer); + + _gdk_x11_drawable_draw_xft_glyphs (x11_renderer->drawable, + x11_renderer->gc, + xft_font, glyphs, n_glyphs); +} + +static void +_gdk_x11_renderer_init (GdkX11Renderer *renderer) +{ +} + +static void +_gdk_x11_renderer_class_init (GdkX11RendererClass *klass) +{ + PangoXftRendererClass *xftrenderer_class = PANGO_XFT_RENDERER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + xftrenderer_class->composite_glyphs = gdk_x11_renderer_composite_glyphs; + xftrenderer_class->composite_trapezoids = gdk_x11_renderer_composite_trapezoids; + + object_class->finalize = gdk_x11_renderer_finalize; +} + +PangoRenderer * +_gdk_x11_renderer_get (GdkDrawable *drawable, + GdkGC *gc) +{ + GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; + GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); + GdkX11Renderer *x11_renderer; + + if (!screen_x11->renderer) + { + screen_x11->renderer = g_object_new (GDK_TYPE_X11_RENDERER, + "display", GDK_SCREEN_XDISPLAY (screen), + "screen", GDK_SCREEN_XNUMBER (screen), + NULL); + } + + x11_renderer = GDK_X11_RENDERER (screen_x11->renderer); + + x11_renderer->drawable = drawable; + x11_renderer->gc = gc; + + return screen_x11->renderer; +} + +/** + * gdk_pango_context_get_for_screen: + * @screen: the #GdkScreen for which the context is to be created. + * + * Creates a #PangoContext for @screen. + * + * The context must be freed when you're finished with it. + * + * When using GTK+, normally you should use gtk_widget_get_pango_context() + * instead of this function, to get the appropriate context for + * the widget you intend to render text onto. + * + * Return value: a new #PangoContext for @screen + * + * Since: 2.2 + **/ +PangoContext * +gdk_pango_context_get_for_screen (GdkScreen *screen) +{ + PangoContext *context; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + if (screen->closed) + return NULL; + + context = pango_xft_get_context (GDK_SCREEN_XDISPLAY (screen), + GDK_SCREEN_X11 (screen)->screen_num); + + g_object_set_data (G_OBJECT (context), "gdk-pango-screen", screen); + + return context; +} + +#define __GDK_PANGO_X11_C__ +#include "gdkaliasdef.c" Index: gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c =================================================================== --- gtk+-2.10.6.orig/gdk/x11/gdkpixmap-x11.c 2006-10-30 12:58:30.000000000 +0000 +++ gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c 2006-10-30 12:59:30.000000000 +0000 @@ -119,6 +119,9 @@ { GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl); + if (draw_impl->xft_draw) + XftDrawDestroy (draw_impl->xft_draw); + _gdk_x11_drawable_finish (GDK_DRAWABLE (draw_impl)); } --- gtk+-2.10.6.orig/gtk/gtkcalendar.c.orig 2006-11-14 14:39:34.000000000 -0800 +++ gtk+-2.10.6/gtk/gtkcalendar.c 2006-11-14 14:37:34.000000000 -0800 @@ -1495,6 +1495,10 @@ gtk_calendar_realize (GtkWidget *widget) BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); gdk_window_show (priv->main_win); gdk_window_set_user_data (priv->main_win, widget); + + /* Set widgets gc */ + calendar->gc = gdk_gc_new (widget->window); + gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget)); gdk_window_show (widget->window); gdk_window_set_user_data (widget->window, widget);