[gimp] app: port GimpDisplayShell image drawing to cairo



commit f0c40d3717c9778bb40fa2bb9c1eef3ab15c6862
Author: Michael Natterer <mitch gimp org>
Date:   Fri Aug 27 19:32:16 2010 +0200

    app: port GimpDisplayShell image drawing to cairo

 app/display/gimpcanvas.c                 |   42 -------------
 app/display/gimpcanvas.h                 |   11 ----
 app/display/gimpdisplayshell-callbacks.c |    6 ++-
 app/display/gimpdisplayshell-draw.c      |    4 +-
 app/display/gimpdisplayshell-draw.h      |    1 +
 app/display/gimpdisplayshell-render.c    |   93 +++++++++++++++++-------------
 app/display/gimpdisplayshell-render.h    |    1 +
 app/display/gimpdisplayshell.c           |   12 ++--
 app/display/gimpdisplayshell.h           |    2 +-
 9 files changed, 69 insertions(+), 103 deletions(-)
---
diff --git a/app/display/gimpcanvas.c b/app/display/gimpcanvas.c
index 2004227..f068de9 100644
--- a/app/display/gimpcanvas.c
+++ b/app/display/gimpcanvas.c
@@ -258,11 +258,6 @@ gimp_canvas_gc_new (GimpCanvas      *canvas,
 
   switch (style)
     {
-    case GIMP_CANVAS_STYLE_RENDER:
-      mask |= GDK_GC_EXPOSURES;
-      values.graphics_exposures = TRUE;
-      break;
-
     case GIMP_CANVAS_STYLE_XOR_DOTTED:
     case GIMP_CANVAS_STYLE_XOR_DASHED:
       mask |= GDK_GC_LINE_STYLE;
@@ -556,43 +551,6 @@ gimp_canvas_get_layout (GimpCanvas  *canvas,
   return canvas->layout;
 }
 
-/**
- * gimp_canvas_draw_rgb:
- * @canvas:    a #GimpCanvas widget
- * @style:     one of the enumerated #GimpCanvasStyle's.
- * @x:         X coordinate of the upper left corner.
- * @y:         Y coordinate of the upper left corner.
- * @width:     width of the rectangle to be drawn.
- * @height:    height of the rectangle to be drawn.
- * @rgb_buf:   pixel data for the image to be drawn.
- * @rowstride: the rowstride in @rgb_buf.
- * @xdith:     x offset for dither alignment.
- * @ydith:     y offset for dither alignment.
- *
- * Draws an RGB image on the canvas in the specified style.
- **/
-void
-gimp_canvas_draw_rgb (GimpCanvas      *canvas,
-                      GimpCanvasStyle  style,
-                      gint             x,
-                      gint             y,
-                      gint             width,
-                      gint             height,
-                      guchar          *rgb_buf,
-                      gint             rowstride,
-                      gint             xdith,
-                      gint             ydith)
-{
-  if (! gimp_canvas_ensure_style (canvas, style))
-    return;
-
-  gdk_draw_rgb_image_dithalign (gtk_widget_get_window (GTK_WIDGET (canvas)),
-                                canvas->gc[style],
-                                x, y, width, height,
-                                GDK_RGB_DITHER_MAX,
-                                rgb_buf, rowstride, xdith, ydith);
-}
-
 void
 gimp_canvas_draw_drop_zone (GimpCanvas *canvas,
                             cairo_t    *cr)
diff --git a/app/display/gimpcanvas.h b/app/display/gimpcanvas.h
index 7c7ef45..6373ff9 100644
--- a/app/display/gimpcanvas.h
+++ b/app/display/gimpcanvas.h
@@ -24,7 +24,6 @@
 
 typedef enum
 {
-  GIMP_CANVAS_STYLE_RENDER,
   GIMP_CANVAS_STYLE_XOR,
   GIMP_CANVAS_STYLE_XOR_DASHED,
   GIMP_CANVAS_STYLE_XOR_DOTTED,
@@ -116,16 +115,6 @@ void         gimp_canvas_draw_segments     (GimpCanvas         *canvas,
 PangoLayout *gimp_canvas_get_layout        (GimpCanvas         *canvas,
                                             const gchar        *format,
                                             ...) G_GNUC_PRINTF (2, 3);
-void         gimp_canvas_draw_rgb          (GimpCanvas         *canvas,
-                                            GimpCanvasStyle     style,
-                                            gint                x,
-                                            gint                y,
-                                            gint                width,
-                                            gint                height,
-                                            guchar             *rgb_buf,
-                                            gint                rowstride,
-                                            gint                xdith,
-                                            gint                ydith);
 void         gimp_canvas_draw_drop_zone    (GimpCanvas         *canvas,
                                             cairo_t            *cr);
 
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index 49e5e75..d8df28b 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -2273,13 +2273,17 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
     {
       gdk_region_get_rectangles (image_region, &rects, &n_rects);
 
+      cairo_save (cr);
+
       for (i = 0; i < n_rects; i++)
-        gimp_display_shell_draw_area (shell,
+        gimp_display_shell_draw_area (shell, cr,
                                       rects[i].x,
                                       rects[i].y,
                                       rects[i].width,
                                       rects[i].height);
 
+      cairo_restore (cr);
+
       g_free (rects);
     }
 
diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c
index 28bfc00..d900412 100644
--- a/app/display/gimpdisplayshell-draw.c
+++ b/app/display/gimpdisplayshell-draw.c
@@ -692,6 +692,7 @@ gimp_display_shell_draw_cursor (GimpDisplayShell *shell,
 
 void
 gimp_display_shell_draw_area (GimpDisplayShell *shell,
+                              cairo_t          *cr,
                               gint              x,
                               gint              y,
                               gint              w,
@@ -703,6 +704,7 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (gimp_display_get_image (shell->display));
+  g_return_if_fail (cr != NULL);
 
   x2 = x + w;
   y2 = y + h;
@@ -732,7 +734,7 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
                                                      &disp_xoffset,
                                                      &disp_yoffset);
 
-          gimp_display_shell_render (shell,
+          gimp_display_shell_render (shell, cr,
                                      j - disp_xoffset,
                                      i - disp_yoffset,
                                      dx, dy,
diff --git a/app/display/gimpdisplayshell-draw.h b/app/display/gimpdisplayshell-draw.h
index 9ad1e62..5f51ba2 100644
--- a/app/display/gimpdisplayshell-draw.h
+++ b/app/display/gimpdisplayshell-draw.h
@@ -67,6 +67,7 @@ void   gimp_display_shell_draw_vectors               (GimpDisplayShell   *shell)
 void   gimp_display_shell_draw_cursor                (GimpDisplayShell   *shell,
                                                       cairo_t            *cr);
 void   gimp_display_shell_draw_area                  (GimpDisplayShell   *shell,
+                                                      cairo_t            *cr,
                                                       gint                x,
                                                       gint                y,
                                                       gint                w,
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index 956c424..b229ed0 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -76,7 +76,6 @@ struct _RenderInfo
   gint              src_y;
   gint              dest_bpp;
   gint              dest_bpl;
-  gint              dest_width;
 
   gint              zoom_quality;
 
@@ -195,6 +194,7 @@ static const guchar * render_image_tile_fault    (RenderInfo         *info);
 
 
 static void  gimp_display_shell_render_highlight (GimpDisplayShell   *shell,
+                                                  RenderInfo         *info,
                                                   gint                x,
                                                   gint                y,
                                                   gint                w,
@@ -213,6 +213,7 @@ static void  gimp_display_shell_render_mask      (GimpDisplayShell   *shell,
 
 void
 gimp_display_shell_render (GimpDisplayShell   *shell,
+                           cairo_t            *cr,
                            gint                x,
                            gint                y,
                            gint                w,
@@ -227,6 +228,7 @@ gimp_display_shell_render (GimpDisplayShell   *shell,
   gint            offset_y;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+  g_return_if_fail (cr != NULL);
   g_return_if_fail (w > 0 && h > 0);
 
   image = gimp_display_get_image (shell->display);
@@ -239,16 +241,15 @@ gimp_display_shell_render (GimpDisplayShell   *shell,
   /* Initialize RenderInfo with values that don't change during the
    * call of this function.
    */
-  info.shell      = shell;
+  info.shell    = shell;
 
-  info.x          = x + offset_x;
-  info.y          = y + offset_y;
-  info.w          = w;
-  info.h          = h;
+  info.x        = x + offset_x;
+  info.y        = y + offset_y;
+  info.w        = w;
+  info.h        = h;
 
-  info.dest_bpp   = 3;
-  info.dest_bpl   = info.dest_bpp * GIMP_DISPLAY_RENDER_BUF_WIDTH;
-  info.dest_width = info.dest_bpp * info.w;
+  info.dest_bpp = 4;
+  info.dest_bpl = cairo_image_surface_get_stride (shell->render_surface);
 
   switch (shell->display->config->zoom_quality)
     {
@@ -293,17 +294,19 @@ gimp_display_shell_render (GimpDisplayShell   *shell,
     }
 
   /*  apply filters to the rendered projection  */
+#if 0
   if (shell->filter_stack)
     gimp_color_display_stack_convert (shell->filter_stack,
                                       shell->render_buf,
                                       w, h,
                                       3,
                                       3 * GIMP_DISPLAY_RENDER_BUF_WIDTH);
+#endif
 
   /*  dim pixels outside the highlighted rectangle  */
   if (highlight)
     {
-      gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
+      gimp_display_shell_render_highlight (shell, &info, x, y, w, h, highlight);
     }
   else if (shell->mask)
     {
@@ -315,6 +318,8 @@ gimp_display_shell_render (GimpDisplayShell   *shell,
       gimp_display_shell_render_mask (shell, &info);
     }
 
+  cairo_surface_mark_dirty (shell->render_surface);
+
   /*  put it to the screen  */
   {
     gint disp_xoffset, disp_yoffset;
@@ -322,35 +327,43 @@ gimp_display_shell_render (GimpDisplayShell   *shell,
     gimp_display_shell_scroll_get_disp_offset (shell,
 					       &disp_xoffset, &disp_yoffset);
 
-    gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas),
-			  GIMP_CANVAS_STYLE_RENDER,
-			  x + disp_xoffset, y + disp_yoffset,
-			  w, h,
-			  shell->render_buf,
-			  3 * GIMP_DISPLAY_RENDER_BUF_WIDTH,
-			  offset_x, offset_y);
+    cairo_set_source_surface (cr, shell->render_surface,
+                              x + disp_xoffset, y + disp_yoffset);
+    cairo_rectangle (cr, x + disp_xoffset, y + disp_yoffset, w, h);
+    cairo_fill (cr);
   }
 }
 
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define CAIRO_RGB24_RED_PIXEL   2
+#define CAIRO_RGB24_GREEN_PIXEL 1
+#define CAIRO_RGB24_BLUE_PIXEL  0
+#else
+#define CAIRO_RGB24_RED_PIXEL   1
+#define CAIRO_RGB24_GREEN_PIXEL 2
+#define CAIRO_RGB24_BLUE_PIXEL  3
+#endif
+
 #define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
 { \
-  buf[3 * (x) + 0] >>= 1; \
-  buf[3 * (x) + 1] >>= 1; \
-  buf[3 * (x) + 2] >>= 1; \
+  buf[4 * (x) + CAIRO_RGB24_RED_PIXEL]   >>= 1; \
+  buf[4 * (x) + CAIRO_RGB24_GREEN_PIXEL] >>= 1; \
+  buf[4 * (x) + CAIRO_RGB24_BLUE_PIXEL]  >>= 1; \
 }
 
 /*  This function highlights the given area by dimming all pixels outside. */
 
 static void
 gimp_display_shell_render_highlight (GimpDisplayShell   *shell,
+                                     RenderInfo         *info,
                                      gint                x,
                                      gint                y,
                                      gint                w,
                                      gint                h,
                                      const GdkRectangle *highlight)
 {
-  guchar       *buf  = shell->render_buf;
+  guchar       *buf = cairo_image_surface_get_data (shell->render_surface);
   GdkRectangle  rect;
   gint          offset_x;
   gint          offset_y;
@@ -373,7 +386,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell   *shell,
           for (x = 0; x < w; x++)
             GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
-          buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
+          buf += info->dest_bpl;
         }
 
       for ( ; y < rect.y + rect.height; y++)
@@ -384,7 +397,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell   *shell,
           for (x += rect.width; x < w; x++)
             GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
-          buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
+          buf += info->dest_bpl;
         }
 
       for ( ; y < h; y++)
@@ -392,7 +405,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell   *shell,
           for (x = 0; x < w; x++)
             GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
-          buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
+          buf += info->dest_bpl;
         }
     }
   else
@@ -402,7 +415,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell   *shell,
           for (x = 0; x < w; x++)
             GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
 
-          buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
+          buf += info->dest_bpl;
         }
     }
 }
@@ -429,35 +442,35 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
       switch (shell->mask_color)
         {
         case GIMP_RED_CHANNEL:
-          for (x = info->x; x < xe; x++, src++, dest += 3)
+          for (x = info->x; x < xe; x++, src++, dest += info->dest_bpp)
             {
               if (*src & 0x80)
                 continue;
 
-              dest[1] = dest[1] >> 2;
-              dest[2] = dest[2] >> 2;
+              dest[CAIRO_RGB24_GREEN_PIXEL] >>= 2;
+              dest[CAIRO_RGB24_BLUE_PIXEL]  >>= 2;
             }
           break;
 
         case GIMP_GREEN_CHANNEL:
-          for (x = info->x; x < xe; x++, src++, dest += 3)
+          for (x = info->x; x < xe; x++, src++, dest += info->dest_bpp)
             {
               if (*src & 0x80)
                 continue;
 
-              dest[0] = dest[0] >> 2;
-              dest[2] = dest[2] >> 2;
+              dest[CAIRO_RGB24_RED_PIXEL]  >>= 2;
+              dest[CAIRO_RGB24_BLUE_PIXEL] >>= 2;
             }
           break;
 
         case GIMP_BLUE_CHANNEL:
-          for (x = info->x; x < xe; x++, src++, dest += 3)
+          for (x = info->x; x < xe; x++, src++, dest += info->dest_bpp)
             {
               if (*src & 0x80)
                 continue;
 
-              dest[0] = dest[0] >> 2;
-              dest[1] = dest[1] >> 2;
+              dest[CAIRO_RGB24_RED_PIXEL]   >>= 2;
+              dest[CAIRO_RGB24_GREEN_PIXEL] >>= 2;
             }
           break;
 
@@ -504,7 +517,7 @@ render_image_gray_a (RenderInfo *info)
 
       dark_light = (y >> check_shift) + (info->x >> check_shift);
 
-      for (x = info->x; x < xe; x++, src += 2, dest += 3)
+      for (x = info->x; x < xe; x++, src += 2, dest += info->dest_bpp)
         {
           guint v;
 
@@ -513,7 +526,7 @@ render_image_gray_a (RenderInfo *info)
           else
             v = ((src[0] << 8) + check_light * (256 - src[1])) >> 8;
 
-          dest[0] = dest[1] = dest[2] = v;
+          GIMP_CAIRO_RGB24_SET_PIXEL (dest, v, v, v);
 
           if (((x + 1) & check_mod) == 0)
             dark_light += 1;
@@ -553,7 +566,7 @@ render_image_rgb_a (RenderInfo *info)
 
       dark_light = (y >> check_shift) + (info->x >> check_shift);
 
-      for (x = info->x; x < xe; x++, src += 4, dest += 3)
+      for (x = info->x; x < xe; x++, src += 4, dest += info->dest_bpp)
         {
           guint r, g, b;
 
@@ -570,9 +583,7 @@ render_image_rgb_a (RenderInfo *info)
               b = ((src[2] << 8) + check_light * (256 - src[3])) >> 8;
             }
 
-          dest[0] = r;
-          dest[1] = g;
-          dest[2] = b;
+          GIMP_CAIRO_RGB24_SET_PIXEL (dest, r, g, b);
 
           if (((x + 1) & check_mod) == 0)
             dark_light += 1;
@@ -605,7 +616,7 @@ gimp_display_shell_render_info_scale (RenderInfo       *info,
   /* We must reset info->dest because this member is modified in render
    * functions.
    */
-  info->dest     = shell->render_buf;
+  info->dest     = cairo_image_surface_get_data (shell->render_surface);
 
   info->scalex   = shell->scale_x * (1 << level);
   info->scaley   = shell->scale_y * (1 << level);
diff --git a/app/display/gimpdisplayshell-render.h b/app/display/gimpdisplayshell-render.h
index f5e14fa..f60ff65 100644
--- a/app/display/gimpdisplayshell-render.h
+++ b/app/display/gimpdisplayshell-render.h
@@ -27,6 +27,7 @@ void   gimp_display_shell_render_init (Gimp               *gimp);
 void   gimp_display_shell_render_exit (Gimp               *gimp);
 
 void   gimp_display_shell_render      (GimpDisplayShell   *shell,
+                                       cairo_t            *cr,
                                        gint                x,
                                        gint                y,
                                        gint                w,
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index c72310a..d8a3870 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -289,9 +289,9 @@ gimp_display_shell_init (GimpDisplayShell *shell)
   shell->x_src_dec   = 1;
   shell->y_src_dec   = 1;
 
-  shell->render_buf = g_new (guchar,
-                             GIMP_DISPLAY_RENDER_BUF_WIDTH  *
-                             GIMP_DISPLAY_RENDER_BUF_HEIGHT * 3);
+  shell->render_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+                                                      GIMP_DISPLAY_RENDER_BUF_WIDTH,
+                                                      GIMP_DISPLAY_RENDER_BUF_HEIGHT);
 
   shell->icon_size  = 32;
 
@@ -868,10 +868,10 @@ gimp_display_shell_destroy (GtkObject *object)
       shell->filter_idle_id = 0;
     }
 
-  if (shell->render_buf)
+  if (shell->render_surface)
     {
-      g_free (shell->render_buf);
-      shell->render_buf = NULL;
+      cairo_surface_destroy (shell->render_surface);
+      shell->render_surface = NULL;
     }
 
   if (shell->highlight)
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index bfd4d98..63a6e24 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -131,7 +131,7 @@ struct _GimpDisplayShell
 
   GtkWidget         *statusbar;        /*  statusbar                          */
 
-  guchar            *render_buf;       /*  buffer for rendering the image     */
+  cairo_surface_t   *render_surface;   /*  buffer for rendering the image     */
 
   guint              title_idle_id;    /*  title update idle ID               */
   gchar             *title;            /*  current title                      */



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