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 GValueArray * channel_copy_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GValueArray *args) { gboolean success = TRUE; GValueArray *return_vals; GimpChannel *channel; GimpChannel *channel_copy = NULL; channel = gimp_value_get_channel (&args->values[0], gimp); if (success) { channel_copy = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (channel), G_TYPE_FROM_INSTANCE (channel), FALSE)); if (! channel_copy) success = FALSE; } return_vals = gimp_procedure_get_return_values (procedure, success); if (success) gimp_value_set_channel (&return_vals->values[1], channel_copy); return return_vals; }
static void gimp_vectors_mod_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpVectorsModUndo *vectors_mod_undo = GIMP_VECTORS_MOD_UNDO (undo); GimpVectors *vectors = GIMP_VECTORS (GIMP_ITEM_UNDO (undo)->item); GimpVectors *temp; GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); temp = vectors_mod_undo->vectors; vectors_mod_undo->vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors), FALSE)); gimp_vectors_freeze (vectors); gimp_vectors_copy_strokes (temp, vectors); GIMP_ITEM (vectors)->width = GIMP_ITEM (temp)->width; GIMP_ITEM (vectors)->height = GIMP_ITEM (temp)->height; GIMP_ITEM (vectors)->offset_x = GIMP_ITEM (temp)->offset_x; GIMP_ITEM (vectors)->offset_y = GIMP_ITEM (temp)->offset_y; g_object_unref (temp); gimp_vectors_thaw (vectors); }
static GimpValueArray * channel_copy_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GimpValueArray *args, GError **error) { gboolean success = TRUE; GimpValueArray *return_vals; GimpChannel *channel; GimpChannel *channel_copy = NULL; channel = gimp_value_get_channel (gimp_value_array_index (args, 0), gimp); if (success) { channel_copy = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (channel), G_TYPE_FROM_INSTANCE (channel))); if (! channel_copy) success = FALSE; } return_vals = gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); if (success) gimp_value_set_channel (gimp_value_array_index (return_vals, 1), channel_copy); return return_vals; }
void vectors_duplicate_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; GimpVectors *vectors; GimpVectors *new_vectors; return_if_no_vectors (image, vectors, data); new_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors))); gimp_image_add_vectors (image, new_vectors, -1); gimp_image_flush (image); }
/** * gimp_item_convert: * @item: The #GimpItem to convert. * @dest_image: The #GimpImage in which to place the converted item. * @new_type: The type to convert the item to. * * Returns: the new item that results from the conversion. */ GimpItem * gimp_item_convert (GimpItem *item, GimpImage *dest_image, GType new_type) { GimpItem *new_item; g_return_val_if_fail (GIMP_IS_ITEM (item), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (item->image), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL); g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_ITEM), NULL); new_item = gimp_item_duplicate (item, new_type); if (new_item) GIMP_ITEM_GET_CLASS (new_item)->convert (new_item, dest_image); return new_item; }
void vectors_duplicate_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; GimpVectors *vectors; GimpVectors *new_vectors; return_if_no_vectors (image, vectors, data); new_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors))); /* use the actual parent here, not GIMP_IMAGE_ACTIVE_PARENT because * the latter would add a duplicated group inside itself instead of * above it */ gimp_image_add_vectors (image, new_vectors, gimp_vectors_get_parent (vectors), -1, TRUE); gimp_image_flush (image); }
static GObject * gimp_vectors_mod_undo_constructor (GType type, guint n_params, GObjectConstructParam *params) { GObject *object; GimpVectorsModUndo *vectors_mod_undo; GimpVectors *vectors; object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params); vectors_mod_undo = GIMP_VECTORS_MOD_UNDO (object); g_assert (GIMP_IS_VECTORS (GIMP_ITEM_UNDO (object)->item)); vectors = GIMP_VECTORS (GIMP_ITEM_UNDO (object)->item); vectors_mod_undo->vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors), FALSE)); return object; }
static void gimp_image_duplicate_floating_sel (GimpImage *image, GimpImage *new_image) { GimpLayer *floating_sel; GimpDrawable *floating_sel_drawable; GList *floating_sel_path; GimpItemStack *new_item_stack; GimpLayer *new_floating_sel; GimpDrawable *new_floating_sel_drawable; floating_sel = gimp_image_get_floating_selection (image); if (! floating_sel) return; floating_sel_drawable = gimp_layer_get_floating_sel_drawable (floating_sel); if (GIMP_IS_LAYER_MASK (floating_sel_drawable)) { GimpLayer *layer; layer = gimp_layer_mask_get_layer (GIMP_LAYER_MASK (floating_sel_drawable)); floating_sel_path = gimp_item_get_path (GIMP_ITEM (layer)); new_item_stack = GIMP_ITEM_STACK (gimp_image_get_layers (new_image)); } else { floating_sel_path = gimp_item_get_path (GIMP_ITEM (floating_sel_drawable)); if (GIMP_IS_LAYER (floating_sel_drawable)) new_item_stack = GIMP_ITEM_STACK (gimp_image_get_layers (new_image)); else new_item_stack = GIMP_ITEM_STACK (gimp_image_get_channels (new_image)); } /* adjust path[0] for the floating layer missing in new_image */ floating_sel_path->data = GUINT_TO_POINTER (GPOINTER_TO_UINT (floating_sel_path->data) - 1); if (GIMP_IS_LAYER (floating_sel_drawable)) { new_floating_sel = GIMP_LAYER (gimp_image_duplicate_item (GIMP_ITEM (floating_sel), new_image)); } else { /* can't use gimp_item_convert() for floating selections of channels * or layer masks because they maybe don't have a normal layer's type */ new_floating_sel = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (floating_sel), G_TYPE_FROM_INSTANCE (floating_sel))); gimp_item_set_image (GIMP_ITEM (new_floating_sel), new_image); gimp_object_set_name (GIMP_OBJECT (new_floating_sel), gimp_object_get_name (floating_sel)); } /* Make sure the copied layer doesn't say: "<old layer> copy" */ gimp_object_set_name (GIMP_OBJECT (new_floating_sel), gimp_object_get_name (floating_sel)); new_floating_sel_drawable = GIMP_DRAWABLE (gimp_item_stack_get_item_by_path (new_item_stack, floating_sel_path)); if (GIMP_IS_LAYER_MASK (floating_sel_drawable)) new_floating_sel_drawable = GIMP_DRAWABLE (gimp_layer_get_mask (GIMP_LAYER (new_floating_sel_drawable))); floating_sel_attach (new_floating_sel, new_floating_sel_drawable); g_list_free (floating_sel_path); }
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); }
GimpVectors * gimp_image_merge_visible_vectors (GimpImage *image, GError **error) { GList *list = NULL; GSList *merge_list = NULL; GSList *cur_item = NULL; GimpVectors *vectors = NULL; GimpVectors *target_vectors = NULL; gchar *name = NULL; gint pos = 0; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); for (list = GIMP_LIST (image->vectors)->list; list; list = g_list_next (list)) { vectors = list->data; if (gimp_item_get_visible (GIMP_ITEM (vectors))) merge_list = g_slist_append (merge_list, vectors); } if (merge_list && merge_list->next) { gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_VECTORS_MERGE, _("Merge Visible Paths")); cur_item = merge_list; vectors = GIMP_VECTORS (cur_item->data); name = g_strdup (gimp_object_get_name (GIMP_OBJECT (vectors))); target_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), GIMP_TYPE_VECTORS)); pos = gimp_image_get_vectors_index (image, vectors); gimp_image_remove_vectors (image, vectors); cur_item = cur_item->next; while (cur_item) { vectors = GIMP_VECTORS (cur_item->data); gimp_vectors_add_strokes (vectors, target_vectors); gimp_image_remove_vectors (image, vectors); cur_item = g_slist_next (cur_item); } gimp_object_take_name (GIMP_OBJECT (target_vectors), name); g_slist_free (merge_list); gimp_image_add_vectors (image, target_vectors, pos); gimp_unset_busy (image->gimp); gimp_image_undo_group_end (image); return target_vectors; } else { g_set_error (error, 0, 0, _("Not enough visible paths for a merge. " "There must be at least two.")); return NULL; } }
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; } }
static void gimp_warp_tool_animate (GimpWarpTool *wt) { GimpTool *tool = GIMP_TOOL (wt); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GimpImage *orig_image; GimpImage *image; GimpLayer *layer; GimpLayer *first_layer; GeglNode *scale_node; GimpProgress *progress; GtkWidget *widget; gint i; if (! gimp_warp_tool_get_undo_desc (tool, tool->display)) { gimp_tool_message_literal (tool, tool->display, _("Please add some warp strokes first.")); return; } /* get rid of the image map so we can use wt->graph */ if (wt->image_map) { gimp_image_map_abort (wt->image_map); g_object_unref (wt->image_map); wt->image_map = NULL; } gimp_progress_start (GIMP_PROGRESS (tool), FALSE, _("Rendering Frame %d"), 1); orig_image = gimp_item_get_image (GIMP_ITEM (tool->drawable)); image = gimp_create_image (orig_image->gimp, gimp_item_get_width (GIMP_ITEM (tool->drawable)), gimp_item_get_height (GIMP_ITEM (tool->drawable)), gimp_drawable_get_base_type (tool->drawable), gimp_drawable_get_precision (tool->drawable), TRUE); /* the first frame is always the unwarped image */ layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (tool->drawable), image, GIMP_TYPE_LAYER)); gimp_object_take_name (GIMP_OBJECT (layer), g_strdup_printf (_("Frame %d"), 1)); gimp_item_set_offset (GIMP_ITEM (layer), 0, 0); gimp_item_set_visible (GIMP_ITEM (layer), TRUE, FALSE); gimp_layer_set_mode (layer, GIMP_NORMAL_MODE, FALSE); gimp_layer_set_opacity (layer, GIMP_OPACITY_OPAQUE, FALSE); gimp_image_add_layer (image, layer, NULL, 0, FALSE); first_layer = layer; scale_node = gegl_node_new_child (NULL, "operation", "gimp:scalar-multiply", "n-components", 2, NULL); gimp_warp_tool_add_op (wt, scale_node); progress = gimp_sub_progress_new (GIMP_PROGRESS (tool)); for (i = 1; i < options->n_animation_frames; i++) { gimp_progress_set_text (GIMP_PROGRESS (tool), _("Rendering Frame %d"), i + 1); gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), i, options->n_animation_frames); layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (first_layer), GIMP_TYPE_LAYER)); gimp_object_take_name (GIMP_OBJECT (layer), g_strdup_printf (_("Frame %d"), i + 1)); gegl_node_set (scale_node, "factor", (gdouble) i / (gdouble) (options->n_animation_frames - 1), NULL); gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (first_layer)), progress, _("Frame"), wt->graph, gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)), NULL); gimp_image_add_layer (image, layer, NULL, 0, FALSE); } g_object_unref (progress); gimp_warp_tool_remove_op (wt, scale_node); gimp_progress_end (GIMP_PROGRESS (tool)); /* recreate the image map */ gimp_warp_tool_create_image_map (wt, tool->drawable); gimp_image_map_apply (wt->image_map, NULL); widget = GTK_WIDGET (gimp_display_get_shell (tool->display)); gimp_create_display (orig_image->gimp, image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (image); }