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)
{
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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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,

View File

@ -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,

View File

@ -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);

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 (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,

View File

@ -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)

View File

@ -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 */