void gimp_channel_select_round_rect (GimpChannel *channel, gint x, gint y, gint w, gint h, gdouble corner_radius_x, gdouble corner_radius_y, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y, gboolean push_undo) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); if (push_undo) gimp_channel_push_undo (channel, C_("undo-type", "Rounded Rectangle Select")); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); /* if feathering for rect, make a new mask with the * rectangle and feather that with the old mask */ if (feather || op == GIMP_CHANNEL_OP_INTERSECT) { GimpItem *item = GIMP_ITEM (channel); GeglBuffer *add_on; add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0, gimp_item_get_width (item), gimp_item_get_height (item)), babl_format ("Y float")); gimp_gegl_mask_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_ADD, x, y, w, h, corner_radius_x, corner_radius_y, antialias); if (feather) gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, feather_radius_x, feather_radius_y); gimp_channel_combine_buffer (channel, add_on, op, 0, 0); g_object_unref (add_on); } else { gimp_channel_combine_ellipse_rect (channel, op, x, y, w, h, corner_radius_x, corner_radius_y, antialias); } }
void gimp_channel_select_round_rect (GimpChannel *channel, gint x, gint y, gint w, gint h, gdouble corner_radius_x, gdouble corner_radius_y, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y, gboolean push_undo) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); if (push_undo) gimp_channel_push_undo (channel, Q_("command|Rounded Rectangle Select")); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); /* if feathering for rect, make a new mask with the * rectangle and feather that with the old mask */ if (feather || op == GIMP_CHANNEL_OP_INTERSECT) { GimpItem *item = GIMP_ITEM (channel); GimpChannel *add_on; add_on = gimp_channel_new_mask (gimp_item_get_image (item), gimp_item_width (item), gimp_item_height (item)); gimp_channel_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_ADD, x, y, w, h, corner_radius_x, corner_radius_y, antialias); if (feather) gimp_channel_feather (add_on, feather_radius_x, feather_radius_y, FALSE /* no undo */); gimp_channel_combine_mask (channel, add_on, op, 0, 0); g_object_unref (add_on); } else { gimp_channel_combine_ellipse_rect (channel, op, x, y, w, h, corner_radius_x, corner_radius_y, antialias); } }
void select_none_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; return_if_no_image (image, data); gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); gimp_image_flush (image); }
void gimp_channel_select_buffer (GimpChannel *channel, const gchar *undo_desc, GeglBuffer *add_on, gint offset_x, gint offset_y, GimpChannelOps op, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); g_return_if_fail (undo_desc != NULL); g_return_if_fail (GEGL_IS_BUFFER (add_on)); gimp_channel_push_undo (channel, undo_desc); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); if (feather || op == GIMP_CHANNEL_OP_INTERSECT) { GimpItem *item = GIMP_ITEM (channel); GeglBuffer *add_on2; add_on2 = gegl_buffer_new (GEGL_RECTANGLE (0, 0, gimp_item_get_width (item), gimp_item_get_height (item)), babl_format ("Y float")); gimp_gegl_mask_combine_buffer (add_on2, add_on, GIMP_CHANNEL_OP_ADD, offset_x, offset_y); if (feather) gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2, NULL, feather_radius_x, feather_radius_y); gimp_channel_combine_buffer (channel, add_on2, op, 0, 0); g_object_unref (add_on2); } else { gimp_channel_combine_buffer (channel, add_on, op, offset_x, offset_y); } }
void gimp_channel_select_channel (GimpChannel *channel, const gchar *undo_desc, GimpChannel *add_on, gint offset_x, gint offset_y, GimpChannelOps op, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); g_return_if_fail (undo_desc != NULL); g_return_if_fail (GIMP_IS_CHANNEL (add_on)); gimp_channel_push_undo (channel, undo_desc); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); if (feather || op == GIMP_CHANNEL_OP_INTERSECT) { GimpItem *item = GIMP_ITEM (channel); GimpChannel *add_on2; add_on2 = gimp_channel_new_mask (gimp_item_get_image (item), gimp_item_width (item), gimp_item_height (item)); gimp_channel_combine_mask (add_on2, add_on, GIMP_CHANNEL_OP_ADD, offset_x, offset_y); if (feather) gimp_channel_feather (add_on2, feather_radius_x, feather_radius_y, FALSE /* no undo */); gimp_channel_combine_mask (channel, add_on2, op, 0, 0); g_object_unref (add_on2); } else { gimp_channel_combine_mask (channel, add_on, op, offset_x, offset_y); } }
void gimp_channel_select_scan_convert (GimpChannel *channel, const gchar *undo_desc, GimpScanConvert *scan_convert, gint offset_x, gint offset_y, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y, gboolean push_undo) { GimpItem *item; GeglBuffer *add_on; g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); g_return_if_fail (undo_desc != NULL); g_return_if_fail (scan_convert != NULL); if (push_undo) gimp_channel_push_undo (channel, undo_desc); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); item = GIMP_ITEM (channel); add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0, gimp_item_get_width (item), gimp_item_get_height (item)), babl_format ("Y float")); gimp_scan_convert_render (scan_convert, add_on, offset_x, offset_y, antialias); if (feather) gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, feather_radius_x, feather_radius_y); gimp_channel_combine_buffer (channel, add_on, op, 0, 0); g_object_unref (add_on); }
void gimp_channel_select_scan_convert (GimpChannel *channel, const gchar *undo_desc, GimpScanConvert *scan_convert, gint offset_x, gint offset_y, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y, gboolean push_undo) { GimpItem *item; GimpChannel *add_on; g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); g_return_if_fail (undo_desc != NULL); g_return_if_fail (scan_convert != NULL); if (push_undo) gimp_channel_push_undo (channel, undo_desc); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); item = GIMP_ITEM (channel); add_on = gimp_channel_new_mask (gimp_item_get_image (item), gimp_item_width (item), gimp_item_height (item)); gimp_scan_convert_render (scan_convert, gimp_drawable_get_tiles (GIMP_DRAWABLE (add_on)), offset_x, offset_y, antialias); if (feather) gimp_channel_feather (add_on, feather_radius_x, feather_radius_y, FALSE /* no undo */); gimp_channel_combine_mask (channel, add_on, op, 0, 0); g_object_unref (add_on); }
static GimpValueArray * selection_none_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GimpValueArray *args, GError **error) { gboolean success = TRUE; GimpImage *image; image = gimp_value_get_image (gimp_value_array_index (args, 0), gimp); if (success) { gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); } return gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); }
/* * This function is called if the user clicks and releases the left * button without moving it. There are the things we might want * to do here: * 1) If there is an existing rectangle and we are inside it, we * convert it into a selection. * 2) If there is an existing rectangle and we are outside it, we * clear it. * 3) If there is no rectangle and there is a floating selection, * we anchor it. * 4) If there is no rectangle and we are inside the selection, we * create a rectangle from the selection bounds. * 5) If there is no rectangle and we are outside the selection, * we clear the selection. */ static gboolean gimp_rectangle_select_tool_execute (GimpRectangleTool *rectangle, gint x, gint y, gint w, gint h) { GimpTool *tool = GIMP_TOOL (rectangle); GimpRectangleSelectTool *rect_sel_tool; GimpRectangleSelectToolPrivate *priv; rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (rectangle); priv = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool); if (w == 0 && h == 0 && tool->display != NULL) { GimpImage *image = gimp_display_get_image (tool->display); GimpChannel *selection = gimp_image_get_mask (image); gint pressx; gint pressy; if (gimp_image_get_floating_selection (image)) { floating_sel_anchor (gimp_image_get_floating_selection (image)); gimp_image_flush (image); return TRUE; } pressx = ROUND (priv->press_x); pressy = ROUND (priv->press_y); /* if the click was inside the marching ants */ if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (selection), pressx, pressy) > 0.5) { gint x1, y1, x2, y2; if (gimp_channel_bounds (selection, &x1, &y1, &x2, &y2)) { g_object_set (rectangle, "x1", x1, "y1", y1, "x2", x2, "y2", y2, NULL); } gimp_rectangle_tool_set_function (rectangle, GIMP_RECTANGLE_TOOL_MOVING); return FALSE; } else { GimpTool *tool = GIMP_TOOL (rectangle); GimpChannelOps operation; /* prevent this change from halting the tool */ gimp_tool_control_push_preserve (tool->control, TRUE); /* We can conceptually think of a click outside of the * selection as adding a 0px selection. Behave intuitivly * for the current selection mode */ operation = gimp_rectangle_select_tool_get_operation (rect_sel_tool); switch (operation) { case GIMP_CHANNEL_OP_REPLACE: case GIMP_CHANNEL_OP_INTERSECT: gimp_channel_clear (selection, NULL, TRUE); gimp_image_flush (image); break; case GIMP_CHANNEL_OP_ADD: case GIMP_CHANNEL_OP_SUBTRACT: default: /* Do nothing */ break; } gimp_tool_control_pop_preserve (tool->control); } } gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, FALSE); /* Reset the automatic undo/redo mechanism */ priv->undo = NULL; priv->redo = NULL; return TRUE; }
GimpLayer * text_render (GimpImage *image, GimpDrawable *drawable, GimpContext *context, gint text_x, gint text_y, const gchar *fontname, const gchar *text, gint border, gboolean antialias) { PangoFontDescription *desc; GimpText *gtext; GimpLayer *layer; GimpRGB color; gchar *font; gdouble size; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (drawable == NULL || gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (fontname != NULL, NULL); g_return_val_if_fail (text != NULL, NULL); if (border < 0) border = 0; desc = pango_font_description_from_string (fontname); size = PANGO_PIXELS (pango_font_description_get_size (desc)); pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE); font = pango_font_description_to_string (desc); pango_font_description_free (desc); gimp_context_get_foreground (context, &color); gtext = g_object_new (GIMP_TYPE_TEXT, "text", text, "font", font, "font-size", size, "antialias", antialias, "border", border, "color", &color, NULL); g_free (font); layer = gimp_text_layer_new (image, gtext); g_object_unref (gtext); if (!layer) return NULL; /* Start a group undo */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TEXT, _("Add Text Layer")); /* Set the layer offsets */ gimp_item_set_offset (GIMP_ITEM (layer), text_x, text_y); /* If there is a selection mask clear it-- * this might not always be desired, but in general, * it seems like the correct behavior. */ if (! gimp_channel_is_empty (gimp_image_get_mask (image))) gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); if (drawable == NULL) { /* If the drawable is NULL, create a new layer */ gimp_image_add_layer (image, layer, NULL, -1, TRUE); } else { /* Otherwise, instantiate the text as the new floating selection */ floating_sel_attach (layer, drawable); } /* end the group undo */ gimp_image_undo_group_end (image); return layer; }
void gimp_image_set_quick_mask_state (GimpImage *image, gboolean active) { GimpChannel *selection; GimpChannel *mask; gboolean channel_was_active; g_return_if_fail (GIMP_IS_IMAGE (image)); if (active == gimp_image_get_quick_mask_state (image)) return; /* Keep track of the state so that we can make the right drawable * active again when deactiviting quick mask (see bug #134371). */ if (image->quick_mask_state) channel_was_active = (image->quick_mask_state & CHANNEL_WAS_ACTIVE) != 0; else channel_was_active = gimp_image_get_active_channel (image) != NULL; /* Set image->quick_mask_state early so we can return early when * being called recursively. */ image->quick_mask_state = (active ? TRUE | (channel_was_active ? CHANNEL_WAS_ACTIVE : 0) : FALSE); selection = gimp_image_get_mask (image); mask = gimp_image_get_quick_mask (image); if (active) { if (! mask) { gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_QUICK_MASK, _("Enable Quick Mask")); if (gimp_channel_is_empty (selection)) { /* if no selection */ GimpLayer *floating_sel = gimp_image_floating_sel (image); if (floating_sel) floating_sel_to_layer (floating_sel); mask = gimp_channel_new (image, image->width, image->height, GIMP_IMAGE_QUICK_MASK_NAME, &image->quick_mask_color); /* Clear the mask */ gimp_channel_clear (mask, NULL, FALSE); } else { /* if selection */ mask = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (selection), GIMP_TYPE_CHANNEL, FALSE)); /* Clear the selection */ gimp_channel_clear (selection, NULL, TRUE); gimp_channel_set_color (mask, &image->quick_mask_color, FALSE); gimp_item_rename (GIMP_ITEM (mask), GIMP_IMAGE_QUICK_MASK_NAME); } if (image->quick_mask_inverted) gimp_channel_invert (mask, FALSE); gimp_image_add_channel (image, mask, 0); gimp_image_undo_group_end (image); } } else { if (mask) { GimpLayer *floating_sel = gimp_image_floating_sel (image); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_QUICK_MASK, _("Disable Quick Mask")); if (image->quick_mask_inverted) gimp_channel_invert (mask, TRUE); if (floating_sel && floating_sel->fs.drawable == GIMP_DRAWABLE (mask)) floating_sel_anchor (floating_sel); gimp_selection_load (gimp_image_get_mask (image), mask); gimp_image_remove_channel (image, mask); if (! channel_was_active) gimp_image_unset_active_channel (image); gimp_image_undo_group_end (image); } } gimp_image_quick_mask_changed (image); }
GeglBuffer * gimp_drawable_transform_cut (GimpDrawable *drawable, GimpContext *context, gint *offset_x, gint *offset_y, gboolean *new_layer) { GimpImage *image; GeglBuffer *buffer; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (offset_x != NULL, NULL); g_return_val_if_fail (offset_y != NULL, NULL); g_return_val_if_fail (new_layer != NULL, NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); /* extract the selected mask if there is a selection */ if (! gimp_channel_is_empty (gimp_image_get_mask (image))) { gint x, y, w, h; /* set the keep_indexed flag to FALSE here, since we use * gimp_layer_new_from_buffer() later which assumes that the buffer * are either RGB or GRAY. Eeek!!! (Sven) */ if (gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &w, &h)) { buffer = gimp_selection_extract (GIMP_SELECTION (gimp_image_get_mask (image)), GIMP_PICKABLE (drawable), context, TRUE, FALSE, TRUE, offset_x, offset_y, NULL); /* clear the selection */ gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); *new_layer = TRUE; } else { buffer = NULL; *new_layer = FALSE; } } else /* otherwise, just copy the layer */ { buffer = gimp_selection_extract (GIMP_SELECTION (gimp_image_get_mask (image)), GIMP_PICKABLE (drawable), context, FALSE, TRUE, GIMP_IS_LAYER (drawable), offset_x, offset_y, NULL); *new_layer = FALSE; } return buffer; }
GimpLayer * gimp_edit_paste (GimpImage *image, GimpDrawable *drawable, GimpBuffer *paste, gboolean paste_into, gint viewport_x, gint viewport_y, gint viewport_width, gint viewport_height) { GimpLayer *layer; const Babl *format; gint image_width; gint image_height; gint width; gint height; gint offset_x; gint offset_y; gboolean clamp_to_image = TRUE; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (drawable == NULL || gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_BUFFER (paste), NULL); /* Make a new layer: if drawable == NULL, * user is pasting into an empty image. */ if (drawable) format = gimp_drawable_get_format_with_alpha (drawable); else format = gimp_image_get_layer_format (image, TRUE); layer = gimp_layer_new_from_buffer (paste, image, format, _("Pasted Layer"), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (! layer) return NULL; image_width = gimp_image_get_width (image); image_height = gimp_image_get_height (image); width = gimp_item_get_width (GIMP_ITEM (layer)); height = gimp_item_get_height (GIMP_ITEM (layer)); if (viewport_width == image_width && viewport_height == image_height) { /* if the whole image is visible, act as if there was no viewport */ viewport_x = 0; viewport_y = 0; viewport_width = 0; viewport_height = 0; } if (drawable) { /* if pasting to a drawable */ gint off_x, off_y; gint x1, y1, x2, y2; gint paste_x, paste_y; gint paste_width, paste_height; gboolean have_mask; gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); have_mask = gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2); if (! have_mask && /* if we have no mask */ viewport_width > 0 && /* and we have a viewport */ viewport_height > 0 && (width < (x2 - x1) || /* and the paste is smaller than the target */ height < (y2 - y1)) && /* and the viewport intersects with the target */ gimp_rectangle_intersect (viewport_x, viewport_y, viewport_width, viewport_height, off_x, off_y, x2 - x1, y2 - y1, &paste_x, &paste_y, &paste_width, &paste_height)) { /* center on the viewport */ offset_x = paste_x + (paste_width - width) / 2; offset_y = paste_y + (paste_height- height) / 2; } else { /* otherwise center on the target */ offset_x = off_x + ((x1 + x2) - width) / 2; offset_y = off_y + ((y1 + y2) - height) / 2; /* and keep it that way */ clamp_to_image = FALSE; } } else if (viewport_width > 0 && /* if we have a viewport */ viewport_height > 0 && (width < image_width || /* and the paste is */ height < image_height)) /* smaller than the image */ { /* center on the viewport */ offset_x = viewport_x + (viewport_width - width) / 2; offset_y = viewport_y + (viewport_height - height) / 2; } else { /* otherwise center on the image */ offset_x = (image_width - width) / 2; offset_y = (image_height - height) / 2; /* and keep it that way */ clamp_to_image = FALSE; } if (clamp_to_image) { /* Ensure that the pasted layer is always within the image, if it * fits and aligned at top left if it doesn't. (See bug #142944). */ offset_x = MIN (offset_x, image_width - width); offset_y = MIN (offset_y, image_height - height); offset_x = MAX (offset_x, 0); offset_y = MAX (offset_y, 0); } gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y); /* Start a group undo */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, C_("undo-type", "Paste")); /* If there is a selection mask clear it-- * this might not always be desired, but in general, * it seems like the correct behavior. */ if (! gimp_channel_is_empty (gimp_image_get_mask (image)) && ! paste_into) gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); /* if there's a drawable, add a new floating selection */ if (drawable) floating_sel_attach (layer, drawable); else gimp_image_add_layer (image, layer, NULL, 0, TRUE); /* end the group undo */ gimp_image_undo_group_end (image); return layer; }
GimpLayer * gimp_edit_paste (GimpImage *image, GimpDrawable *drawable, GimpObject *paste, GimpPasteType paste_type, gint viewport_x, gint viewport_y, gint viewport_width, gint viewport_height) { GimpLayer *layer = NULL; const Babl *floating_format; gint offset_x; gint offset_y; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (drawable == NULL || gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (paste) || GIMP_IS_BUFFER (paste), NULL); /* change paste type to NEW_LAYER for cases where we can't attach a * floating selection */ if (! drawable || gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) || gimp_item_is_content_locked (GIMP_ITEM (drawable))) { paste_type = GIMP_PASTE_TYPE_NEW_LAYER; } /* floating pastes always have the pasted-to drawable's format with * alpha; if drawable == NULL, user is pasting into an empty image */ if (drawable) floating_format = gimp_drawable_get_format_with_alpha (drawable); else floating_format = gimp_image_get_layer_format (image, TRUE); if (GIMP_IS_IMAGE (paste)) { GType layer_type; layer = gimp_image_get_layer_iter (GIMP_IMAGE (paste))->data; switch (paste_type) { case GIMP_PASTE_TYPE_FLOATING: case GIMP_PASTE_TYPE_FLOATING_INTO: /* when pasting as floating selection, force creation of a * plain layer, so gimp_item_convert() will collapse a * group layer */ layer_type = GIMP_TYPE_LAYER; break; case GIMP_PASTE_TYPE_NEW_LAYER: layer_type = G_TYPE_FROM_INSTANCE (layer); break; default: g_return_val_if_reached (NULL); } layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer), image, layer_type)); switch (paste_type) { case GIMP_PASTE_TYPE_FLOATING: case GIMP_PASTE_TYPE_FLOATING_INTO: /* when pasting as floating selection, get rid of the layer mask, * and make sure the layer has the right format */ if (gimp_layer_get_mask (layer)) gimp_layer_apply_mask (layer, GIMP_MASK_DISCARD, FALSE); if (gimp_drawable_get_format (GIMP_DRAWABLE (layer)) != floating_format) { gimp_drawable_convert_type (GIMP_DRAWABLE (layer), image, gimp_drawable_get_base_type (drawable), gimp_drawable_get_precision (drawable), TRUE, NULL, GEGL_DITHER_NONE, GEGL_DITHER_NONE, FALSE, NULL); } break; default: break; } } else if (GIMP_IS_BUFFER (paste)) { layer = gimp_layer_new_from_buffer (GIMP_BUFFER (paste), image, floating_format, _("Pasted Layer"), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); } if (! layer) return NULL; gimp_edit_get_paste_offset (image, drawable, GIMP_OBJECT (layer), viewport_x, viewport_y, viewport_width, viewport_height, &offset_x, &offset_y); gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, C_("undo-type", "Paste")); switch (paste_type) { case GIMP_PASTE_TYPE_FLOATING: /* if there is a selection mask clear it - this might not * always be desired, but in general, it seems like the correct * behavior */ if (! gimp_channel_is_empty (gimp_image_get_mask (image))) gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); /* fall thru */ case GIMP_PASTE_TYPE_FLOATING_INTO: floating_sel_attach (layer, drawable); break; case GIMP_PASTE_TYPE_NEW_LAYER: { GimpLayer *parent = NULL; gint position = 0; /* always add on top of the passed layer, where we would * attach a floating selection */ if (GIMP_IS_LAYER (drawable)) { parent = gimp_layer_get_parent (GIMP_LAYER (drawable)); position = gimp_item_get_index (GIMP_ITEM (drawable)); } gimp_image_add_layer (image, layer, parent, position, TRUE); } break; } gimp_image_undo_group_end (image); return layer; }
static void gimp_region_select_tool_button_release (GimpTool *tool, GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpRegionSelectTool *region_sel = GIMP_REGION_SELECT_TOOL (tool); GimpSelectionOptions *sel_options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); GimpRegionSelectOptions *options = GIMP_REGION_SELECT_TOOL_GET_OPTIONS (tool); gimp_tool_pop_status (tool, display); gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool)); gimp_tool_control_halt (tool->control); if (release_type != GIMP_BUTTON_RELEASE_CANCEL) { gint off_x, off_y; if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_ANCHOR) { if (gimp_image_floating_sel (display->image)) { /* If there is a floating selection, anchor it */ floating_sel_anchor (gimp_image_floating_sel (display->image)); } else { /* Otherwise, clear the selection mask */ gimp_channel_clear (gimp_image_get_mask (display->image), NULL, TRUE); } gimp_image_flush (display->image); } else if (region_sel->region_mask) { if (options->sample_merged) { off_x = 0; off_y = 0; } else { GimpDrawable *drawable; drawable = gimp_image_get_active_drawable (display->image); gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y); } gimp_channel_select_channel (gimp_image_get_mask (display->image), GIMP_REGION_SELECT_TOOL_GET_CLASS (tool)->undo_desc, region_sel->region_mask, off_x, off_y, sel_options->operation, sel_options->feather, sel_options->feather_radius, sel_options->feather_radius); gimp_image_flush (display->image); } } if (region_sel->region_mask) { g_object_unref (region_sel->region_mask); region_sel->region_mask = NULL; } if (region_sel->segs) { g_free (region_sel->segs); region_sel->segs = NULL; region_sel->num_segs = 0; } /* Restore the original threshold */ g_object_set (options, "threshold", region_sel->saved_threshold, NULL); }