app: port GimpDisplayShell image drawing to cairo

This commit is contained in:
Michael Natterer 2010-08-27 19:32:16 +02:00
parent 90655d8744
commit f0c40d3717
9 changed files with 69 additions and 103 deletions

View File

@ -258,11 +258,6 @@ gimp_canvas_gc_new (GimpCanvas *canvas,
switch (style) 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_DOTTED:
case GIMP_CANVAS_STYLE_XOR_DASHED: case GIMP_CANVAS_STYLE_XOR_DASHED:
mask |= GDK_GC_LINE_STYLE; mask |= GDK_GC_LINE_STYLE;
@ -556,43 +551,6 @@ gimp_canvas_get_layout (GimpCanvas *canvas,
return canvas->layout; 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 void
gimp_canvas_draw_drop_zone (GimpCanvas *canvas, gimp_canvas_draw_drop_zone (GimpCanvas *canvas,
cairo_t *cr) cairo_t *cr)

View File

@ -24,7 +24,6 @@
typedef enum typedef enum
{ {
GIMP_CANVAS_STYLE_RENDER,
GIMP_CANVAS_STYLE_XOR, GIMP_CANVAS_STYLE_XOR,
GIMP_CANVAS_STYLE_XOR_DASHED, GIMP_CANVAS_STYLE_XOR_DASHED,
GIMP_CANVAS_STYLE_XOR_DOTTED, GIMP_CANVAS_STYLE_XOR_DOTTED,
@ -116,16 +115,6 @@ void gimp_canvas_draw_segments (GimpCanvas *canvas,
PangoLayout *gimp_canvas_get_layout (GimpCanvas *canvas, PangoLayout *gimp_canvas_get_layout (GimpCanvas *canvas,
const gchar *format, const gchar *format,
...) G_GNUC_PRINTF (2, 3); ...) 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, void gimp_canvas_draw_drop_zone (GimpCanvas *canvas,
cairo_t *cr); cairo_t *cr);

View File

@ -2273,13 +2273,17 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
{ {
gdk_region_get_rectangles (image_region, &rects, &n_rects); gdk_region_get_rectangles (image_region, &rects, &n_rects);
cairo_save (cr);
for (i = 0; i < n_rects; i++) 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].x,
rects[i].y, rects[i].y,
rects[i].width, rects[i].width,
rects[i].height); rects[i].height);
cairo_restore (cr);
g_free (rects); g_free (rects);
} }

View File

@ -692,6 +692,7 @@ gimp_display_shell_draw_cursor (GimpDisplayShell *shell,
void void
gimp_display_shell_draw_area (GimpDisplayShell *shell, gimp_display_shell_draw_area (GimpDisplayShell *shell,
cairo_t *cr,
gint x, gint x,
gint y, gint y,
gint w, 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_IS_DISPLAY_SHELL (shell));
g_return_if_fail (gimp_display_get_image (shell->display)); g_return_if_fail (gimp_display_get_image (shell->display));
g_return_if_fail (cr != NULL);
x2 = x + w; x2 = x + w;
y2 = y + h; y2 = y + h;
@ -732,7 +734,7 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
&disp_xoffset, &disp_xoffset,
&disp_yoffset); &disp_yoffset);
gimp_display_shell_render (shell, gimp_display_shell_render (shell, cr,
j - disp_xoffset, j - disp_xoffset,
i - disp_yoffset, i - disp_yoffset,
dx, dy, dx, dy,

View File

@ -67,6 +67,7 @@ void gimp_display_shell_draw_vectors (GimpDisplayShell *shell)
void gimp_display_shell_draw_cursor (GimpDisplayShell *shell, void gimp_display_shell_draw_cursor (GimpDisplayShell *shell,
cairo_t *cr); cairo_t *cr);
void gimp_display_shell_draw_area (GimpDisplayShell *shell, void gimp_display_shell_draw_area (GimpDisplayShell *shell,
cairo_t *cr,
gint x, gint x,
gint y, gint y,
gint w, gint w,

View File

@ -76,7 +76,6 @@ struct _RenderInfo
gint src_y; gint src_y;
gint dest_bpp; gint dest_bpp;
gint dest_bpl; gint dest_bpl;
gint dest_width;
gint zoom_quality; 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, static void gimp_display_shell_render_highlight (GimpDisplayShell *shell,
RenderInfo *info,
gint x, gint x,
gint y, gint y,
gint w, gint w,
@ -213,6 +213,7 @@ static void gimp_display_shell_render_mask (GimpDisplayShell *shell,
void void
gimp_display_shell_render (GimpDisplayShell *shell, gimp_display_shell_render (GimpDisplayShell *shell,
cairo_t *cr,
gint x, gint x,
gint y, gint y,
gint w, gint w,
@ -227,6 +228,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gint offset_y; gint offset_y;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (cr != NULL);
g_return_if_fail (w > 0 && h > 0); g_return_if_fail (w > 0 && h > 0);
image = gimp_display_get_image (shell->display); 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 /* Initialize RenderInfo with values that don't change during the
* call of this function. * call of this function.
*/ */
info.shell = shell; info.shell = shell;
info.x = x + offset_x; info.x = x + offset_x;
info.y = y + offset_y; info.y = y + offset_y;
info.w = w; info.w = w;
info.h = h; info.h = h;
info.dest_bpp = 3; info.dest_bpp = 4;
info.dest_bpl = info.dest_bpp * GIMP_DISPLAY_RENDER_BUF_WIDTH; info.dest_bpl = cairo_image_surface_get_stride (shell->render_surface);
info.dest_width = info.dest_bpp * info.w;
switch (shell->display->config->zoom_quality) switch (shell->display->config->zoom_quality)
{ {
@ -293,17 +294,19 @@ gimp_display_shell_render (GimpDisplayShell *shell,
} }
/* apply filters to the rendered projection */ /* apply filters to the rendered projection */
#if 0
if (shell->filter_stack) if (shell->filter_stack)
gimp_color_display_stack_convert (shell->filter_stack, gimp_color_display_stack_convert (shell->filter_stack,
shell->render_buf, shell->render_buf,
w, h, w, h,
3, 3,
3 * GIMP_DISPLAY_RENDER_BUF_WIDTH); 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH);
#endif
/* dim pixels outside the highlighted rectangle */ /* dim pixels outside the highlighted rectangle */
if (highlight) 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) else if (shell->mask)
{ {
@ -315,6 +318,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gimp_display_shell_render_mask (shell, &info); gimp_display_shell_render_mask (shell, &info);
} }
cairo_surface_mark_dirty (shell->render_surface);
/* put it to the screen */ /* put it to the screen */
{ {
gint disp_xoffset, disp_yoffset; gint disp_xoffset, disp_yoffset;
@ -322,35 +327,43 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gimp_display_shell_scroll_get_disp_offset (shell, gimp_display_shell_scroll_get_disp_offset (shell,
&disp_xoffset, &disp_yoffset); &disp_xoffset, &disp_yoffset);
gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), cairo_set_source_surface (cr, shell->render_surface,
GIMP_CANVAS_STYLE_RENDER, x + disp_xoffset, y + disp_yoffset);
x + disp_xoffset, y + disp_yoffset, cairo_rectangle (cr, x + disp_xoffset, y + disp_yoffset, w, h);
w, h, cairo_fill (cr);
shell->render_buf,
3 * GIMP_DISPLAY_RENDER_BUF_WIDTH,
offset_x, offset_y);
} }
} }
#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) \ #define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
{ \ { \
buf[3 * (x) + 0] >>= 1; \ buf[4 * (x) + CAIRO_RGB24_RED_PIXEL] >>= 1; \
buf[3 * (x) + 1] >>= 1; \ buf[4 * (x) + CAIRO_RGB24_GREEN_PIXEL] >>= 1; \
buf[3 * (x) + 2] >>= 1; \ buf[4 * (x) + CAIRO_RGB24_BLUE_PIXEL] >>= 1; \
} }
/* This function highlights the given area by dimming all pixels outside. */ /* This function highlights the given area by dimming all pixels outside. */
static void static void
gimp_display_shell_render_highlight (GimpDisplayShell *shell, gimp_display_shell_render_highlight (GimpDisplayShell *shell,
RenderInfo *info,
gint x, gint x,
gint y, gint y,
gint w, gint w,
gint h, gint h,
const GdkRectangle *highlight) const GdkRectangle *highlight)
{ {
guchar *buf = shell->render_buf; guchar *buf = cairo_image_surface_get_data (shell->render_surface);
GdkRectangle rect; GdkRectangle rect;
gint offset_x; gint offset_x;
gint offset_y; gint offset_y;
@ -373,7 +386,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, 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++) 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++) for (x += rect.width; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x) GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH; buf += info->dest_bpl;
} }
for ( ; y < h; y++) for ( ; y < h; y++)
@ -392,7 +405,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x) GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH; buf += info->dest_bpl;
} }
} }
else else
@ -402,7 +415,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, 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) switch (shell->mask_color)
{ {
case GIMP_RED_CHANNEL: 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) if (*src & 0x80)
continue; continue;
dest[1] = dest[1] >> 2; dest[CAIRO_RGB24_GREEN_PIXEL] >>= 2;
dest[2] = dest[2] >> 2; dest[CAIRO_RGB24_BLUE_PIXEL] >>= 2;
} }
break; break;
case GIMP_GREEN_CHANNEL: 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) if (*src & 0x80)
continue; continue;
dest[0] = dest[0] >> 2; dest[CAIRO_RGB24_RED_PIXEL] >>= 2;
dest[2] = dest[2] >> 2; dest[CAIRO_RGB24_BLUE_PIXEL] >>= 2;
} }
break; break;
case GIMP_BLUE_CHANNEL: 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) if (*src & 0x80)
continue; continue;
dest[0] = dest[0] >> 2; dest[CAIRO_RGB24_RED_PIXEL] >>= 2;
dest[1] = dest[1] >> 2; dest[CAIRO_RGB24_GREEN_PIXEL] >>= 2;
} }
break; break;
@ -504,7 +517,7 @@ render_image_gray_a (RenderInfo *info)
dark_light = (y >> check_shift) + (info->x >> check_shift); 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; guint v;
@ -513,7 +526,7 @@ render_image_gray_a (RenderInfo *info)
else else
v = ((src[0] << 8) + check_light * (256 - src[1])) >> 8; 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) if (((x + 1) & check_mod) == 0)
dark_light += 1; dark_light += 1;
@ -553,7 +566,7 @@ render_image_rgb_a (RenderInfo *info)
dark_light = (y >> check_shift) + (info->x >> check_shift); 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; guint r, g, b;
@ -570,9 +583,7 @@ render_image_rgb_a (RenderInfo *info)
b = ((src[2] << 8) + check_light * (256 - src[3])) >> 8; b = ((src[2] << 8) + check_light * (256 - src[3])) >> 8;
} }
dest[0] = r; GIMP_CAIRO_RGB24_SET_PIXEL (dest, r, g, b);
dest[1] = g;
dest[2] = b;
if (((x + 1) & check_mod) == 0) if (((x + 1) & check_mod) == 0)
dark_light += 1; 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 /* We must reset info->dest because this member is modified in render
* functions. * functions.
*/ */
info->dest = shell->render_buf; info->dest = cairo_image_surface_get_data (shell->render_surface);
info->scalex = shell->scale_x * (1 << level); info->scalex = shell->scale_x * (1 << level);
info->scaley = shell->scale_y * (1 << level); info->scaley = shell->scale_y * (1 << level);

View File

@ -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_exit (Gimp *gimp);
void gimp_display_shell_render (GimpDisplayShell *shell, void gimp_display_shell_render (GimpDisplayShell *shell,
cairo_t *cr,
gint x, gint x,
gint y, gint y,
gint w, gint w,

View File

@ -289,9 +289,9 @@ gimp_display_shell_init (GimpDisplayShell *shell)
shell->x_src_dec = 1; shell->x_src_dec = 1;
shell->y_src_dec = 1; shell->y_src_dec = 1;
shell->render_buf = g_new (guchar, shell->render_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_BUF_WIDTH,
GIMP_DISPLAY_RENDER_BUF_HEIGHT * 3); GIMP_DISPLAY_RENDER_BUF_HEIGHT);
shell->icon_size = 32; shell->icon_size = 32;
@ -868,10 +868,10 @@ gimp_display_shell_destroy (GtkObject *object)
shell->filter_idle_id = 0; shell->filter_idle_id = 0;
} }
if (shell->render_buf) if (shell->render_surface)
{ {
g_free (shell->render_buf); cairo_surface_destroy (shell->render_surface);
shell->render_buf = NULL; shell->render_surface = NULL;
} }
if (shell->highlight) if (shell->highlight)

View File

@ -131,7 +131,7 @@ struct _GimpDisplayShell
GtkWidget *statusbar; /* statusbar */ 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 */ guint title_idle_id; /* title update idle ID */
gchar *title; /* current title */ gchar *title; /* current title */