[gimp] app: port GimpDisplayShell grid drawing to cairo



commit 529ce40a5d92d9c9957c7e8350ce48ffbcad033a
Author: Michael Natterer <mitch gimp org>
Date:   Wed Aug 11 13:16:55 2010 +0200

    app: port GimpDisplayShell grid drawing to cairo

 app/display/gimpdisplayshell-callbacks.c |   12 ++-
 app/display/gimpdisplayshell-draw.c      |  185 ++++++++++++++++++------------
 app/display/gimpdisplayshell-draw.h      |    2 +-
 app/display/gimpdisplayshell-handlers.c  |   12 --
 app/display/gimpdisplayshell.c           |    6 -
 app/display/gimpdisplayshell.h           |    1 -
 6 files changed, 121 insertions(+), 97 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index 52159c0..f4d592e 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -2216,6 +2216,7 @@ static void
 gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
                                         GdkEventExpose   *eevent)
 {
+  cairo_t      *cr;
   GdkRegion    *clear_region;
   GdkRegion    *image_region;
   GdkRectangle  image_rect;
@@ -2223,6 +2224,11 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
   gint          n_rects;
   gint          i;
 
+  cr = gdk_cairo_create (eevent->window);
+
+  gdk_cairo_region (cr, eevent->region);
+  cairo_clip (cr);
+
   /*  first, clear the exposed part of the region that is outside the
    *  image, which is the exposed region minus the image rectangle
    */
@@ -2286,7 +2292,9 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
   gimp_display_shell_preview_transform (shell);
 
   /* draw the grid */
-  gimp_display_shell_draw_grid (shell, eevent->region);
+  cairo_save (cr);
+  gimp_display_shell_draw_grid (shell, cr);
+  cairo_restore (cr);
 
   /* draw the guides */
   gimp_display_shell_draw_guides (shell, eevent->region);
@@ -2299,6 +2307,8 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
 
   /* restart (and recalculate) the selection boundaries */
   gimp_display_shell_selection_control (shell, GIMP_SELECTION_ON);
+
+  cairo_destroy (cr);
 }
 
 static void
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 4889a1b..0a72ca3 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -21,6 +21,7 @@
 #include <gtk/gtk.h>
 
 #include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
 #include "libgimpmath/gimpmath.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
@@ -56,11 +57,12 @@
 
 /*  local function prototypes  */
 
-static GdkGC * gimp_display_shell_get_grid_gc (GimpDisplayShell *shell,
-                                               GimpGrid         *grid);
-static GdkGC * gimp_display_shell_get_pen_gc  (GimpDisplayShell *shell,
-                                               GimpContext      *context,
-                                               GimpActiveColor   active);
+static void    gimp_display_shell_set_grid_style (GimpDisplayShell *shell,
+                                                  GimpGrid         *grid,
+                                                  cairo_t          *cr);
+static GdkGC * gimp_display_shell_get_pen_gc     (GimpDisplayShell *shell,
+                                                  GimpContext      *context,
+                                                  GimpActiveColor   active);
 
 
 /*  public functions  */
@@ -226,27 +228,25 @@ gimp_display_shell_draw_guides (GimpDisplayShell *shell,
 
 void
 gimp_display_shell_draw_grid (GimpDisplayShell *shell,
-                              const GdkRegion  *region)
+                              cairo_t          *cr)
 {
   GimpImage *image;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-  g_return_if_fail (region != NULL);
+  g_return_if_fail (cr != NULL);
 
   image = gimp_display_get_image (shell->display);
 
   if (image && gimp_display_shell_get_show_grid (shell))
     {
-      GimpCanvas   *canvas = GIMP_CANVAS (shell->canvas);
-      GimpGrid     *grid;
-      GdkRectangle  area;
-      GdkGC        *grid_gc;
-      gdouble       x, y;
-      gint          x0, x1, x2, x3;
-      gint          y0, y1, y2, y3;
-      gint          x_real, y_real;
-      gdouble       x_offset, y_offset;
-      gint          width, height;
+      GimpGrid *grid;
+      gdouble   x, y;
+      gdouble   dx1, dy1, dx2, dy2;
+      gint      x0, x1, x2, x3;
+      gint      y0, y1, y2, y3;
+      gint      x_real, y_real;
+      gdouble   x_offset, y_offset;
+      gint      width, height;
 
 #define CROSSHAIR 2
 
@@ -256,12 +256,12 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell,
 
       g_return_if_fail (grid->xspacing > 0 && grid->yspacing > 0);
 
-      gdk_region_get_clipbox (region, &area);
+      cairo_clip_extents (cr, &dx1, &dy1, &dx2, &dy2);
 
-      x1 = area.x;
-      y1 = area.y;
-      x2 = area.x + area.width;
-      y2 = area.y + area.height;
+      x1 = floor (dx1);
+      y1 = floor (dy1);
+      x2 = ceil (dx2);
+      y2 = ceil (dy2);
 
       width  = gimp_image_get_width  (image);
       height = gimp_image_get_height (image);
@@ -274,10 +274,7 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell,
       while (y_offset > 0)
         y_offset -= grid->yspacing;
 
-      grid_gc = gimp_display_shell_get_grid_gc (shell, grid);
-
-      gdk_gc_set_clip_region (grid_gc, region);
-      gimp_canvas_set_custom_gc (canvas, grid_gc);
+      gimp_display_shell_set_grid_style (shell, grid, cr);
 
       switch (grid->style)
         {
@@ -304,9 +301,10 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell,
                                                    FALSE);
 
                   if (y_real >= y1 && y_real < y2)
-                    gimp_canvas_draw_point (GIMP_CANVAS (shell->canvas),
-                                            GIMP_CANVAS_STYLE_CUSTOM,
-                                            x_real, y_real);
+                    {
+                      cairo_move_to (cr, x_real,     y_real + 0.5);
+                      cairo_line_to (cr, x_real + 1, y_real + 0.5);
+                    }
                 }
             }
           break;
@@ -337,21 +335,28 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell,
                     continue;
 
                   if (x_real >= x1 && x_real < x2)
-                    gimp_canvas_draw_line (canvas, GIMP_CANVAS_STYLE_CUSTOM,
-                                           x_real,
-                                           CLAMP (y_real - CROSSHAIR,
-                                                  y1, y2 - 1),
-                                           x_real,
-                                           CLAMP (y_real + CROSSHAIR,
-                                                  y1, y2 - 1));
+                    {
+                      cairo_move_to (cr,
+                                     x_real + 0.5,
+                                     CLAMP (y_real - CROSSHAIR,
+                                            y1, y2 - 1));
+                      cairo_line_to (cr,
+                                     x_real + 0.5,
+                                     CLAMP (y_real + CROSSHAIR,
+                                            y1, y2 - 1) + 1);
+                    }
+
                   if (y_real >= y1 && y_real < y2)
-                    gimp_canvas_draw_line (canvas, GIMP_CANVAS_STYLE_CUSTOM,
-                                           CLAMP (x_real - CROSSHAIR,
-                                                  x1, x2 - 1),
-                                           y_real,
-                                           CLAMP (x_real + CROSSHAIR,
-                                                  x1, x2 - 1),
-                                           y_real);
+                    {
+                      cairo_move_to (cr,
+                                     CLAMP (x_real - CROSSHAIR,
+                                            x1, x2 - 1),
+                                     y_real + 0.5);
+                      cairo_line_to (cr,
+                                     CLAMP (x_real + CROSSHAIR,
+                                            x1, x2 - 1) + 1,
+                                     y_real + 0.5);
+                    }
                 }
             }
           break;
@@ -376,8 +381,10 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell,
                                                FALSE);
 
               if (x_real >= x1 && x_real < x2)
-                gimp_canvas_draw_line (canvas, GIMP_CANVAS_STYLE_CUSTOM,
-                                       x_real, y0, x_real, y3 - 1);
+                {
+                  cairo_move_to (cr, x_real + 0.5, y0);
+                  cairo_line_to (cr, x_real + 0.5, y3 + 1);
+                }
             }
 
           for (y = y_offset; y < height; y += grid->yspacing)
@@ -390,14 +397,15 @@ gimp_display_shell_draw_grid (GimpDisplayShell *shell,
                                                FALSE);
 
               if (y_real >= y1 && y_real < y2)
-                gimp_canvas_draw_line (canvas, GIMP_CANVAS_STYLE_CUSTOM,
-                                       x0, y_real, x3 - 1, y_real);
+                {
+                  cairo_move_to (cr, x0,     y_real + 0.5);
+                  cairo_line_to (cr, x3 + 1, y_real + 0.5);
+                }
             }
           break;
         }
 
-      gimp_canvas_set_custom_gc (canvas, NULL);
-      gdk_gc_set_clip_region (grid_gc, NULL);
+      cairo_stroke (cr);
     }
 }
 
@@ -692,46 +700,71 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
 
 /*  private functions  */
 
-static GdkGC *
-gimp_display_shell_get_grid_gc (GimpDisplayShell *shell,
-                                GimpGrid         *grid)
+static void
+gimp_display_shell_set_grid_style (GimpDisplayShell *shell,
+                                   GimpGrid         *grid,
+                                   cairo_t          *cr)
 {
-  GdkGCValues  values;
-  GdkColor     fg, bg;
-
-  if (shell->grid_gc)
-    return shell->grid_gc;
+  cairo_set_line_width (cr, 1.0);
 
   switch (grid->style)
     {
     case GIMP_GRID_ON_OFF_DASH:
-      values.line_style = GDK_LINE_ON_OFF_DASH;
-      break;
-
     case GIMP_GRID_DOUBLE_DASH:
-      values.line_style = GDK_LINE_DOUBLE_DASH;
+      {
+        guchar *data = g_malloc0 (8 * 8 * 4);
+        guchar  fg_r, fg_g, fg_b, fg_a;
+        guchar  bg_r, bg_g, bg_b, bg_a;
+        gint    x, y;
+        guchar *d;
+        cairo_surface_t *surface;
+        static cairo_user_data_key_t data_key;
+
+        gimp_rgba_get_uchar (&grid->fgcolor, &fg_r, &fg_g, &fg_b, &fg_a);
+
+        if (grid->style == GIMP_GRID_DOUBLE_DASH)
+          gimp_rgba_get_uchar (&grid->bgcolor, &bg_r, &bg_g, &bg_b, &bg_a);
+        else
+          bg_r = bg_g = bg_b = bg_a = 0;
+
+        d = data;
+
+        for (y = 0; y < 8; y++)
+          {
+            for (x = 0; x < 8; x++)
+              {
+                if ((y < 4 && x < 4) || (y >= 4 && x >= 4))
+                  GIMP_CAIRO_ARGB32_SET_PIXEL (d, fg_r, fg_g, fg_b, fg_a);
+                else
+                  GIMP_CAIRO_ARGB32_SET_PIXEL (d, bg_r, bg_g, bg_b, bg_a);
+
+                d += 4;
+              }
+          }
+
+        surface = cairo_image_surface_create_for_data (data,
+                                                       CAIRO_FORMAT_ARGB32,
+                                                       8, 8, 8 * 4);
+        cairo_surface_set_user_data (surface, &data_key,
+                                     data, (cairo_destroy_func_t) g_free);
+
+        cairo_set_source_surface (cr, surface, 0, 0);
+        cairo_surface_destroy (surface);
+
+        cairo_pattern_set_extend (cairo_get_source (cr),
+                                  CAIRO_EXTEND_REPEAT);
+      }
       break;
 
     case GIMP_GRID_DOTS:
     case GIMP_GRID_INTERSECTIONS:
     case GIMP_GRID_SOLID:
-      values.line_style = GDK_LINE_SOLID;
+      cairo_set_source_rgb (cr,
+                            grid->fgcolor.r,
+                            grid->fgcolor.g,
+                            grid->fgcolor.b);
       break;
     }
-
-  values.join_style = GDK_JOIN_MITER;
-
-  shell->grid_gc = gdk_gc_new_with_values (gtk_widget_get_window (shell->canvas),
-                                           &values, (GDK_GC_LINE_STYLE |
-                                                     GDK_GC_JOIN_STYLE));
-
-  gimp_rgb_get_gdk_color (&grid->fgcolor, &fg);
-  gdk_gc_set_rgb_fg_color (shell->grid_gc, &fg);
-
-  gimp_rgb_get_gdk_color (&grid->bgcolor, &bg);
-  gdk_gc_set_rgb_bg_color (shell->grid_gc, &bg);
-
-  return shell->grid_gc;
 }
 
 static GdkGC *
diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h
index b756f62..1f48106 100644
--- a/app/display/gimpdisplayshell-draw.h
+++ b/app/display/gimpdisplayshell-draw.h
@@ -34,7 +34,7 @@ void   gimp_display_shell_draw_guide                 (GimpDisplayShell   *shell,
 void   gimp_display_shell_draw_guides                (GimpDisplayShell   *shell,
                                                       const GdkRegion    *region);
 void   gimp_display_shell_draw_grid                  (GimpDisplayShell   *shell,
-                                                      const GdkRegion    *region);
+                                                      cairo_t            *cr);
 void   gimp_display_shell_draw_pen                   (GimpDisplayShell   *shell,
                                                       const GimpVector2  *points,
                                                       gint                num_points,
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index 69b68e2..f494e85 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -304,12 +304,6 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell)
 
   gimp_display_shell_icon_update_stop (shell);
 
-  if (shell->grid_gc)
-    {
-      g_object_unref (shell->grid_gc);
-      shell->grid_gc = NULL;
-    }
-
   if (shell->pen_gc)
     {
       g_object_unref (shell->pen_gc);
@@ -426,12 +420,6 @@ gimp_display_shell_grid_notify_handler (GimpGrid         *grid,
                                         GParamSpec       *pspec,
                                         GimpDisplayShell *shell)
 {
-  if (shell->grid_gc)
-    {
-      g_object_unref (shell->grid_gc);
-      shell->grid_gc = NULL;
-    }
-
   gimp_display_shell_expose_full (shell);
 
   /* update item factory */
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 4bfae00..2860db3 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -938,12 +938,6 @@ gimp_display_shell_unrealize (GtkWidget *widget)
 {
   GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (widget);
 
-  if (shell->grid_gc)
-    {
-      g_object_unref (shell->grid_gc);
-      shell->grid_gc = NULL;
-    }
-
   if (shell->pen_gc)
     {
       g_object_unref (shell->pen_gc);
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 562eb4e..d4ebfc9 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -115,7 +115,6 @@ struct _GimpDisplayShell
   GList             *children;
 
   GtkWidget         *canvas;           /*  GimpCanvas widget                  */
-  GdkGC             *grid_gc;          /*  GC for grid drawing                */
   GdkGC             *pen_gc;           /*  GC for felt pen drawing            */
 
   GtkAdjustment     *hsbdata;          /*  adjustments                        */



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