GimpLayer * gimp_image_merge_group_layer (GimpImage *image, GimpGroupLayer *group) { GimpLayer *parent; GimpLayer *layer; gint index; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_GROUP_LAYER (group), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (group)), NULL); g_return_val_if_fail (gimp_item_get_image (GIMP_ITEM (group)) == image, NULL); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, C_("undo-type", "Merge Layer Group")); parent = gimp_layer_get_parent (GIMP_LAYER (group)); index = gimp_item_get_index (GIMP_ITEM (group)); layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (group), GIMP_TYPE_LAYER)); gimp_object_set_name (GIMP_OBJECT (layer), gimp_object_get_name (group)); gimp_image_remove_layer (image, GIMP_LAYER (group), TRUE, NULL); gimp_image_add_layer (image, layer, parent, index, TRUE); gimp_image_undo_group_end (image); return layer; }
static void gimp_item_prop_undo_constructed (GObject *object) { GimpItemPropUndo *item_prop_undo = GIMP_ITEM_PROP_UNDO (object); GimpItem *item; G_OBJECT_CLASS (parent_class)->constructed (object); item = GIMP_ITEM_UNDO (object)->item; switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_ITEM_REORDER: item_prop_undo->parent = gimp_item_get_parent (item); item_prop_undo->position = gimp_item_get_index (item); break; case GIMP_UNDO_ITEM_RENAME: item_prop_undo->name = g_strdup (gimp_object_get_name (item)); break; case GIMP_UNDO_ITEM_DISPLACE: gimp_item_get_offset (item, &item_prop_undo->offset_x, &item_prop_undo->offset_y); break; case GIMP_UNDO_ITEM_VISIBILITY: item_prop_undo->visible = gimp_item_get_visible (item); break; case GIMP_UNDO_ITEM_LINKED: item_prop_undo->linked = gimp_item_get_linked (item); break; case GIMP_UNDO_ITEM_COLOR_TAG: item_prop_undo->color_tag = gimp_item_get_color_tag (item); break; case GIMP_UNDO_ITEM_LOCK_CONTENT: item_prop_undo->lock_content = gimp_item_get_lock_content (item); break; case GIMP_UNDO_ITEM_LOCK_POSITION: item_prop_undo->lock_position = gimp_item_get_lock_position (item); break; case GIMP_UNDO_PARASITE_ATTACH: case GIMP_UNDO_PARASITE_REMOVE: g_assert (item_prop_undo->parasite_name != NULL); item_prop_undo->parasite = gimp_parasite_copy (gimp_item_parasite_find (item, item_prop_undo->parasite_name)); break; default: g_assert_not_reached (); } }
static void gimp_channel_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpChannelUndo *channel_undo = GIMP_CHANNEL_UNDO (undo); GimpChannel *channel = GIMP_CHANNEL (GIMP_ITEM_UNDO (undo)->item); GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); if ((undo_mode == GIMP_UNDO_MODE_UNDO && undo->undo_type == GIMP_UNDO_CHANNEL_ADD) || (undo_mode == GIMP_UNDO_MODE_REDO && undo->undo_type == GIMP_UNDO_CHANNEL_REMOVE)) { /* remove channel */ /* record the current parent and position */ channel_undo->prev_parent = gimp_channel_get_parent (channel); channel_undo->prev_position = gimp_item_get_index (GIMP_ITEM (channel)); gimp_image_remove_channel (undo->image, channel, FALSE, channel_undo->prev_channel); } else { /* restore channel */ /* record the active channel */ channel_undo->prev_channel = gimp_image_get_active_channel (undo->image); gimp_image_add_channel (undo->image, channel, channel_undo->prev_parent, channel_undo->prev_position, FALSE); } }
static void gimp_item_prop_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpItemPropUndo *item_prop_undo = GIMP_ITEM_PROP_UNDO (undo); GimpItem *item = GIMP_ITEM_UNDO (undo)->item; GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { case GIMP_UNDO_ITEM_REORDER: { GimpItem *parent; gint position; parent = gimp_item_get_parent (item); position = gimp_item_get_index (item); gimp_item_tree_reorder_item (gimp_item_get_tree (item), item, item_prop_undo->parent, item_prop_undo->position, FALSE, NULL); item_prop_undo->parent = parent; item_prop_undo->position = position; } break; case GIMP_UNDO_ITEM_RENAME: { gchar *name; name = g_strdup (gimp_object_get_name (item)); gimp_item_tree_rename_item (gimp_item_get_tree (item), item, item_prop_undo->name, FALSE, NULL); g_free (item_prop_undo->name); item_prop_undo->name = name; } break; case GIMP_UNDO_ITEM_DISPLACE: { gint offset_x; gint offset_y; gimp_item_get_offset (item, &offset_x, &offset_y); gimp_item_translate (item, item_prop_undo->offset_x - offset_x, item_prop_undo->offset_y - offset_y, FALSE); item_prop_undo->offset_x = offset_x; item_prop_undo->offset_y = offset_y; } break; case GIMP_UNDO_ITEM_VISIBILITY: { gboolean visible; visible = gimp_item_get_visible (item); gimp_item_set_visible (item, item_prop_undo->visible, FALSE); item_prop_undo->visible = visible; } break; case GIMP_UNDO_ITEM_LINKED: { gboolean linked; linked = gimp_item_get_linked (item); gimp_item_set_linked (item, item_prop_undo->linked, FALSE); item_prop_undo->linked = linked; } break; case GIMP_UNDO_ITEM_COLOR_TAG: { GimpColorTag color_tag; color_tag = gimp_item_get_color_tag (item); gimp_item_set_color_tag (item, item_prop_undo->color_tag, FALSE); item_prop_undo->color_tag = color_tag; } break; case GIMP_UNDO_ITEM_LOCK_CONTENT: { gboolean lock_content; lock_content = gimp_item_get_lock_content (item); gimp_item_set_lock_content (item, item_prop_undo->lock_content, FALSE); item_prop_undo->lock_content = lock_content; } break; case GIMP_UNDO_ITEM_LOCK_POSITION: { gboolean lock_position; lock_position = gimp_item_get_lock_position (item); gimp_item_set_lock_position (item, item_prop_undo->lock_position, FALSE); item_prop_undo->lock_position = lock_position; } break; case GIMP_UNDO_PARASITE_ATTACH: case GIMP_UNDO_PARASITE_REMOVE: { GimpParasite *parasite; parasite = item_prop_undo->parasite; item_prop_undo->parasite = gimp_parasite_copy (gimp_item_parasite_find (item, item_prop_undo->parasite_name)); if (parasite) gimp_item_parasite_attach (item, parasite, FALSE); else gimp_item_parasite_detach (item, item_prop_undo->parasite_name, FALSE); if (parasite) gimp_parasite_free (parasite); } break; default: g_assert_not_reached (); } }
GimpVectors * gimp_image_merge_visible_vectors (GimpImage *image, GError **error) { GList *list; GList *merge_list = NULL; GimpVectors *vectors; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); for (list = gimp_image_get_vectors_iter (image); list; list = g_list_next (list)) { vectors = list->data; if (gimp_item_get_visible (GIMP_ITEM (vectors))) merge_list = g_list_prepend (merge_list, vectors); } merge_list = g_list_reverse (merge_list); if (merge_list && merge_list->next) { GimpVectors *target_vectors; gchar *name; gint pos; gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_VECTORS_MERGE, C_("undo-type", "Merge Visible Paths")); vectors = GIMP_VECTORS (merge_list->data); name = g_strdup (gimp_object_get_name (vectors)); pos = gimp_item_get_index (GIMP_ITEM (vectors)); target_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), GIMP_TYPE_VECTORS)); gimp_image_remove_vectors (image, vectors, TRUE, NULL); for (list = g_list_next (merge_list); list; list = g_list_next (list)) { vectors = list->data; gimp_vectors_add_strokes (vectors, target_vectors); gimp_image_remove_vectors (image, vectors, TRUE, NULL); } gimp_object_take_name (GIMP_OBJECT (target_vectors), name); g_list_free (merge_list); /* FIXME tree */ gimp_image_add_vectors (image, target_vectors, NULL, pos, TRUE); gimp_unset_busy (image->gimp); gimp_image_undo_group_end (image); return target_vectors; } else { g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("Not enough visible paths for a merge. " "There must be at least two.")); return NULL; } }
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; }