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; }
GimpLayer * gimp_layer_new (GimpImage *image, gint width, gint height, const Babl *format, const gchar *name, gdouble opacity, GimpLayerModeEffects mode) { GimpLayer *layer; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (height > 0, NULL); g_return_val_if_fail (format != NULL, NULL); layer = GIMP_LAYER (gimp_drawable_new (GIMP_TYPE_LAYER, image, name, 0, 0, width, height, format)); opacity = CLAMP (opacity, GIMP_OPACITY_TRANSPARENT, GIMP_OPACITY_OPAQUE); layer->opacity = opacity; layer->mode = mode; return layer; }
static void gimp_layer_prop_undo_constructed (GObject *object) { GimpLayerPropUndo *layer_prop_undo = GIMP_LAYER_PROP_UNDO (object); GimpLayer *layer; G_OBJECT_CLASS (parent_class)->constructed (object); g_assert (GIMP_IS_LAYER (GIMP_ITEM_UNDO (object)->item)); layer = GIMP_LAYER (GIMP_ITEM_UNDO (object)->item); switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_LAYER_MODE: layer_prop_undo->mode = gimp_layer_get_mode (layer); break; case GIMP_UNDO_LAYER_OPACITY: layer_prop_undo->opacity = gimp_layer_get_opacity (layer); break; case GIMP_UNDO_LAYER_LOCK_ALPHA: layer_prop_undo->lock_alpha = gimp_layer_get_lock_alpha (layer); break; default: g_assert_not_reached (); } }
static void gimp_layer_mask_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpLayerMaskUndo *layer_mask_undo = GIMP_LAYER_MASK_UNDO (undo); GimpLayer *layer = GIMP_LAYER (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_LAYER_MASK_ADD) || (undo_mode == GIMP_UNDO_MODE_REDO && undo->undo_type == GIMP_UNDO_LAYER_MASK_REMOVE)) { /* remove layer mask */ gimp_layer_apply_mask (layer, GIMP_MASK_DISCARD, FALSE); } else { /* restore layer mask */ gimp_layer_add_mask (layer, layer_mask_undo->layer_mask, FALSE, NULL); } }
/** * gimp_text_layer_new: * @image: the #GimpImage the layer should belong to * @text: a #GimpText object * * Creates a new text layer. * * Return value: a new #GimpTextLayer or %NULL in case of a problem **/ GimpLayer * gimp_text_layer_new (GimpImage *image, GimpText *text) { GimpTextLayer *layer; GimpImageType type; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); if (! text->text && ! text->markup) return NULL; type = gimp_image_base_type_with_alpha (image); layer = GIMP_TEXT_LAYER (gimp_drawable_new (GIMP_TYPE_TEXT_LAYER, image, NULL, 0, 0, 1, 1, type)); gimp_text_layer_set_text (layer, text); if (! gimp_text_layer_render (layer)) { g_object_unref (layer); return NULL; } return GIMP_LAYER (layer); }
void floating_sel_activate_drawable (GimpLayer *layer) { GimpImage *image; GimpDrawable *drawable; g_return_if_fail (GIMP_IS_LAYER (layer)); g_return_if_fail (gimp_layer_is_floating_sel (layer)); image = gimp_item_get_image (GIMP_ITEM (layer)); drawable = gimp_layer_get_floating_sel_drawable (layer); /* set the underlying drawable to active */ if (GIMP_IS_LAYER_MASK (drawable)) { GimpLayerMask *mask = GIMP_LAYER_MASK (drawable); gimp_image_set_active_layer (image, gimp_layer_mask_get_layer (mask)); } else if (GIMP_IS_CHANNEL (drawable)) { gimp_image_set_active_channel (image, GIMP_CHANNEL (drawable)); } else { gimp_image_set_active_layer (image, GIMP_LAYER (drawable)); } }
/** * gimp_text_layer_new: * @image: the #GimpImage the layer should belong to * @text: a #GimpText object * * Creates a new text layer. * * Return value: a new #GimpTextLayer or %NULL in case of a problem **/ GimpLayer * gimp_text_layer_new (GimpImage *image, GimpText *text) { GimpTextLayer *layer; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); if (! text->text && ! text->markup) return NULL; layer = GIMP_TEXT_LAYER (gimp_drawable_new (GIMP_TYPE_TEXT_LAYER, image, NULL, 0, 0, 1, 1, gimp_image_get_layer_format (image, TRUE))); gimp_text_layer_set_text (layer, text); if (! gimp_text_layer_render (layer)) { g_object_unref (layer); return NULL; } return GIMP_LAYER (layer); }
static void gimp_layer_mask_prop_undo_constructed (GObject *object) { GimpLayerMaskPropUndo *layer_mask_prop_undo; GimpLayer *layer; layer_mask_prop_undo = GIMP_LAYER_MASK_PROP_UNDO (object); G_OBJECT_CLASS (parent_class)->constructed (object); g_assert (GIMP_IS_LAYER (GIMP_ITEM_UNDO (object)->item)); layer = GIMP_LAYER (GIMP_ITEM_UNDO (object)->item); switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_LAYER_MASK_APPLY: layer_mask_prop_undo->apply = gimp_layer_get_apply_mask (layer); break; case GIMP_UNDO_LAYER_MASK_SHOW: layer_mask_prop_undo->show = gimp_layer_get_show_mask (layer); break; default: g_assert_not_reached (); } }
static void gimp_view_renderer_layer_render (GimpViewRenderer *renderer, GtkWidget *widget) { const gchar *icon_name = NULL; if (gimp_layer_is_floating_sel (GIMP_LAYER (renderer->viewable))) { icon_name = GIMP_STOCK_FLOATING_SELECTION; } else if (gimp_item_is_text_layer (GIMP_ITEM (renderer->viewable))) { icon_name = gimp_viewable_get_icon_name (renderer->viewable); } else { GimpContainer *children = gimp_viewable_get_children (renderer->viewable); if (children && gimp_container_get_n_children (children) == 0) icon_name = "folder"; } if (icon_name) gimp_view_renderer_render_icon (renderer, widget, icon_name); else GIMP_VIEW_RENDERER_CLASS (parent_class)->render (renderer, widget); }
void gimp_text_layer_rotate (GimpItem *item, GimpContext *context, GimpRotationType rotate_type, gdouble center_x, gdouble center_y, gboolean clip_result) { GimpTextLayer *layer = GIMP_TEXT_LAYER (item); if (! gimp_text_layer_transform_rotate (layer, rotate_type, center_x, center_y)) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (layer)); if (mask) gimp_item_rotate (GIMP_ITEM (mask), context, rotate_type, center_x, center_y, clip_result); } else { gimp_text_layer_parent_class ()->rotate (item, context, rotate_type, center_x, center_y, clip_result); } }
static void gimp_display_shell_drop_component (GtkWidget *widget, gint x, gint y, GimpImage *image, GimpChannelType component, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *dest_image = gimp_display_get_image (shell->display); GimpChannel *channel; GimpItem *new_item; const gchar *desc; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! dest_image) { dest_image = gimp_image_new_from_component (image->gimp, image, component); gimp_create_display (dest_image->gimp, dest_image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (dest_image); return; } channel = gimp_channel_new_from_component (image, component, NULL, NULL); new_item = gimp_item_convert (GIMP_ITEM (channel), dest_image, GIMP_TYPE_LAYER); g_object_unref (channel); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_enum_get_value (GIMP_TYPE_CHANNEL_TYPE, component, NULL, NULL, &desc, NULL); gimp_object_take_name (GIMP_OBJECT (new_layer), g_strdup_printf (_("%s Channel Copy"), desc)); gimp_image_undo_group_start (dest_image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); gimp_display_shell_dnd_position_item (shell, image, new_item); gimp_image_add_layer (dest_image, new_layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_undo_group_end (dest_image); gimp_display_shell_dnd_flush (shell, dest_image); } }
static void gimp_layer_prop_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpLayerPropUndo *layer_prop_undo = GIMP_LAYER_PROP_UNDO (undo); GimpLayer *layer = GIMP_LAYER (GIMP_ITEM_UNDO (undo)->item); GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { case GIMP_UNDO_LAYER_REPOSITION: { gint position; position = gimp_image_get_layer_index (undo->image, layer); gimp_image_position_layer (undo->image, layer, layer_prop_undo->position, FALSE, NULL); layer_prop_undo->position = position; } break; case GIMP_UNDO_LAYER_MODE: { GimpLayerModeEffects mode; mode = gimp_layer_get_mode (layer); gimp_layer_set_mode (layer, layer_prop_undo->mode, FALSE); layer_prop_undo->mode = mode; } break; case GIMP_UNDO_LAYER_OPACITY: { gdouble opacity; opacity = gimp_layer_get_opacity (layer); gimp_layer_set_opacity (layer, layer_prop_undo->opacity, FALSE); layer_prop_undo->opacity = opacity; } break; case GIMP_UNDO_LAYER_LOCK_ALPHA: { gboolean lock_alpha; lock_alpha = gimp_layer_get_lock_alpha (layer); gimp_layer_set_lock_alpha (layer, layer_prop_undo->lock_alpha, FALSE); layer_prop_undo->lock_alpha = lock_alpha; } break; default: g_assert_not_reached (); } }
static void gimp_display_shell_drop_drawable (GtkWidget *widget, gint x, gint y, GimpViewable *viewable, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = gimp_display_get_image (shell->display); GType new_type; GimpItem *new_item; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) { image = gimp_image_new_from_drawable (shell->display->gimp, GIMP_DRAWABLE (viewable)); gimp_create_display (shell->display->gimp, image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (image); return; } if (GIMP_IS_LAYER (viewable)) new_type = G_TYPE_FROM_INSTANCE (viewable); else new_type = GIMP_TYPE_LAYER; new_item = gimp_item_convert (GIMP_ITEM (viewable), image, new_type); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); gimp_display_shell_dnd_position_item (shell, image, new_item); gimp_item_set_visible (new_item, TRUE, FALSE); gimp_item_set_linked (new_item, FALSE, FALSE); gimp_image_add_layer (image, new_layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } }
GimpObject * gimp_edit_cut (GimpImage *image, GimpDrawable *drawable, GimpContext *context, GError **error) { g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); 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 (error == NULL || *error == NULL, NULL); if (GIMP_IS_LAYER (drawable) && gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpImage *clip_image; clip_image = gimp_image_new_from_drawable (image->gimp, drawable); gimp_container_remove (image->gimp->images, GIMP_OBJECT (clip_image)); gimp_set_clipboard_image (image->gimp, clip_image); g_object_unref (clip_image); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_CUT, C_("undo-type", "Cut Layer")); gimp_image_remove_layer (image, GIMP_LAYER (drawable), TRUE, NULL); gimp_image_undo_group_end (image); return GIMP_OBJECT (gimp_get_clipboard_image (image->gimp)); } else { GimpBuffer *buffer; buffer = gimp_edit_extract (image, GIMP_PICKABLE (drawable), context, TRUE, error); if (buffer) { gimp_set_clipboard_buffer (image->gimp, buffer); g_object_unref (buffer); return GIMP_OBJECT (gimp_get_clipboard_buffer (image->gimp)); } } return NULL; }
static gint64 gimp_layer_mask_undo_get_memsize (GimpObject *object, gint64 *gui_size) { GimpLayerMaskUndo *layer_mask_undo = GIMP_LAYER_MASK_UNDO (object); GimpLayer *layer = GIMP_LAYER (GIMP_ITEM_UNDO (object)->item); gint64 memsize = 0; /* don't use !gimp_item_is_attached() here */ if (gimp_layer_get_mask (layer) != layer_mask_undo->layer_mask) memsize += gimp_object_get_memsize (GIMP_OBJECT (layer_mask_undo->layer_mask), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static void gimp_floating_sel_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpFloatingSelUndo *floating_sel_undo = GIMP_FLOATING_SEL_UNDO (undo); GimpLayer *floating_layer = GIMP_LAYER (GIMP_ITEM_UNDO (undo)->item); GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { case GIMP_UNDO_FS_TO_LAYER: if (undo_mode == GIMP_UNDO_MODE_UNDO) { /* Update the preview for the floating sel */ gimp_viewable_invalidate_preview (GIMP_VIEWABLE (floating_layer)); gimp_layer_set_floating_sel_drawable (floating_layer, floating_sel_undo->drawable); gimp_image_set_active_layer (undo->image, floating_layer); gimp_drawable_attach_floating_sel (gimp_layer_get_floating_sel_drawable (floating_layer), floating_layer); } else { gimp_drawable_detach_floating_sel (gimp_layer_get_floating_sel_drawable (floating_layer)); gimp_layer_set_floating_sel_drawable (floating_layer, NULL); } /* When the floating selection is converted to/from a normal * layer it does something resembling a name change, so emit the * "name-changed" signal */ gimp_object_name_changed (GIMP_OBJECT (floating_layer)); gimp_drawable_update (GIMP_DRAWABLE (floating_layer), 0, 0, gimp_item_get_width (GIMP_ITEM (floating_layer)), gimp_item_get_height (GIMP_ITEM (floating_layer))); break; default: g_assert_not_reached (); } }
static GObject * gimp_layer_prop_undo_constructor (GType type, guint n_params, GObjectConstructParam *params) { GObject *object; GimpLayerPropUndo *layer_prop_undo; GimpImage *image; GimpLayer *layer; object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params); layer_prop_undo = GIMP_LAYER_PROP_UNDO (object); g_assert (GIMP_IS_LAYER (GIMP_ITEM_UNDO (object)->item)); image = GIMP_UNDO (object)->image; layer = GIMP_LAYER (GIMP_ITEM_UNDO (object)->item); switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_LAYER_REPOSITION: layer_prop_undo->position = gimp_image_get_layer_index (image, layer); break; case GIMP_UNDO_LAYER_MODE: layer_prop_undo->mode = gimp_layer_get_mode (layer); break; case GIMP_UNDO_LAYER_OPACITY: layer_prop_undo->opacity = gimp_layer_get_opacity (layer); break; case GIMP_UNDO_LAYER_LOCK_ALPHA: layer_prop_undo->lock_alpha = gimp_layer_get_lock_alpha (layer); break; default: g_assert_not_reached (); } return object; }
static void gimp_view_renderer_layer_render (GimpViewRenderer *renderer, GtkWidget *widget) { const gchar *stock_id = NULL; if (gimp_layer_is_floating_sel (GIMP_LAYER (renderer->viewable))) { stock_id = GIMP_STOCK_FLOATING_SELECTION; } else if (gimp_drawable_is_text_layer (GIMP_DRAWABLE (renderer->viewable))) { stock_id = gimp_viewable_get_stock_id (renderer->viewable); } if (stock_id) gimp_view_renderer_default_render_stock (renderer, widget, stock_id); else GIMP_VIEW_RENDERER_CLASS (parent_class)->render (renderer, widget); }
static void gimp_floating_sel_undo_constructed (GObject *object) { GimpFloatingSelUndo *floating_sel_undo = GIMP_FLOATING_SEL_UNDO (object); GimpLayer *layer; G_OBJECT_CLASS (parent_class)->constructed (object); g_assert (GIMP_IS_LAYER (GIMP_ITEM_UNDO (object)->item)); layer = GIMP_LAYER (GIMP_ITEM_UNDO (object)->item); switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_FS_TO_LAYER: floating_sel_undo->drawable = gimp_layer_get_floating_sel_drawable (layer); break; default: g_assert_not_reached (); } }
void gimp_text_layer_flip (GimpItem *item, GimpContext *context, GimpOrientationType flip_type, gdouble axis, gboolean clip_result) { GimpTextLayer *layer = GIMP_TEXT_LAYER (item); if (gimp_text_layer_transform_flip (layer, flip_type, axis)) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (layer)); if (mask) gimp_item_flip (GIMP_ITEM (mask), context, flip_type, axis, clip_result); } else { gimp_text_layer_parent_class ()->flip (item, context, flip_type, axis, clip_result); } }
/** * gimp_text_layer_from_layer: * @layer: a #GimpLayer object * @text: a #GimpText object * * Converts a standard #GimpLayer and a #GimpText object into a * #GimpTextLayer. The new text layer takes ownership of the @text and * @layer objects. The @layer object is rendered unusable by this * function. Don't even try to use if afterwards! * * This is a gross hack that is needed in order to load text layers * from XCF files in a backwards-compatible way. Please don't use it * for anything else! * * Return value: a newly allocated #GimpTextLayer object **/ static GimpLayer * gimp_text_layer_from_layer (GimpLayer *layer, GimpText *text) { GimpTextLayer *text_layer; GimpDrawable *drawable; g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); text_layer = g_object_new (GIMP_TYPE_TEXT_LAYER, "image", gimp_item_get_image (GIMP_ITEM (layer)), NULL); gimp_item_replace_item (GIMP_ITEM (text_layer), GIMP_ITEM (layer)); drawable = GIMP_DRAWABLE (text_layer); gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (layer)); gimp_layer_set_opacity (GIMP_LAYER (text_layer), gimp_layer_get_opacity (layer), FALSE); gimp_layer_set_mode (GIMP_LAYER (text_layer), gimp_layer_get_mode (layer), FALSE); gimp_layer_set_blend_space (GIMP_LAYER (text_layer), gimp_layer_get_blend_space (layer), FALSE); gimp_layer_set_composite_space (GIMP_LAYER (text_layer), gimp_layer_get_composite_space (layer), FALSE); gimp_layer_set_composite_mode (GIMP_LAYER (text_layer), gimp_layer_get_composite_mode (layer), FALSE); gimp_layer_set_lock_alpha (GIMP_LAYER (text_layer), gimp_layer_get_lock_alpha (layer), FALSE); gimp_text_layer_set_text (text_layer, text); g_object_unref (text); g_object_unref (layer); return GIMP_LAYER (text_layer); }
static GimpLayer * gimp_image_duplicate_layers (GimpImage *image, GimpImage *new_image) { GimpLayer *active_layer = NULL; GList *list; gint count; for (list = gimp_image_get_layer_iter (image), count = 0; list; list = g_list_next (list)) { GimpLayer *layer = list->data; GimpLayer *new_layer; if (gimp_layer_is_floating_sel (layer)) continue; new_layer = GIMP_LAYER (gimp_image_duplicate_item (GIMP_ITEM (layer), new_image)); /* Make sure that if the layer has a layer mask, * its name isn't screwed up */ if (new_layer->mask) gimp_object_set_name (GIMP_OBJECT (new_layer->mask), gimp_object_get_name (layer->mask)); if (gimp_image_get_active_layer (image) == layer) active_layer = new_layer; gimp_image_add_layer (new_image, new_layer, NULL, count++, FALSE); } return active_layer; }
static void gimp_layer_mask_prop_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpLayerMaskPropUndo *layer_mask_prop_undo = GIMP_LAYER_MASK_PROP_UNDO (undo); GimpLayer *layer = GIMP_LAYER (GIMP_ITEM_UNDO (undo)->item); GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { case GIMP_UNDO_LAYER_MASK_APPLY: { gboolean apply; apply = gimp_layer_get_apply_mask (layer); gimp_layer_set_apply_mask (layer, layer_mask_prop_undo->apply, FALSE); layer_mask_prop_undo->apply = apply; } break; case GIMP_UNDO_LAYER_MASK_SHOW: { gboolean show; show = gimp_layer_get_show_mask (layer); gimp_layer_set_show_mask (layer, layer_mask_prop_undo->show, FALSE); layer_mask_prop_undo->show = show; } break; default: g_assert_not_reached (); } }
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); }
static void gimp_display_shell_drop_drawable (GtkWidget *widget, gint x, gint y, GimpViewable *viewable, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = shell->display->image; GType new_type; GimpItem *new_item; gboolean new_image = FALSE; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) { GimpImage *src_image = gimp_item_get_image (GIMP_ITEM (viewable)); GimpDrawable *drawable = GIMP_DRAWABLE (viewable); GimpImageBaseType type; gdouble xres; gdouble yres; type = GIMP_IMAGE_TYPE_BASE_TYPE (gimp_drawable_type (drawable)); image = gimp_create_image (shell->display->gimp, gimp_item_width (GIMP_ITEM (viewable)), gimp_item_height (GIMP_ITEM (viewable)), type, TRUE); gimp_image_undo_disable (image); if (type == GIMP_INDEXED) gimp_image_set_colormap (image, gimp_image_get_colormap (src_image), gimp_image_get_colormap_size (src_image), FALSE); gimp_image_get_resolution (src_image, &xres, &yres); gimp_image_set_resolution (image, xres, yres); gimp_image_set_unit (image, gimp_image_get_unit (src_image)); gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0); g_object_unref (image); new_image = TRUE; } if (GIMP_IS_LAYER (viewable)) new_type = G_TYPE_FROM_INSTANCE (viewable); else new_type = GIMP_TYPE_LAYER; new_item = gimp_item_convert (GIMP_ITEM (viewable), image, new_type); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); if (! new_image) gimp_display_shell_dnd_position_item (shell, new_item); gimp_item_set_visible (new_item, TRUE, FALSE); gimp_item_set_linked (new_item, FALSE, FALSE); gimp_image_add_layer (image, new_layer, -1); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } if (new_image) gimp_image_undo_enable (image); }
GimpDrawable * gimp_drawable_transform_rotate (GimpDrawable *drawable, GimpContext *context, GimpRotationType rotate_type, gdouble center_x, gdouble center_y, gboolean clip_result) { GimpImage *image; GeglBuffer *orig_buffer; gint orig_offset_x; gint orig_offset_y; gboolean new_layer; GimpDrawable *result = NULL; 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); image = gimp_item_get_image (GIMP_ITEM (drawable)); /* Start a transform undo group */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM, C_("undo-type", "Rotate")); /* Cut/Copy from the specified drawable */ orig_buffer = gimp_drawable_transform_cut (drawable, context, &orig_offset_x, &orig_offset_y, &new_layer); if (orig_buffer) { GeglBuffer *new_buffer; gint new_offset_x; gint new_offset_y; /* always clip unfloated buffers so they keep their size */ if (GIMP_IS_CHANNEL (drawable) && ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) clip_result = TRUE; /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable)); gimp_item_rotate (GIMP_ITEM (mask), context, rotate_type, center_x, center_y, clip_result); } /* transform the buffer */ new_buffer = gimp_drawable_transform_buffer_rotate (drawable, context, orig_buffer, orig_offset_x, orig_offset_y, rotate_type, center_x, center_y, clip_result, &new_offset_x, &new_offset_y); /* Free the cut/copied buffer */ g_object_unref (orig_buffer); if (new_buffer) { result = gimp_drawable_transform_paste (drawable, new_buffer, new_offset_x, new_offset_y, new_layer); g_object_unref (new_buffer); } } /* push the undo group end */ gimp_image_undo_group_end (image); return result; }
GimpDrawable * gimp_drawable_transform_affine (GimpDrawable *drawable, GimpContext *context, const GimpMatrix3 *matrix, GimpTransformDirection direction, GimpInterpolationType interpolation_type, gint recursion_level, GimpTransformResize clip_result, GimpProgress *progress) { GimpImage *image; GeglBuffer *orig_buffer; gint orig_offset_x; gint orig_offset_y; gboolean new_layer; GimpDrawable *result = NULL; 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 (matrix != NULL, NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); /* Start a transform undo group */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM, C_("undo-type", "Transform")); /* Cut/Copy from the specified drawable */ orig_buffer = gimp_drawable_transform_cut (drawable, context, &orig_offset_x, &orig_offset_y, &new_layer); if (orig_buffer) { GeglBuffer *new_buffer; gint new_offset_x; gint new_offset_y; /* always clip unfloated buffers so they keep their size */ if (GIMP_IS_CHANNEL (drawable) && ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) clip_result = GIMP_TRANSFORM_RESIZE_CLIP; /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable)); gimp_item_transform (GIMP_ITEM (mask), context, matrix, direction, interpolation_type, recursion_level, clip_result, progress); } /* transform the buffer */ new_buffer = gimp_drawable_transform_buffer_affine (drawable, context, orig_buffer, orig_offset_x, orig_offset_y, matrix, direction, interpolation_type, recursion_level, clip_result, &new_offset_x, &new_offset_y, progress); /* Free the cut/copied buffer */ g_object_unref (orig_buffer); if (new_buffer) { result = gimp_drawable_transform_paste (drawable, new_buffer, new_offset_x, new_offset_y, new_layer); g_object_unref (new_buffer); } } /* push the undo group end */ gimp_image_undo_group_end (image); return result; }
GimpLayer * gimp_image_merge_visible_layers (GimpImage *image, GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, gboolean discard_invisible) { GimpContainer *container; GList *list; GSList *merge_list = NULL; GSList *invisible_list = NULL; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); if (merge_active_group) { GimpLayer *active_layer = gimp_image_get_active_layer (image); /* if the active layer is the floating selection, get the * underlying drawable, but only if it is a layer */ if (active_layer && gimp_layer_is_floating_sel (active_layer)) { GimpDrawable *fs_drawable; fs_drawable = gimp_layer_get_floating_sel_drawable (active_layer); if (GIMP_IS_LAYER (fs_drawable)) active_layer = GIMP_LAYER (fs_drawable); } if (active_layer) container = gimp_item_get_container (GIMP_ITEM (active_layer)); else container = gimp_image_get_layers (image); } else { container = gimp_image_get_layers (image); } for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container)); list; list = g_list_next (list)) { GimpLayer *layer = list->data; if (gimp_layer_is_floating_sel (layer)) continue; if (gimp_item_get_visible (GIMP_ITEM (layer))) { merge_list = g_slist_append (merge_list, layer); } else if (discard_invisible) { invisible_list = g_slist_append (invisible_list, layer); } } if (merge_list) { GimpLayer *layer; gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, C_("undo-type", "Merge Visible Layers")); /* if there's a floating selection, anchor it */ if (gimp_image_get_floating_selection (image)) floating_sel_anchor (gimp_image_get_floating_selection (image)); layer = gimp_image_merge_layers (image, container, merge_list, context, merge_type); g_slist_free (merge_list); if (invisible_list) { GSList *list; for (list = invisible_list; list; list = g_slist_next (list)) gimp_image_remove_layer (image, list->data, TRUE, NULL); g_slist_free (invisible_list); } gimp_image_undo_group_end (image); gimp_unset_busy (image->gimp); return layer; } return gimp_image_get_active_layer (image); }
static gboolean gimp_text_layer_render (GimpTextLayer *layer) { GimpDrawable *drawable; GimpItem *item; GimpImage *image; GimpTextLayout *layout; gdouble xres; gdouble yres; gint width; gint height; if (! layer->text) return FALSE; drawable = GIMP_DRAWABLE (layer); item = GIMP_ITEM (layer); image = gimp_item_get_image (item); if (gimp_container_is_empty (image->gimp->fonts)) { gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, _("Due to lack of any fonts, " "text functionality is not available.")); return FALSE; } gimp_image_get_resolution (image, &xres, &yres); layout = gimp_text_layout_new (layer->text, xres, yres); g_object_freeze_notify (G_OBJECT (drawable)); if (gimp_text_layout_get_size (layout, &width, &height) && (width != gimp_item_get_width (item) || height != gimp_item_get_height (item))) { GeglBuffer *new_buffer; new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), gimp_drawable_get_format (drawable)); gimp_drawable_set_buffer (drawable, FALSE, NULL, new_buffer); g_object_unref (new_buffer); if (gimp_layer_get_mask (GIMP_LAYER (layer))) { GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (layer)); static GimpContext *unused_eek = NULL; if (! unused_eek) unused_eek = gimp_context_new (image->gimp, "eek", NULL); gimp_item_resize (GIMP_ITEM (mask), unused_eek, width, height, 0, 0); } } if (layer->auto_rename) { GimpItem *item = GIMP_ITEM (layer); gchar *name = NULL; if (layer->text->text) { name = gimp_utf8_strtrim (layer->text->text, 30); } else if (layer->text->markup) { gchar *tmp = gimp_markup_extract_text (layer->text->markup); name = gimp_utf8_strtrim (tmp, 30); g_free (tmp); } if (! name) name = g_strdup (_("Empty Text Layer")); if (gimp_item_is_attached (item)) { gimp_item_tree_rename_item (gimp_item_get_tree (item), item, name, FALSE, NULL); g_free (name); } else { gimp_object_take_name (GIMP_OBJECT (layer), name); } } gimp_text_layer_render_layout (layer, layout); g_object_unref (layout); g_object_thaw_notify (G_OBJECT (drawable)); return (width > 0 && height > 0); }
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; }