[metacity] Replace GDK drawing API with cairo



commit 3608ff90798cbb6c8d88be902abd56f1a4b16bc0
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Aug 18 03:09:50 2010 +0200

    Replace GDK drawing API with cairo
    
    The GDK drawing API was deprecated/removed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=627245

 src/ui/draw-workspace.c |   19 ++---
 src/ui/frames.c         |  121 ++++++++++++++---------
 src/ui/tabpopup.c       |   97 +++++++++++-------
 src/ui/testgradient.c   |  134 +++++++++++--------------
 src/ui/theme.c          |  254 +++++++++++++++++++++++------------------------
 src/ui/ui.c             |    8 ++-
 6 files changed, 331 insertions(+), 302 deletions(-)
---
diff --git a/src/ui/draw-workspace.c b/src/ui/draw-workspace.c
index 72daf67..9dc491f 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, &gtk_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 7945a0c..d8fe3cd 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 5cc4d71..544bb01 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 02c1364..89d0d22 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 921a91b..4184b1f 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 f15e4bc..960e702 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);
   



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]