Commit 1016a3dc authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

app/display/gimpdisplayshell-render.c added

2005-07-30  Sven Neumann  <sven@gimp.org>

	* app/display/gimpdisplayshell-render.c
	* app/display/gimpdisplayshell.[ch]: added
	gimp_display_shell_set_overlay(); allows to overlay a mask over the
	display to visualize a selection.

	* app/tools/gimpforegroundselecttool.[ch]: use the new functionality
	to display the selection. Escape cancels the tool, Enter applies the
	selection.
parent 335bd846
2005-07-30 Sven Neumann <sven@gimp.org>
* app/display/gimpdisplayshell-render.c
* app/display/gimpdisplayshell.[ch]: added
gimp_display_shell_set_overlay(); allows to overlay a mask over the
display to visualize a selection.
* app/tools/gimpforegroundselecttool.[ch]: use the new functionality
to display the selection. Escape cancels the tool, Enter applies the
selection.
2005-07-30 Sven Neumann <sven@gimp.org>
* libgimpbase/gimpbase.def: added missing symbol.
......
......@@ -32,6 +32,7 @@
#include "base/tile.h"
#include "core/gimp.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
#include "core/gimpimage-colormap.h"
#include "core/gimpprojection.h"
......@@ -191,6 +192,8 @@ static void gimp_display_shell_render_highlight (GimpDisplayShell *shell,
gint w,
gint h,
GdkRectangle *highlight);
static void gimp_display_shell_render_overlay (GimpDisplayShell *shell,
RenderInfo *info);
/*****************************************************************/
......@@ -237,7 +240,21 @@ gimp_display_shell_render (GimpDisplayShell *shell,
/* 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, x, y, w, h, highlight);
}
else if (shell->overlay)
{
info.src_tiles = gimp_drawable_data (shell->overlay);
info.src_bpp = 1;
info.x = x + shell->offset_x;
info.y = y + shell->offset_y;
info.src_x = (gdouble) info.x / info.scalex;
info.src_y = (gdouble) info.y / info.scaley;
info.dest = shell->render_buf;
gimp_display_shell_render_overlay (shell, &info);
}
/* put it to the screen */
gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER,
......@@ -318,6 +335,63 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
}
}
static void
gimp_display_shell_render_overlay (GimpDisplayShell *shell,
RenderInfo *info)
{
gint y, ye;
gint x, xe;
gboolean initial = TRUE;
y = info->y;
ye = info->y + info->h;
xe = info->x + info->w;
info->src = render_image_tile_fault (info);
while (TRUE)
{
gint error =
RINT (floor ((y + 1) / info->scaley) - floor (y / info->scaley));
if (!initial && (error == 0))
{
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
}
else
{
const guchar *src = info->src;
guchar *dest = info->dest;
for (x = info->x; x < xe; x++, src++, dest += 3)
{
if (*src & 0x80)
continue;
dest[0] = dest[0] >> 2;
dest[1] = dest[1] >> 2;
}
}
if (++y == ye)
break;
info->dest += info->dest_bpl;
if (error)
{
info->src_y += error;
info->src = render_image_tile_fault (info);
initial = TRUE;
}
else
{
initial = FALSE;
}
}
}
/*************************/
/* 8 Bit functions */
......@@ -737,6 +811,7 @@ render_image_init_info (RenderInfo *info,
info->shell = shell;
info->src_tiles = gimp_projection_get_tiles (gimage->projection);
info->src_bpp = gimp_projection_get_bytes (gimage->projection);
info->x = x + shell->offset_x;
info->y = y + shell->offset_y;
info->w = w;
......@@ -745,7 +820,6 @@ render_image_init_info (RenderInfo *info,
info->scaley = SCALEFACTOR_Y (shell);
info->src_x = (gdouble) info->x / info->scalex;
info->src_y = (gdouble) info->y / info->scaley;
info->src_bpp = gimp_projection_get_bytes (gimage->projection);
info->dest = shell->render_buf;
info->dest_bpp = 3;
info->dest_bpl = info->dest_bpp * GIMP_RENDER_BUF_WIDTH;
......
......@@ -318,6 +318,7 @@ gimp_display_shell_init (GimpDisplayShell *shell)
shell->button_press_before_focus = FALSE;
shell->highlight = NULL;
shell->overlay = NULL;
gtk_window_set_role (GTK_WINDOW (shell), "gimp-image-window");
gtk_window_set_resizable (GTK_WINDOW (shell), TRUE);
......@@ -407,6 +408,12 @@ gimp_display_shell_destroy (GtkObject *object)
shell->highlight = NULL;
}
if (shell->overlay)
{
g_object_unref (shell->overlay);
shell->overlay = NULL;
}
if (shell->title_idle_id)
{
g_source_remove (shell->title_idle_id);
......@@ -1586,3 +1593,33 @@ gimp_display_shell_set_highlight (GimpDisplayShell *shell,
gimp_display_shell_expose_full (shell);
}
}
/**
* gimp_display_shell_set_overlay:
* @shell: a #GimpDisplayShell
* @mask: a #GimpDrawable (1 byte per pixel)
*
* Allows to preview a selection (used by the foreground selection tool).
**/
void
gimp_display_shell_set_overlay (GimpDisplayShell *shell,
GimpDrawable *mask)
{
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (mask == NULL || GIMP_IS_DRAWABLE (mask));
if (shell->overlay)
{
g_object_unref (shell->overlay);
shell->overlay = NULL;
}
if (mask)
{
g_return_if_fail (gimp_drawable_bytes (mask) == 1);
shell->overlay = g_object_ref (mask);
}
gimp_display_shell_expose_full (shell);
}
......@@ -166,6 +166,8 @@ struct _GimpDisplayShell
GdkRectangle *highlight; /* in image coordinates, can be NULL */
GimpDrawable *overlay;
gpointer scroll_info;
};
......@@ -235,6 +237,8 @@ void gimp_display_shell_selection_visibility (GimpDisplayShell *shell,
GimpSelectionControl control);
void gimp_display_shell_set_highlight (GimpDisplayShell *shell,
const GdkRectangle *highlight);
void gimp_display_shell_set_overlay (GimpDisplayShell *shell,
GimpDrawable *overlay);
#endif /* __GIMP_DISPLAY_SHELL_H__ */
......@@ -19,6 +19,7 @@
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "libgimpwidgets/gimpwidgets.h"
......@@ -36,6 +37,7 @@
#include "widgets/gimphelp-ids.h"
#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"
#include "gimpforegroundselecttool.h"
#include "gimpselectionoptions.h"
......@@ -48,6 +50,12 @@ static void gimp_foreground_select_tool_class_init (GimpForegroundSelectToolCl
static void gimp_foreground_select_tool_init (GimpForegroundSelectTool *fg_select);
static void gimp_foreground_select_tool_finalize (GObject *object);
static void gimp_foreground_select_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *gdisp);
static gboolean gimp_foreground_select_tool_key_press (GimpTool *tool,
GdkEventKey *kevent,
GimpDisplay *gdisp);
static void gimp_foreground_select_tool_button_press (GimpTool *tool,
GimpCoords *coords,
guint32 time,
......@@ -68,6 +76,10 @@ static void gimp_foreground_select_tool_draw (GimpDrawTool *draw_
static void gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
GimpDisplay *gdisp);
static void gimp_foreground_select_tool_set_mask (GimpForegroundSelectTool *fg_select,
GimpChannel *mask);
static void gimp_foreground_select_tool_apply_mask (GimpForegroundSelectTool *fg_select,
GimpImage *gimage);
static GimpFreeSelectToolClass *parent_class = NULL;
......@@ -134,6 +146,8 @@ gimp_foreground_select_tool_class_init (GimpForegroundSelectToolClass *klass)
object_class->finalize = gimp_foreground_select_tool_finalize;
tool_class->control = gimp_foreground_select_tool_control;
tool_class->key_press = gimp_foreground_select_tool_key_press;
tool_class->button_press = gimp_foreground_select_tool_button_press;
tool_class->button_release = gimp_foreground_select_tool_button_release;
tool_class->motion = gimp_foreground_select_tool_motion;
......@@ -160,13 +174,56 @@ gimp_foreground_select_tool_finalize (GObject *object)
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (object);
if (fg_select->mask)
gimp_foreground_select_tool_set_mask (fg_select, NULL);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_foreground_select_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *gdisp)
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
switch (action)
{
g_object_unref (fg_select->mask);
fg_select->mask = NULL;
case HALT:
gimp_foreground_select_tool_set_mask (fg_select, NULL);
gimp_display_shell_set_overlay (GIMP_DISPLAY_SHELL (gdisp->shell), NULL);
break;
default:
break;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
}
static gboolean
gimp_foreground_select_tool_key_press (GimpTool *tool,
GdkEventKey *kevent,
GimpDisplay *gdisp)
{
if (gdisp != tool->gdisp)
return FALSE;
switch (kevent->keyval)
{
case GDK_KP_Enter:
case GDK_Return:
gimp_foreground_select_tool_apply_mask (GIMP_FOREGROUND_SELECT_TOOL (tool),
gdisp->gimage);
gimp_display_shell_set_overlay (GIMP_DISPLAY_SHELL (gdisp->shell), NULL);
return TRUE;
case GDK_Escape:
gimp_tool_control (tool, HALT, gdisp);
return TRUE;
default:
return FALSE;
}
}
static void
......@@ -212,18 +269,14 @@ static void
gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
GimpDisplay *gdisp)
{
GimpTool *tool = GIMP_TOOL (free_sel);
GimpImage *gimage = gdisp->gimage;
GimpDrawable *drawable = gimp_image_active_drawable (gimage);
GimpScanConvert *scan_convert;
GimpChannel *mask;
GimpSelectionOptions *options;
GimpImage *gimage = gdisp->gimage;
GimpDrawable *drawable = gimp_image_active_drawable (gimage);
GimpScanConvert *scan_convert;
GimpChannel *mask;
if (! drawable)
return;
options = GIMP_SELECTION_OPTIONS (tool->tool_info->tool_options);
gimp_set_busy (gimage->gimp);
scan_convert = gimp_scan_convert_new ();
......@@ -245,15 +298,52 @@ gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel,
GIMP_DRAWABLE (mask),
GIMP_PROGRESS (gdisp));
gimp_foreground_select_tool_set_mask (GIMP_FOREGROUND_SELECT_TOOL (free_sel),
mask);
gimp_display_shell_set_overlay (GIMP_DISPLAY_SHELL (gdisp->shell),
GIMP_DRAWABLE (mask));
g_object_unref (mask);
gimp_unset_busy (gimage->gimp);
}
static void
gimp_foreground_select_tool_set_mask (GimpForegroundSelectTool *fg_select,
GimpChannel *mask)
{
if (fg_select->mask == mask)
return;
if (fg_select->mask)
{
g_object_unref (fg_select->mask);
fg_select->mask = NULL;
}
if (mask)
fg_select->mask = g_object_ref (mask);
}
static void
gimp_foreground_select_tool_apply_mask (GimpForegroundSelectTool *fg_select,
GimpImage *gimage)
{
GimpTool *tool = GIMP_TOOL (fg_select);
GimpSelectionOptions *options;
options = GIMP_SELECTION_OPTIONS (tool->tool_info->tool_options);
if (! fg_select->mask)
return;
gimp_channel_select_channel (gimp_image_get_mask (gimage),
tool->tool_info->blurb,
mask, 0, 0,
fg_select->mask, 0, 0,
GIMP_SELECTION_TOOL (tool)->op,
options->feather,
options->feather_radius,
options->feather_radius);
g_object_unref (mask);
gimp_unset_busy (gimage->gimp);
gimp_foreground_select_tool_set_mask (fg_select, NULL);
}
......@@ -38,7 +38,7 @@ struct _GimpForegroundSelectTool
{
GimpFreeSelectTool parent_instance;
GimpChannel *mask;
GimpChannel *mask;
};
struct _GimpForegroundSelectToolClass
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment