[gimp] app/display: implement drawing of selection mask
- From: Sven Neumann <neo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app/display: implement drawing of selection mask
- Date: Wed, 29 Sep 2010 18:38:58 +0000 (UTC)
commit a7413bd784335f474f28cfc962d0d67517089102
Author: Sven Neumann <sven gimp org>
Date: Tue Sep 28 23:49:22 2010 +0200
app/display: implement drawing of selection mask
Use cairo_mask_surface() to render the selection mask (as used by
the foreground selection tool).
app/display/gimpdisplayshell-render.c | 144 +++++++++++++++------------------
app/display/gimpdisplayshell-render.h | 12 ++--
app/display/gimpdisplayshell.c | 10 ++-
app/display/gimpdisplayshell.h | 1 +
4 files changed, 82 insertions(+), 85 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index 6d85047..c309731 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -105,14 +105,11 @@ static void gimp_display_shell_render_info_init (RenderInfo *info,
/* Render Image functions */
-static void render_image_rgb_a (RenderInfo *info);
-static void render_image_gray_a (RenderInfo *info);
+static void render_image_alpha (RenderInfo *info);
+static void render_image_gray_a (RenderInfo *info);
+static void render_image_rgb_a (RenderInfo *info);
-static const guchar * render_image_tile_fault (RenderInfo *info);
-
-
-static void gimp_display_shell_render_mask (GimpDisplayShell *shell,
- RenderInfo *info);
+static const guchar * render_image_tile_fault (RenderInfo *info);
/*****************************************************************/
@@ -132,9 +129,9 @@ gimp_display_shell_render (GimpDisplayShell *shell,
{
GimpProjection *projection;
GimpImage *image;
+ TileManager *tiles;
RenderInfo info;
GimpImageType type;
- TileManager *tiles;
gint level;
gboolean premult;
@@ -143,7 +140,6 @@ gimp_display_shell_render (GimpDisplayShell *shell,
g_return_if_fail (w > 0 && h > 0);
image = gimp_display_get_image (shell->display);
-
projection = gimp_image_get_projection (image);
/* setup RenderInfo for rendering a GimpProjection level. */
@@ -183,49 +179,80 @@ gimp_display_shell_render (GimpDisplayShell *shell,
3 * GIMP_DISPLAY_RENDER_BUF_WIDTH);
#endif
-#if 0
+ cairo_surface_mark_dirty (shell->render_surface);
+
if (shell->mask)
{
- TileManager *tiles = gimp_drawable_get_tiles (shell->mask);
+ if (! shell->mask_surface)
+ {
+ shell->mask_surface =
+ cairo_image_surface_create (CAIRO_FORMAT_A8,
+ GIMP_DISPLAY_RENDER_BUF_WIDTH,
+ GIMP_DISPLAY_RENDER_BUF_HEIGHT);
+ }
+
+ tiles = gimp_drawable_get_tiles (shell->mask);
/* The mask does not (yet) have an image pyramid, use 0 as level, */
- gimp_display_shell_render_info_scale (&info, shell, tiles, 0, FALSE);
+ gimp_display_shell_render_info_init (&info,
+ shell, x, y, w, h,
+ shell->mask_surface,
+ tiles, 0, FALSE);
- gimp_display_shell_render_mask (shell, &info);
- }
-#endif
+ render_image_alpha (&info);
- cairo_surface_mark_dirty (shell->render_surface);
+ cairo_surface_mark_dirty (shell->mask_surface);
+ }
/* put it to the screen */
{
gint disp_xoffset, disp_yoffset;
+ cairo_save (cr);
+
gimp_display_shell_scroll_get_disp_offset (shell,
&disp_xoffset, &disp_yoffset);
cairo_rectangle (cr, x + disp_xoffset, y + disp_yoffset, w, h);
+ cairo_clip (cr);
+
cairo_set_source_surface (cr, shell->render_surface,
x + disp_xoffset, y + disp_yoffset);
- cairo_fill (cr);
+ cairo_paint (cr);
+
+ if (shell->mask)
+ {
+ /* FIXME: mask_color should be GimpRGB */
+ switch (shell->mask_color)
+ {
+ case GIMP_RED_CHANNEL:
+ cairo_set_source_rgba (cr, 1, 0, 0, 0.5);
+ break;
+
+ case GIMP_GREEN_CHANNEL:
+ cairo_set_source_rgba (cr, 0, 1, 0, 0.5);
+ break;
+
+ case GIMP_BLUE_CHANNEL:
+ cairo_set_source_rgba (cr, 0, 0, 1, 0.5);
+ break;
+
+ default:
+ g_warn_if_reached ();
+ return;
+ }
+
+ cairo_mask_surface (cr, shell->mask_surface,
+ x + disp_xoffset, y + disp_yoffset);
+ }
+
+ cairo_restore (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
-
-
+/* render a GRAY tile to an A8 cairo surface */
static void
-gimp_display_shell_render_mask (GimpDisplayShell *shell,
- RenderInfo *info)
+render_image_alpha (RenderInfo *info)
{
gint y, ye;
gint x, xe;
@@ -234,7 +261,7 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
ye = info->y + info->h;
xe = info->x + info->w;
- info->dy = info->dy_start;
+ info->dy = info->dy_start;
info->src = render_image_tile_fault (info);
while (TRUE)
@@ -242,43 +269,9 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
const guchar *src = info->src;
guchar *dest = info->dest;
- switch (shell->mask_color)
+ for (x = info->x; x < xe; x++, src++, dest++)
{
- case GIMP_RED_CHANNEL:
- for (x = info->x; x < xe; x++, src++, dest += 4)
- {
- if (*src & 0x80)
- continue;
-
- 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 += 4)
- {
- if (*src & 0x80)
- continue;
-
- 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 += 4)
- {
- if (*src & 0x80)
- continue;
-
- dest[CAIRO_RGB24_RED_PIXEL] >>= 2;
- dest[CAIRO_RGB24_GREEN_PIXEL] >>= 2;
- }
- break;
-
- default:
- break;
+ *dest = *src;
}
if (++y == ye)
@@ -294,16 +287,12 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
}
}
-
-/*************************/
-/* 8 Bit functions */
-/*************************/
-
+/* render a GRAYA tile to an ARGB32 cairo surface */
static void
render_image_gray_a (RenderInfo *info)
{
- gint y, ye;
- gint x, xe;
+ gint y, ye;
+ gint x, xe;
y = info->y;
ye = info->y + info->h;
@@ -336,11 +325,12 @@ render_image_gray_a (RenderInfo *info)
}
}
+/* render an RGBA tile to an ARGB32 cairo surface */
static void
render_image_rgb_a (RenderInfo *info)
{
- gint y, ye;
- gint x, xe;
+ gint y, ye;
+ gint x, xe;
y = info->y;
ye = info->y + info->h;
diff --git a/app/display/gimpdisplayshell-render.h b/app/display/gimpdisplayshell-render.h
index 82964aa..01cac48 100644
--- a/app/display/gimpdisplayshell-render.h
+++ b/app/display/gimpdisplayshell-render.h
@@ -23,12 +23,12 @@
#define GIMP_DISPLAY_RENDER_BUF_HEIGHT 256
-void gimp_display_shell_render (GimpDisplayShell *shell,
- cairo_t *cr,
- gint x,
- gint y,
- gint w,
- gint h);
+void gimp_display_shell_render (GimpDisplayShell *shell,
+ cairo_t *cr,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
#endif /* __GIMP_DISPLAY_SHELL_RENDER_H__ */
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 0ceeb7f..221127d 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -769,6 +769,12 @@ gimp_display_shell_dispose (GObject *object)
shell->render_surface = NULL;
}
+ if (shell->mask_surface)
+ {
+ cairo_surface_destroy (shell->mask_surface);
+ shell->mask_surface = NULL;
+ }
+
if (shell->checkerboard)
{
cairo_pattern_destroy (shell->checkerboard);
@@ -1802,7 +1808,7 @@ gimp_display_shell_set_highlight (GimpDisplayShell *shell,
*
* Allows to preview a selection (used by the foreground selection
* tool). Pixels that are not selected (> 127) in the mask are tinted
- * with dark blue.
+ * with the given color.
**/
void
gimp_display_shell_set_mask (GimpDisplayShell *shell,
@@ -1823,7 +1829,7 @@ gimp_display_shell_set_mask (GimpDisplayShell *shell,
if (shell->mask)
g_object_unref (shell->mask);
- shell->mask = mask;
+ shell->mask = mask;
shell->mask_color = color;
gimp_display_shell_expose_full (shell);
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index e990352..7283761 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -132,6 +132,7 @@ struct _GimpDisplayShell
GtkWidget *statusbar; /* statusbar */
cairo_surface_t *render_surface; /* buffer for rendering the image */
+ cairo_surface_t *mask_surface; /* buffer for rendering the mask */
cairo_pattern_t *checkerboard; /* checkerboard pattern */
guint title_idle_id; /* title update idle ID */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]