diff --git a/app/display/gimpcanvas.c b/app/display/gimpcanvas.c index 20042274a7..f068de9e59 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 7c7ef45b28..6373ff99a0 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 49e5e75690..d8df28b58b 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 28bfc0037c..d900412d0d 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 9ad1e627e1..5f51ba2b6e 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 956c4243a8..b229ed0c58 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 f5e14face3..f60ff65683 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 c72310aa1e..d8a38703b4 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 bfd4d9816c..63a6e240a9 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 */