diff options
author | Florian Müllner <fmuellner@gnome.org> | 2010-08-18 03:09:50 +0200 |
---|---|---|
committer | Thomas Thurman <tthurman@gnome.org> | 2010-09-15 11:58:29 -0400 |
commit | 3608ff90798cbb6c8d88be902abd56f1a4b16bc0 (patch) | |
tree | 4ffb446cbf78ea2defea218df7b9837f2509bfd9 /src | |
parent | 874f55b645d664925b49ee9972cd82dc39287098 (diff) | |
download | metacity-3608ff90798cbb6c8d88be902abd56f1a4b16bc0.tar.gz |
Replace GDK drawing API with cairo
The GDK drawing API was deprecated/removed.
https://bugzilla.gnome.org/show_bug.cgi?id=627245
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/draw-workspace.c | 19 | ||||
-rw-r--r-- | src/ui/frames.c | 119 | ||||
-rw-r--r-- | src/ui/tabpopup.c | 97 | ||||
-rw-r--r-- | src/ui/testgradient.c | 134 | ||||
-rw-r--r-- | src/ui/theme.c | 254 | ||||
-rw-r--r-- | src/ui/ui.c | 8 |
6 files changed, 330 insertions, 301 deletions
diff --git a/src/ui/draw-workspace.c b/src/ui/draw-workspace.c index 72daf67b..9dc491f5 100644 --- a/src/ui/draw-workspace.c +++ b/src/ui/draw-workspace.c @@ -179,6 +179,7 @@ wnck_draw_workspace (GtkWidget *widget, int i; GdkRectangle workspace_rect; GtkStateType state; + cairo_t *cr; workspace_rect.x = x; workspace_rect.y = y; @@ -191,28 +192,22 @@ wnck_draw_workspace (GtkWidget *widget, state = GTK_STATE_PRELIGHT; else state = GTK_STATE_NORMAL; + + cr = gdk_cairo_create (drawable); if (workspace_background) { - gdk_draw_pixbuf (drawable, - gtk_widget_get_style (GTK_WIDGET (widget))->dark_gc[state], - workspace_background, - 0, 0, - x, y, - -1, -1, - GDK_RGB_DITHER_MAX, - 0, 0); + gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y); + cairo_paint (cr); } else { - cairo_t *cr; - - cr = gdk_cairo_create (gtk_widget_get_window (widget)); gdk_cairo_set_source_color (cr, >k_widget_get_style (widget)->dark[state]); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); - cairo_destroy (cr); } + + cairo_destroy (cr); i = 0; while (i < n_windows) diff --git a/src/ui/frames.c b/src/ui/frames.c index 7945a0c6..d8fe3cdc 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -2010,46 +2010,73 @@ meta_frames_destroy_event (GtkWidget *widget, return TRUE; } -/* Cut and paste from GDK */ -static GdkGC * -get_bg_gc (GdkWindow *window, int x_offset, int y_offset) +#if !GTK_CHECK_VERSION(2,21,6) +/* Copied from GDK */ +static cairo_surface_t * +_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable) { - GdkWindow *parent = gdk_window_get_parent (window); - GdkPixmap *back_pixmap; - gboolean parent_relative; - guint gc_mask = 0; - GdkGCValues gc_values; + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); - gdk_window_get_back_pixmap (window, &back_pixmap, &parent_relative); - if (parent_relative && parent) - { - gint window_x, window_y; + return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable); +} - gdk_window_get_position (window, &window_x, &window_y); - return get_bg_gc (parent, - x_offset + window_x, - y_offset + window_y); - } - else if (back_pixmap) +static cairo_pattern_t * +gdk_window_get_background_pattern (GdkWindow *window) +{ + GdkWindowObject *private = (GdkWindowObject *) window; + cairo_pattern_t *pattern; + + g_return_val_if_fail (GDK_IS_WINDOW (window), NULL); + + if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG) + pattern = NULL; + else if (private->bg_pixmap != GDK_NO_BG && + private->bg_pixmap != NULL) { - gc_values.fill = GDK_TILED; - gc_values.tile = back_pixmap; - gc_values.ts_x_origin = x_offset; - gc_values.ts_y_origin = y_offset; - - gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN; + static cairo_user_data_key_t key; + cairo_surface_t *surface; - return gdk_gc_new_with_values (window, &gc_values, gc_mask); + surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap); + pattern = cairo_pattern_create_for_surface (surface); + cairo_surface_destroy (surface); + + cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); + cairo_pattern_set_user_data (pattern, + &key, + g_object_ref (private->bg_pixmap), + g_object_unref); } else { - GdkColor bg_color; - GdkGC *gc = gdk_gc_new (window); + pattern = + cairo_pattern_create_rgb (private->bg_color.red / 65535., + private->bg_color.green / 65535., + private->bg_color.blue / 65535.); + } + + return pattern; +} +#endif - gdk_window_get_background (window, &bg_color); - gdk_gc_set_foreground (gc, &bg_color); +static void +setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset) +{ + GdkWindow *parent = gdk_window_get_parent (window); + cairo_pattern_t *bg_pattern; + + bg_pattern = gdk_window_get_background_pattern (window); + if (bg_pattern == NULL && parent) + { + gint window_x, window_y; - return gc; + gdk_window_get_position (window, &window_x, &window_y); + setup_bg_cr (cr, parent, x_offset + window_x, y_offset + window_y); + } + else if (bg_pattern) + { + cairo_translate (cr, - x_offset, - y_offset); + cairo_set_source (cr, bg_pattern); + cairo_translate (cr, x_offset, y_offset); } } @@ -2058,12 +2085,16 @@ clear_backing (GdkPixmap *pixmap, GdkWindow *window, int xoffset, int yoffset) { - GdkGC *tmp_gc = get_bg_gc (window, xoffset, yoffset); + int width, height; + cairo_t *cr = gdk_cairo_create (pixmap); - gdk_draw_rectangle (pixmap, tmp_gc, TRUE, - 0, 0, -1, -1); - - g_object_unref (tmp_gc); + setup_bg_cr (cr, window, xoffset, yoffset); + + gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + cairo_destroy (cr); } /* Returns a pixmap with a piece of the windows frame painted on it. @@ -2226,10 +2257,10 @@ cached_pixels_draw (CachedPixels *pixels, GdkWindow *window, GdkRegion *region) { - GdkGC *gc; + cairo_t *cr; int i; - gc = gdk_gc_new (window); + cr = gdk_cairo_create (window); for (i = 0; i < 4; i++) { @@ -2238,16 +2269,15 @@ cached_pixels_draw (CachedPixels *pixels, if (piece->pixmap) { - gdk_draw_drawable (window, gc, piece->pixmap, - 0, 0, - piece->rect.x, piece->rect.y, - -1, -1); + gdk_cairo_set_source_pixmap (cr, piece->pixmap, + piece->rect.x, piece->rect.y); + cairo_paint (cr); subtract_from_region (region, piece->pixmap, piece->rect.x, piece->rect.y); } } - g_object_unref (gc); + cairo_destroy (cr); } static gboolean @@ -2556,11 +2586,6 @@ meta_frames_set_window_background (MetaFrames *frames, GTK_WIDGET (frames), &color); - /* Fill in color.pixel */ - - gdk_rgb_find_color (gtk_widget_get_colormap (GTK_WIDGET (frames)), - &color); - /* Set A in ARGB to window_background_alpha, if we have ARGB */ visual = gtk_widget_get_visual (GTK_WIDGET (frames)); diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c index 5cc4d716..544bb013 100644 --- a/src/ui/tabpopup.c +++ b/src/ui/tabpopup.c @@ -78,6 +78,9 @@ outline_window_expose (GtkWidget *widget, { MetaTabPopup *popup; TabEntry *te; + GtkStyle *style; + GdkWindow *window; + cairo_t *cr; popup = data; @@ -85,20 +88,26 @@ outline_window_expose (GtkWidget *widget, return FALSE; te = popup->current_selected_entry; + window = gtk_widget_get_window (widget); + style = gtk_widget_get_style (widget); + cr = gdk_cairo_create (window); - gdk_draw_rectangle (widget->window, - widget->style->white_gc, - FALSE, - 0, 0, - te->rect.width - 1, - te->rect.height - 1); - - gdk_draw_rectangle (widget->window, - widget->style->white_gc, - FALSE, - te->inner_rect.x - 1, te->inner_rect.y - 1, - te->inner_rect.width + 1, - te->inner_rect.height + 1); + cairo_set_line_width (cr, 1.0); + gdk_cairo_set_source_color (cr, &style->white); + + cairo_rectangle (cr, + 0.5, 0.5, + te->rect.width - 1, + te->rect.height - 1); + cairo_stroke (cr); + + cairo_rectangle (cr, + te->inner_rect.x - 0.5, te->inner_rect.y - 0.5, + te->inner_rect.width + 1, + te->inner_rect.height + 1); + cairo_stroke (cr); + + cairo_destroy (cr); return FALSE; } @@ -687,6 +696,9 @@ meta_select_image_expose_event (GtkWidget *widget, { int x, y, w, h; GtkMisc *misc; + GtkStyle *style; + GtkStateType state; + cairo_t *cr; misc = GTK_MISC (widget); @@ -705,26 +717,30 @@ meta_select_image_expose_event (GtkWidget *widget, w = widget->requisition.width - OUTSIDE_SELECT_RECT * 2 - 1; h = widget->requisition.height - OUTSIDE_SELECT_RECT * 2 - 1; - gdk_draw_rectangle (widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - FALSE, - x, y, w, h); - gdk_draw_rectangle (widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - FALSE, - x - 1, y - 1, w + 2, h + 2); - + style = gtk_widget_get_style (widget); + state = gtk_widget_get_state (widget); + cr = gdk_cairo_create (widget->window); + + cairo_set_line_width (cr, 2.0); + gdk_cairo_set_source_color (cr, &style->fg[state]); + + cairo_rectangle (cr, x, y, w + 1, h + 1); + cairo_stroke (cr); + + cairo_set_line_width (cr, 1.0); #if 0 - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_SELECTED], - TRUE, - x, y, w, h); + gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_SELECTED]); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); #endif + #if 0 gtk_paint_focus (widget->style, widget->window, &event->area, widget, "meta-tab-image", x, y, w, h); #endif + + cairo_destroy (cr); } return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); @@ -873,6 +889,8 @@ meta_select_workspace_expose_event (GtkWidget *widget, { MetaWorkspace *workspace; WnckWindowDisplayInfo *windows; + GtkStyle *style; + cairo_t *cr; int i, n_windows; GList *tmp, *list; @@ -928,19 +946,20 @@ meta_select_workspace_expose_event (GtkWidget *widget, if (META_SELECT_WORKSPACE (widget)->selected) { - i = SELECT_OUTLINE_WIDTH - 1; - while (i >= 0) - { - gdk_draw_rectangle (widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - FALSE, - i, - i, - widget->allocation.width - i * 2 - 1, - widget->allocation.height - i * 2 - 1); - - --i; - } + style = gtk_widget_get_style (widget); + cr = gdk_cairo_create (widget->window); + + gdk_cairo_set_source_color (cr, + &style->fg[gtk_widget_get_state (widget)]); + cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH); + + cairo_rectangle (cr, + SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0, + widget->allocation.width - SELECT_OUTLINE_WIDTH, + widget->allocation.height - SELECT_OUTLINE_WIDTH); + cairo_stroke (cr); + + cairo_destroy (cr); } return TRUE; diff --git a/src/ui/testgradient.c b/src/ui/testgradient.c index 02c1364c..89d0d228 100644 --- a/src/ui/testgradient.c +++ b/src/ui/testgradient.c @@ -24,7 +24,7 @@ #include <gtk/gtk.h> typedef void (* RenderGradientFunc) (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height); @@ -34,28 +34,22 @@ draw_checkerboard (GdkDrawable *drawable, int height) { gint i, j, xcount, ycount; - GdkGC *gc1, *gc2; - GdkColor color; + GdkColor color1, color2; + cairo_t *cr; #define CHECK_SIZE 10 #define SPACING 2 - - /* It would be a bit more efficient to keep these - * GC's around instead of recreating on each expose, but - * this is the lazy/slow way. - */ - gc1 = gdk_gc_new (drawable); - color.red = 30000; - color.green = 30000; - color.blue = 30000; - gdk_gc_set_rgb_fg_color (gc1, &color); - - gc2 = gdk_gc_new (drawable); - color.red = 50000; - color.green = 50000; - color.blue = 50000; - gdk_gc_set_rgb_fg_color (gc2, &color); + color1.red = 30000; + color1.green = 30000; + color1.blue = 30000; + + color2.red = 50000; + color2.green = 50000; + color2.blue = 50000; + + cr = gdk_cairo_create (drawable); + xcount = 0; i = SPACING; while (i < width) @@ -64,23 +58,17 @@ draw_checkerboard (GdkDrawable *drawable, ycount = xcount % 2; /* start with even/odd depending on row */ while (j < height) { - GdkGC *gc; - if (ycount % 2) - gc = gc1; + gdk_cairo_set_source_color (cr, &color1); else - gc = gc2; + gdk_cairo_set_source_color (cr, &color2); /* If we're outside event->area, this will do nothing. * It might be mildly more efficient if we handled * the clipping ourselves, but again we're feeling lazy. */ - gdk_draw_rectangle (drawable, - gc, - TRUE, - i, j, - CHECK_SIZE, - CHECK_SIZE); + cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE); + cairo_fill (cr); j += CHECK_SIZE + SPACING; ++ycount; @@ -90,13 +78,12 @@ draw_checkerboard (GdkDrawable *drawable, ++xcount; } - g_object_unref (G_OBJECT (gc1)); - g_object_unref (G_OBJECT (gc2)); + cairo_destroy (cr); } static void render_simple (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height, MetaGradientType type, gboolean with_alpha) @@ -131,52 +118,48 @@ render_simple (GdkDrawable *drawable, draw_checkerboard (drawable, width, height); } - gdk_draw_pixbuf (drawable, - gc, - pixbuf, - 0, 0, - 0, 0, width, height, - GDK_RGB_DITHER_MAX, - 0, 0); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); g_object_unref (G_OBJECT (pixbuf)); } static void render_vertical_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_simple (drawable, gc, width, height, META_GRADIENT_VERTICAL, FALSE); + render_simple (drawable, cr, width, height, META_GRADIENT_VERTICAL, FALSE); } static void render_horizontal_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_simple (drawable, gc, width, height, META_GRADIENT_HORIZONTAL, FALSE); + render_simple (drawable, cr, width, height, META_GRADIENT_HORIZONTAL, FALSE); } static void render_diagonal_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL, FALSE); + render_simple (drawable, cr, width, height, META_GRADIENT_DIAGONAL, FALSE); } static void render_diagonal_alpha_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL, TRUE); + render_simple (drawable, cr, width, height, META_GRADIENT_DIAGONAL, TRUE); } static void render_multi (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height, MetaGradientType type) { @@ -194,13 +177,9 @@ render_multi (GdkDrawable *drawable, colors, N_COLORS, type); - gdk_draw_pixbuf (drawable, - gc, - pixbuf, - 0, 0, - 0, 0, width, height, - GDK_RGB_DITHER_NORMAL, - 0, 0); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); g_object_unref (G_OBJECT (pixbuf)); #undef N_COLORS @@ -208,31 +187,31 @@ render_multi (GdkDrawable *drawable, static void render_vertical_multi_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_multi (drawable, gc, width, height, META_GRADIENT_VERTICAL); + render_multi (drawable, cr, width, height, META_GRADIENT_VERTICAL); } static void render_horizontal_multi_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_multi (drawable, gc, width, height, META_GRADIENT_HORIZONTAL); + render_multi (drawable, cr, width, height, META_GRADIENT_HORIZONTAL); } static void render_diagonal_multi_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { - render_multi (drawable, gc, width, height, META_GRADIENT_DIAGONAL); + render_multi (drawable, cr, width, height, META_GRADIENT_DIAGONAL); } static void render_interwoven_func (GdkDrawable *drawable, - GdkGC *gc, + cairo_t *cr, int width, int height) { GdkPixbuf *pixbuf; @@ -248,13 +227,9 @@ render_interwoven_func (GdkDrawable *drawable, colors, height / 10, colors + 2, height / 14); - gdk_draw_pixbuf (drawable, - gc, - pixbuf, - 0, 0, - 0, 0, width, height, - GDK_RGB_DITHER_NORMAL, - 0, 0); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); g_object_unref (G_OBJECT (pixbuf)); } @@ -265,11 +240,24 @@ expose_callback (GtkWidget *widget, gpointer data) { RenderGradientFunc func = data; + GdkWindow *window; + GtkAllocation allocation; + GtkStyle *style; + cairo_t *cr; + + style = gtk_widget_get_style (widget); + gtk_widget_get_allocation (widget, &allocation); + + window = gtk_widget_get_window (widget); + cr = gdk_cairo_create (window); + gdk_cairo_set_source_color (cr, &style->fg[gtk_widget_get_state (widget)]); + + (* func) (window, + cr, + allocation.width, + allocation.height); - (* func) (widget->window, - widget->style->fg_gc[widget->state], - widget->allocation.width, - widget->allocation.height); + cairo_destroy (cr); return TRUE; } diff --git a/src/ui/theme.c b/src/ui/theme.c index 921a91b0..4184b1ff 100644 --- a/src/ui/theme.c +++ b/src/ui/theme.c @@ -60,6 +60,7 @@ #include <gtk/gtk.h> #include <string.h> #include <stdlib.h> +#define __USE_XOPEN #include <math.h> #define GDK_COLOR_RGBA(color) \ @@ -2912,36 +2913,6 @@ meta_draw_op_free (MetaDrawOp *op) g_free (op); } -static GdkGC* -get_gc_for_primitive (GtkWidget *widget, - GdkDrawable *drawable, - MetaColorSpec *color_spec, - const GdkRectangle *clip, - int line_width) -{ - GdkGC *gc; - GdkGCValues values; - GdkColor color; - - meta_color_spec_render (color_spec, widget, &color); - - values.foreground = color; - - gdk_rgb_find_color (gdk_drawable_get_colormap (drawable), - &values.foreground); - - values.line_width = line_width; - - gc = gdk_gc_new_with_values (drawable, &values, - GDK_GC_FOREGROUND | GDK_GC_LINE_WIDTH); - - if (clip) - gdk_gc_set_clip_rectangle (gc, - (GdkRectangle*) clip); /* const cast */ - - return gc; -} - static GdkPixbuf* apply_alpha (GdkPixbuf *pixbuf, MetaAlphaGradientSpec *spec, @@ -2978,54 +2949,6 @@ apply_alpha (GdkPixbuf *pixbuf, return pixbuf; } -static void -render_pixbuf (GdkDrawable *drawable, - const GdkRectangle *clip, - GdkPixbuf *pixbuf, - int x, - int y) -{ - /* grumble, render_to_drawable_alpha does not accept a clip - * mask, so we have to go through some BS - */ - /* FIXME once GTK 1.3.13 has been out a while we can use - * render_to_drawable() which now does alpha with clip. - * - * Though the gdk_rectangle_intersect() check may be a useful - * optimization anyway. - */ - GdkRectangle pixbuf_rect; - GdkRectangle draw_rect; - - pixbuf_rect.x = x; - pixbuf_rect.y = y; - pixbuf_rect.width = gdk_pixbuf_get_width (pixbuf); - pixbuf_rect.height = gdk_pixbuf_get_height (pixbuf); - - if (clip) - { - if (!gdk_rectangle_intersect ((GdkRectangle*)clip, - &pixbuf_rect, &draw_rect)) - return; - } - else - { - draw_rect = pixbuf_rect; - } - - gdk_draw_pixbuf (drawable, - NULL, - pixbuf, - draw_rect.x - pixbuf_rect.x, - draw_rect.y - pixbuf_rect.y, - draw_rect.x, draw_rect.y, - draw_rect.width, - draw_rect.height, - GDK_RGB_DITHER_NORMAL, - draw_rect.x - pixbuf_rect.x, - draw_rect.y - pixbuf_rect.y); -} - static GdkPixbuf* pixbuf_tile (GdkPixbuf *tile, int width, @@ -3462,6 +3385,17 @@ fill_env (MetaPositionExprEnv *env, env->theme = meta_current_theme; } +/* This code was originally rendering anti-aliased using X primitives, and + * now has been switched to draw anti-aliased using cairo. In general, the + * closest correspondence between X rendering and cairo rendering is given + * by offsetting the geometry by 0.5 pixels in both directions before rendering + * with cairo. This is because X samples at the upper left corner of the + * pixel while cairo averages over the entire pixel. However, in the cases + * where the X rendering was an exact rectangle with no "jaggies" + * we need to be a bit careful about applying the offset. We want to produce + * the exact same pixel-aligned rectangle, rather than a rectangle with + * fuzz around the edges. + */ static void meta_draw_op_draw_with_env (const MetaDrawOp *op, GtkStyle *style_gtk, @@ -3472,7 +3406,18 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, MetaRectangle rect, MetaPositionExprEnv *env) { - GdkGC *gc; + GdkColor color; + cairo_t *cr; + + cr = gdk_cairo_create (drawable); + + cairo_set_line_width (cr, 1.0); + + if (clip) + { + gdk_cairo_rectangle (cr, clip); + cairo_clip (cr); + } switch (op->type) { @@ -3480,18 +3425,19 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, { int x1, x2, y1, y2; - gc = get_gc_for_primitive (widget, drawable, - op->data.line.color_spec, - clip, - op->data.line.width); + meta_color_spec_render (op->data.line.color_spec, widget, &color); + gdk_cairo_set_source_color (cr, &color); + + if (op->data.line.width > 0) + cairo_set_line_width (cr, op->data.line.width); if (op->data.line.dash_on_length > 0 && op->data.line.dash_off_length > 0) { - gint8 dash_list[2]; + double dash_list[2]; dash_list[0] = op->data.line.dash_on_length; dash_list[1] = op->data.line.dash_off_length; - gdk_gc_set_dashes (gc, 0, dash_list, 2); + cairo_set_dash (cr, dash_list, 2, 0); } x1 = parse_x_position_unchecked (op->data.line.x1, env); @@ -3500,7 +3446,10 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, if (!op->data.line.x2 && !op->data.line.y2 && op->data.line.width==0) - gdk_draw_point (drawable, gc, x1, y1); + { + cairo_rectangle (cr, x1, y1, 1, 1); + cairo_fill (cr); + } else { if (op->data.line.x2) @@ -3513,10 +3462,34 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, else y2 = y1; - gdk_draw_line (drawable, gc, x1, y1, x2, y2); - } + /* This is one of the cases where we are matching the exact + * pixel aligned rectangle produced by X. + */ + if (y1 == y2 || x1 == x2) + { + double offset = (op->data.line.width == 0 || + op->data.line.width % 2) ? .5 : 0; + /* X includes end points for lines of width 0 */ + double line_extend = op->data.line.width == 0 ? 1. : 0.; - g_object_unref (G_OBJECT (gc)); + if (y1 == y2) + { + cairo_move_to (cr, x1, y1 + offset); + cairo_line_to (cr, x2 + line_extend, y2 + offset); + } + else + { + cairo_move_to (cr, x1 + offset, y1); + cairo_line_to (cr, x2 + offset, y2 + line_extend); + } + } + else + { + cairo_move_to (cr, x1 + .5, y1 + .5); + cairo_line_to (cr, x2 + .5, y2 + .5); + } + cairo_stroke (cr); + } } break; @@ -3524,45 +3497,69 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, { int rx, ry, rwidth, rheight; - gc = get_gc_for_primitive (widget, drawable, - op->data.rectangle.color_spec, - clip, 0); + meta_color_spec_render (op->data.rectangle.color_spec, widget, &color); + gdk_cairo_set_source_color (cr, &color); rx = parse_x_position_unchecked (op->data.rectangle.x, env); ry = parse_y_position_unchecked (op->data.rectangle.y, env); rwidth = parse_size_unchecked (op->data.rectangle.width, env); rheight = parse_size_unchecked (op->data.rectangle.height, env); - gdk_draw_rectangle (drawable, gc, - op->data.rectangle.filled, - rx, ry, rwidth, rheight); - - g_object_unref (G_OBJECT (gc)); + /* Filled and stroked rectangles are the other cases + * we pixel-align to X rasterization + */ + if (op->data.rectangle.filled) + { + cairo_rectangle (cr, rx, ry, rwidth, rheight); + cairo_fill (cr); + } + else + { + cairo_rectangle (cr, rx + .5, ry + .5, rwidth, rheight); + cairo_stroke (cr); + } } break; case META_DRAW_ARC: { int rx, ry, rwidth, rheight; + double start_angle, end_angle; + double center_x, center_y; - gc = get_gc_for_primitive (widget, drawable, - op->data.arc.color_spec, - clip, 0); + meta_color_spec_render (op->data.arc.color_spec, widget, &color); + gdk_cairo_set_source_color (cr, &color); rx = parse_x_position_unchecked (op->data.arc.x, env); ry = parse_y_position_unchecked (op->data.arc.y, env); rwidth = parse_size_unchecked (op->data.arc.width, env); rheight = parse_size_unchecked (op->data.arc.height, env); - gdk_draw_arc (drawable, - gc, - op->data.arc.filled, - rx, ry, rwidth, rheight, - op->data.arc.start_angle * (360.0 * 64.0) - - (90.0 * 64.0), /* start at 12 instead of 3 oclock */ - op->data.arc.extent_angle * (360.0 * 64.0)); + start_angle = op->data.arc.start_angle * (M_PI / 180.) + - (.25 * M_PI); /* start at 12 instead of 3 oclock */ + end_angle = start_angle + op->data.arc.extent_angle * (M_PI / 180.); + center_x = rx + (double)rwidth / 2. + .5; + center_y = ry + (double)rheight / 2. + .5; + + cairo_save (cr); + + cairo_translate (cr, center_x, center_y); + cairo_scale (cr, (double)rwidth / 2., (double)rheight / 2.); + + if (op->data.arc.extent_angle >= 0) + cairo_arc (cr, 0, 0, 1, start_angle, end_angle); + else + cairo_arc_negative (cr, 0, 0, 1, start_angle, end_angle); + + cairo_restore (cr); - g_object_unref (G_OBJECT (gc)); + if (op->data.arc.filled) + { + cairo_line_to (cr, center_x, center_y); + cairo_fill (cr); + } + else + cairo_stroke (cr); } break; @@ -3585,15 +3582,11 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, if (!needs_alpha) { - gc = get_gc_for_primitive (widget, drawable, - op->data.tint.color_spec, - clip, 0); - - gdk_draw_rectangle (drawable, gc, - TRUE, - rx, ry, rwidth, rheight); + meta_color_spec_render (op->data.tint.color_spec, widget, &color); + gdk_cairo_set_source_color (cr, &color); - g_object_unref (G_OBJECT (gc)); + cairo_rectangle (cr, rx + .5, ry + .5, rwidth, rheight); + cairo_fill (cr); } else { @@ -3604,7 +3597,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, if (pixbuf) { - render_pixbuf (drawable, clip, pixbuf, rx, ry); + gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); + cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } @@ -3627,7 +3621,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, if (pixbuf) { - render_pixbuf (drawable, clip, pixbuf, rx, ry); + gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); + cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } @@ -3656,7 +3651,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, rx = parse_x_position_unchecked (op->data.image.x, env); ry = parse_y_position_unchecked (op->data.image.y, env); - render_pixbuf (drawable, clip, pixbuf, rx, ry); + gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); + cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } @@ -3739,7 +3735,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, rx = parse_x_position_unchecked (op->data.icon.x, env); ry = parse_y_position_unchecked (op->data.icon.y, env); - render_pixbuf (drawable, clip, pixbuf, rx, ry); + gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry); + cairo_paint (cr); g_object_unref (G_OBJECT (pixbuf)); } @@ -3751,18 +3748,14 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, { int rx, ry; - gc = get_gc_for_primitive (widget, drawable, - op->data.title.color_spec, - clip, 0); + meta_color_spec_render (op->data.title.color_spec, widget, &color); + gdk_cairo_set_source_color (cr, &color); rx = parse_x_position_unchecked (op->data.title.x, env); ry = parse_y_position_unchecked (op->data.title.y, env); - gdk_draw_layout (drawable, gc, - rx, ry, - info->title_layout); - - g_object_unref (G_OBJECT (gc)); + cairo_move_to (cr, rx, ry); + pango_cairo_show_layout (cr, info->title_layout); } break; @@ -3830,6 +3823,8 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op, } break; } + + cairo_destroy (cr); } void @@ -6583,7 +6578,8 @@ draw_bg_gradient_composite (const MetaTextureSpec *bg, GDK_INTERP_BILINEAR, 255 * alpha); - render_pixbuf (drawable, clip, composited, x, y); + gdk_cairo_set_source_pixbuf (cr, composited, x, y); + cairo_paint (cr); g_object_unref (G_OBJECT (bg_pixbuf)); g_object_unref (G_OBJECT (fg_pixbuf)); diff --git a/src/ui/ui.c b/src/ui/ui.c index f15e4bcb..960e7029 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -558,6 +558,8 @@ meta_image_window_set (MetaImageWindow *iw, int x, int y) { + cairo_t *cr; + /* We use a back pixmap to avoid having to handle exposes, because * it's really too slow for large clients being minimized, etc. * and this way flicker is genuinely zero. @@ -572,6 +574,10 @@ meta_image_window_set (MetaImageWindow *iw, gdk_pixbuf_get_height (pixbuf), GDK_RGB_DITHER_NORMAL, 0, 0); + cr = gdk_cairo_create (iw->pixmap); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); gdk_window_set_back_pixmap (iw->window->window, iw->pixmap, @@ -1137,7 +1143,7 @@ meta_ui_get_pixbuf_from_pixmap (Pixmap pmap) depth = gdk_drawable_get_depth (GDK_DRAWABLE (gpmap)); if (depth <= 24) - cmap = gdk_screen_get_rgb_colormap (screen); + cmap = gdk_screen_get_system_colormap (screen); else cmap = gdk_screen_get_rgba_colormap (screen); |