static void gimp_foreground_select_tool_motion (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (fg_select->mask) { GimpVector2 *last = &g_array_index (fg_select->stroke, GimpVector2, fg_select->stroke->len - 1); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); fg_select->last_coords = *coords; if (last->x != (gint) coords->x || last->y != (gint) coords->y) { GimpVector2 point = gimp_vector2_new (coords->x, coords->y); g_array_append_val (fg_select->stroke, point); } gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); } else { GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display); } }
static gboolean gimp_foreground_select_tool_key_press (GimpTool *tool, GdkEventKey *kevent, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (display != tool->display) return FALSE; if (fg_select->state) { switch (kevent->keyval) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: gimp_foreground_select_tool_apply (fg_select, display); return TRUE; case GDK_KEY_Escape: gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); return TRUE; default: return FALSE; } } else { return GIMP_TOOL_CLASS (parent_class)->key_press (tool, kevent, display); } }
static void gimp_foreground_select_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (fg_select->mask) { GimpForegroundSelectOptions *options; options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); gimp_tool_control_halt (tool->control); gimp_foreground_select_tool_push_stroke (fg_select, display, options); gimp_free_select_tool_select (GIMP_FREE_SELECT_TOOL (tool), display); gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); } else { GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state, release_type, display); } }
static void gimp_foreground_select_tool_control (GimpTool *tool, GimpToolAction action, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); switch (action) { case GIMP_TOOL_ACTION_PAUSE: case GIMP_TOOL_ACTION_RESUME: break; case GIMP_TOOL_ACTION_HALT: { gimp_foreground_select_tool_drop_masks (fg_select, display); tool->display = NULL; if (fg_select->gui) gimp_tool_gui_hide (fg_select->gui); } break; } GIMP_TOOL_CLASS (parent_class)->control (tool, action, display); }
static void gimp_foreground_select_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (fg_select->mask) { GimpForegroundSelectOptions *options; options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool); gimp_tool_control_set_toggled (tool->control, options->background); switch (GIMP_SELECTION_TOOL (tool)->function) { case SELECTION_MOVE_MASK: case SELECTION_MOVE: case SELECTION_MOVE_COPY: case SELECTION_ANCHOR: return; default: break; } } GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_foreground_select_tool_draw (GimpDrawTool *draw_tool) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (draw_tool); GimpTool *tool = GIMP_TOOL (draw_tool); GimpForegroundSelectOptions *options; options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool); if (fg_select->stroke) { gimp_draw_tool_add_pen (draw_tool, (const GimpVector2 *) fg_select->stroke->data, fg_select->stroke->len, GIMP_CONTEXT (options), (options->background ? GIMP_ACTIVE_COLOR_BACKGROUND : GIMP_ACTIVE_COLOR_FOREGROUND), options->stroke_width); } if (fg_select->mask) { GimpDisplayShell *shell = gimp_display_get_shell (draw_tool->display); gint x = fg_select->last_coords.x; gint y = fg_select->last_coords.y; gdouble radius; radius = (options->stroke_width / shell->scale_y) / 2; /* warn if the user is drawing outside of the working area */ if (FALSE) { gint x1, y1; gint x2, y2; gimp_foreground_select_tool_get_area (fg_select->mask, &x1, &y1, &x2, &y2); if (x < x1 + radius || x > x2 - radius || y < y1 + radius || y > y2 - radius) { gimp_draw_tool_add_rectangle (draw_tool, FALSE, x1, y1, x2 - x1, y2 - y1); } } gimp_draw_tool_add_arc (draw_tool, FALSE, x - radius, y - radius, 2 * radius, 2 * radius, 0.0, 2.0 * G_PI); } else { GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool); } }
static gboolean gimp_foreground_select_tool_key_press (GimpTool *tool, GdkEventKey *kevent, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (display != tool->display) return FALSE; if (fg_select->state == MATTING_STATE_PAINT_TRIMAP) { switch (kevent->keyval) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_PREVIEW, fg_select); return TRUE; case GDK_KEY_Escape: gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_RESET, fg_select); return TRUE; default: return FALSE; } } else if (fg_select->state == MATTING_STATE_PREVIEW_MASK) { switch (kevent->keyval) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_ISO_Enter: gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_APPLY, fg_select); return TRUE; case GDK_KEY_Escape: gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_PREVIEW, fg_select); return TRUE; default: return FALSE; } } else { return GIMP_TOOL_CLASS (parent_class)->key_press (tool, kevent, display); } }
static void gimp_foreground_select_tool_control (GimpTool *tool, GimpToolAction action, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); switch (action) { case GIMP_TOOL_ACTION_PAUSE: case GIMP_TOOL_ACTION_RESUME: break; case GIMP_TOOL_ACTION_HALT: { GList *list; gimp_foreground_select_tool_set_mask (fg_select, display, NULL); for (list = fg_select->strokes; list; list = list->next) { FgSelectStroke *stroke = list->data; g_free (stroke->points); g_slice_free (FgSelectStroke, stroke); } g_list_free (fg_select->strokes); fg_select->strokes = NULL; if (fg_select->state) { gimp_drawable_foreground_extract_siox_done (fg_select->state); fg_select->state = NULL; } tool->display = NULL; } break; } GIMP_TOOL_CLASS (parent_class)->control (tool, action, display); }
static void gimp_foreground_select_tool_finalize (GObject *object) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (object); if (fg_select->stroke) g_warning ("%s: stroke should be NULL at this point", G_STRLOC); if (fg_select->strokes) g_warning ("%s: strokes should be NULL at this point", G_STRLOC); if (fg_select->state) g_warning ("%s: state should be NULL at this point", G_STRLOC); if (fg_select->mask) g_warning ("%s: mask should be NULL at this point", G_STRLOC); G_OBJECT_CLASS (parent_class)->finalize (object); }
static void gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel, GimpDisplay *display) { GimpForegroundSelectTool *fg_select; GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable; GimpScanConvert *scan_convert; const GimpVector2 *points; gint n_points; drawable = gimp_image_get_active_drawable (image); fg_select = GIMP_FOREGROUND_SELECT_TOOL (free_sel); if (! drawable) return; if (fg_select->state == MATTING_STATE_FREE_SELECT) { scan_convert = gimp_scan_convert_new (); gimp_free_select_tool_get_points (free_sel, &points, &n_points); gimp_scan_convert_add_polyline (scan_convert, n_points, points, TRUE); fg_select->trimap = gegl_buffer_new (GEGL_RECTANGLE (0, 0, gimp_image_get_width (image), gimp_image_get_height (image)), gimp_image_get_mask_format (image)); gimp_scan_convert_render_value (scan_convert, fg_select->trimap, 0, 0, 1.0); gimp_scan_convert_free (scan_convert); gimp_foreground_select_tool_set_trimap (fg_select, display); } }
static void gimp_foreground_select_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); if ((fg_select->state == MATTING_STATE_PAINT_TRIMAP) || (fg_select->state == MATTING_STATE_PREVIEW_MASK)) { GimpVector2 point = gimp_vector2_new (coords->x, coords->y); gimp_draw_tool_pause (draw_tool); if (gimp_draw_tool_is_active (draw_tool) && draw_tool->display != display) gimp_draw_tool_stop (draw_tool); gimp_tool_control_activate (tool->control); fg_select->last_coords = *coords; g_return_if_fail (fg_select->stroke == NULL); fg_select->stroke = g_array_new (FALSE, FALSE, sizeof (GimpVector2)); g_array_append_val (fg_select->stroke, point); if (!gimp_draw_tool_is_active (draw_tool)) gimp_draw_tool_start (draw_tool, display); gimp_draw_tool_resume (draw_tool); } else if (fg_select->state == MATTING_STATE_FREE_SELECT) { GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, press_type, display); } }
static void gimp_foreground_select_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if ((fg_select->state == MATTING_STATE_PAINT_TRIMAP) || (fg_select->state == MATTING_STATE_PREVIEW_MASK)) { GimpForegroundSelectOptions *options; options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); gimp_tool_control_halt (tool->control); gimp_foreground_select_tool_stroke_paint (fg_select, display, options); if (fg_select->state == MATTING_STATE_PREVIEW_MASK) gimp_foreground_select_tool_preview (fg_select, display); else gimp_foreground_select_tool_set_trimap (fg_select, display); gimp_free_select_tool_select (GIMP_FREE_SELECT_TOOL (tool), display); gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); } else if (fg_select->state == MATTING_STATE_FREE_SELECT) { GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state, release_type, display); } }
static void gimp_foreground_select_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); const gchar *status = NULL; GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); if (fg_select->mask && display == tool->display) { GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); gimp_draw_tool_pause (draw_tool); fg_select->last_coords = *coords; gimp_draw_tool_resume (draw_tool); if (fg_select->strokes) status = _("Add more strokes or press Enter to accept the selection"); else status = _("Mark foreground by painting on the object to extract"); } else { if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_SELECT) status = _("Roughly outline the object to extract"); } if (proximity && status) gimp_tool_replace_status (tool, display, "%s", status); }
static void gimp_foreground_select_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (fg_select->state == MATTING_STATE_PAINT_TRIMAP) { switch (GIMP_SELECTION_TOOL (tool)->function) { case SELECTION_MOVE_MASK: case SELECTION_MOVE: case SELECTION_MOVE_COPY: case SELECTION_ANCHOR: return; default: break; } } GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_foreground_select_tool_select (GimpFreeSelectTool *free_sel, GimpDisplay *display) { GimpForegroundSelectTool *fg_select; GimpForegroundSelectOptions *options; GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable; GimpScanConvert *scan_convert; GimpChannel *mask; const GimpVector2 *points; gint n_points; drawable = gimp_image_get_active_drawable (image); fg_select = GIMP_FOREGROUND_SELECT_TOOL (free_sel); options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (free_sel); if (fg_select->idle_id) { g_source_remove (fg_select->idle_id); fg_select->idle_id = 0; } if (! drawable) return; scan_convert = gimp_scan_convert_new (); gimp_free_select_tool_get_points (free_sel, &points, &n_points); gimp_scan_convert_add_polyline (scan_convert, n_points, points, TRUE); mask = gimp_channel_new (image, gimp_image_get_width (image), gimp_image_get_height (image), "foreground-extraction", NULL); gimp_scan_convert_render_value (scan_convert, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)), 0, 0, 128); gimp_scan_convert_free (scan_convert); if (fg_select->strokes) { GList *list; gimp_set_busy (image->gimp); /* apply foreground and background markers */ for (list = fg_select->strokes; list; list = list->next) gimp_foreground_select_tool_stroke (mask, list->data); if (fg_select->state) gimp_drawable_foreground_extract_siox (GIMP_DRAWABLE (mask), fg_select->state, fg_select->refinement, options->smoothness, options->sensitivity, ! options->contiguous, GIMP_PROGRESS (fg_select)); fg_select->refinement = SIOX_REFINEMENT_NO_CHANGE; gimp_unset_busy (image->gimp); } else { gint x1, y1; gint x2, y2; g_object_set (options, "background", FALSE, NULL); gimp_foreground_select_tool_get_area (mask, &x1, &y1, &x2, &y2); if (fg_select->state) g_warning ("state should be NULL here"); fg_select->state = gimp_drawable_foreground_extract_siox_init (drawable, x1, y1, x2 - x1, y2 - y1); } gimp_foreground_select_tool_set_mask (fg_select, display, mask); g_object_unref (mask); }
static void gimp_foreground_select_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (fg_select); const gchar *status_stage = NULL; const gchar *status_mode = NULL; GimpDisplayShell *shell = gimp_display_get_shell (display); GimpImage *image = gimp_display_get_image (display); GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); if (fg_select->state == MATTING_STATE_FREE_SELECT) { if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_SELECT) status_stage = _("Roughly outline the object to extract"); } else { GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); gimp_draw_tool_pause (draw_tool); fg_select->last_coords = *coords; gimp_draw_tool_resume (draw_tool); if (options->draw_mode == GIMP_MATTING_DRAW_MODE_FOREGROUND) status_mode = _("Selecting foreground, "); else if (options->draw_mode == GIMP_MATTING_DRAW_MODE_BACKGROUND) status_mode = _("Selecting background, "); else status_mode = _("Selecting unknown, "); if (fg_select->state == MATTING_STATE_PAINT_TRIMAP) status_stage = _("press Enter to preview."); else status_stage = _("press Escape to exit preview or Enter to apply."); } if (proximity && status_stage) { if (status_mode) gimp_tool_replace_status (tool, display, "%s%s", status_mode, status_stage); else gimp_tool_replace_status (tool, display, "%s", status_stage); } gimp_foreground_select_tool_update_gui (fg_select); gimp_tool_gui_set_shell (fg_select->gui, shell); gimp_tool_gui_set_viewable (fg_select->gui, GIMP_VIEWABLE (image)); gimp_tool_gui_show (fg_select->gui); }