static GValueArray * floating_sel_attach_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GValueArray *args, GError **error) { gboolean success = TRUE; GimpLayer *layer; GimpDrawable *drawable; layer = gimp_value_get_layer (&args->values[0], gimp); drawable = gimp_value_get_drawable (&args->values[1], gimp); if (success) { if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, TRUE, error) && gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) floating_sel_attach (layer, drawable); else success = FALSE; } return gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); }
GimpDrawable * gimp_drawable_transform_paste (GimpDrawable *drawable, GeglBuffer *buffer, GimpColorProfile *buffer_profile, gint offset_x, gint offset_y, gboolean new_layer) { GimpImage *image; GimpLayer *layer = NULL; const gchar *undo_desc = 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 (GEGL_IS_BUFFER (buffer), NULL); g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (buffer_profile), NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); if (GIMP_IS_LAYER (drawable)) undo_desc = C_("undo-type", "Transform Layer"); else if (GIMP_IS_CHANNEL (drawable)) undo_desc = C_("undo-type", "Transform Channel"); else return NULL; gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, undo_desc); if (new_layer) { layer = gimp_layer_new_from_gegl_buffer (buffer, image, gimp_drawable_get_format_with_alpha (drawable), _("Transformation"), GIMP_OPACITY_OPAQUE, gimp_image_get_default_new_layer_mode (image), buffer_profile); gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y); floating_sel_attach (layer, drawable); drawable = GIMP_DRAWABLE (layer); } else { gimp_drawable_set_buffer_full (drawable, TRUE, NULL, buffer, offset_x, offset_y, TRUE); } gimp_image_undo_group_end (image); return drawable; }
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); }
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; }
static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo, XCFLayerInfo *outLayer ) { ssize_t i; MagickOffsetType offset; unsigned int foundPropEnd = 0; size_t hierarchy_offset, layer_mask_offset; /* clear the block! */ (void) ResetMagickMemory( outLayer, 0, sizeof( XCFLayerInfo ) ); /* read in the layer width, height, type and name */ outLayer->width = ReadBlobMSBLong(image); outLayer->height = ReadBlobMSBLong(image); outLayer->type = ReadBlobMSBLong(image); (void) ReadBlobStringWithLongSize(image, outLayer->name, sizeof(outLayer->name)); /* allocate the image for this layer */ outLayer->image=CloneImage(image,outLayer->width, outLayer->height,MagickTrue, &image->exception); if (outLayer->image == (Image *) NULL) return MagickFalse; /* read the layer properties! */ foundPropEnd = 0; while ( (foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse) ) { PropType prop_type = (PropType) ReadBlobMSBLong(image); size_t prop_size = ReadBlobMSBLong(image); switch (prop_type) { case PROP_END: foundPropEnd = 1; break; case PROP_ACTIVE_LAYER: outLayer->active = 1; break; case PROP_FLOATING_SELECTION: outLayer->floating_offset = ReadBlobMSBLong(image); break; case PROP_OPACITY: outLayer->opacity = ReadBlobMSBLong(image); break; case PROP_VISIBLE: outLayer->visible = ReadBlobMSBLong(image); break; case PROP_LINKED: outLayer->linked = ReadBlobMSBLong(image); break; case PROP_PRESERVE_TRANSPARENCY: outLayer->preserve_trans = ReadBlobMSBLong(image); break; case PROP_APPLY_MASK: outLayer->apply_mask = ReadBlobMSBLong(image); break; case PROP_EDIT_MASK: outLayer->edit_mask = ReadBlobMSBLong(image); break; case PROP_SHOW_MASK: outLayer->show_mask = ReadBlobMSBLong(image); break; case PROP_OFFSETS: outLayer->offset_x = (ssize_t) ReadBlobMSBLong(image); outLayer->offset_y = (ssize_t) ReadBlobMSBLong(image); break; case PROP_MODE: outLayer->mode = ReadBlobMSBLong(image); break; case PROP_TATTOO: outLayer->preserve_trans = ReadBlobMSBLong(image); break; case PROP_PARASITES: { for (i=0; i < (ssize_t) prop_size; i++ ) (void) ReadBlobByte(image); /* ssize_t base = info->cp; GimpParasite *p; while (info->cp - base < prop_size) { p = xcf_load_parasite(info); gimp_drawable_parasite_attach(GIMP_DRAWABLE(layer), p); gimp_parasite_free(p); } if (info->cp - base != prop_size) g_message ("Error detected while loading a layer's parasites"); */ } break; default: /* g_message ("unexpected/unknown layer property: %d (skipping)", prop_type); */ { int buf[16]; ssize_t amount; /* read over it... */ while ((prop_size > 0) && (EOFBlob(image) == MagickFalse)) { amount = (ssize_t) MagickMin(16, prop_size); amount = ReadBlob(image, (size_t) amount, (unsigned char *) &buf); if (!amount) ThrowBinaryException(CorruptImageError,"CorruptImage", image->filename); prop_size -= (size_t) MagickMin(16, (size_t) amount); } } break; } } if (foundPropEnd == MagickFalse) return(MagickFalse); /* clear the image based on the layer opacity */ outLayer->image->background_color.opacity= ScaleCharToQuantum((unsigned char) (255-outLayer->opacity)); (void) SetImageBackgroundColor(outLayer->image); /* set the compositing mode */ outLayer->image->compose = GIMPBlendModeToCompositeOperator( outLayer->mode ); if ( outLayer->visible == MagickFalse ) { /* BOGUS: should really be separate member var! */ outLayer->image->compose = NoCompositeOp; } /* read the hierarchy and layer mask offsets */ hierarchy_offset = ReadBlobMSBLong(image); layer_mask_offset = ReadBlobMSBLong(image); /* read in the hierarchy */ offset=SeekBlob(image, (MagickOffsetType) hierarchy_offset, SEEK_SET); if (offset < 0) (void) ThrowMagickException(&image->exception,GetMagickModule(), CorruptImageError,"InvalidImageHeader","`%s'",image->filename); if (load_hierarchy (image, inDocInfo, outLayer) == 0) return(MagickFalse); /* read in the layer mask */ if (layer_mask_offset != 0) { offset=SeekBlob(image, (MagickOffsetType) layer_mask_offset, SEEK_SET); #if 0 /* BOGUS: support layer masks! */ layer_mask = xcf_load_layer_mask (info, gimage); if (layer_mask == 0) goto error; /* set the offsets of the layer_mask */ GIMP_DRAWABLE (layer_mask)->offset_x = GIMP_DRAWABLE (layer)->offset_x; GIMP_DRAWABLE (layer_mask)->offset_y = GIMP_DRAWABLE (layer)->offset_y; gimp_layer_add_mask (layer, layer_mask, MagickFalse); layer->mask->apply_mask = apply_mask; layer->mask->edit_mask = edit_mask; layer->mask->show_mask = show_mask; #endif } /* attach the floating selection... */ #if 0 /* BOGUS: we may need to read this, even if we don't support it! */ if (add_floating_sel) { GimpLayer *floating_sel; floating_sel = info->floating_sel; floating_sel_attach (floating_sel, GIMP_DRAWABLE (layer)); } #endif return MagickTrue; }
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; }
GimpImage * gimp_image_duplicate (GimpImage *image) { GimpImage *new_image; GimpLayer *floating_layer; GList *list; GimpLayer *active_layer = NULL; GimpChannel *active_channel = NULL; GimpVectors *active_vectors = NULL; GimpDrawable *new_floating_sel_drawable = NULL; GimpDrawable *floating_sel_drawable = NULL; gchar *filename; gint count; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); gimp_set_busy_until_idle (image->gimp); /* Create a new image */ new_image = gimp_create_image (image->gimp, image->width, image->height, image->base_type, FALSE); gimp_image_undo_disable (new_image); /* Store the folder to be used by the save dialog */ filename = gimp_image_get_filename (image); if (filename) { g_object_set_data_full (G_OBJECT (new_image), "gimp-image-dirname", g_path_get_dirname (filename), (GDestroyNotify) g_free); g_free (filename); } /* Copy the colormap if necessary */ if (new_image->base_type == GIMP_INDEXED) gimp_image_set_colormap (new_image, gimp_image_get_colormap (image), gimp_image_get_colormap_size (image), FALSE); /* Copy resolution information */ new_image->xresolution = image->xresolution; new_image->yresolution = image->yresolution; new_image->resolution_unit = image->resolution_unit; /* Copy floating layer */ floating_layer = gimp_image_floating_sel (image); if (floating_layer) { floating_sel_relax (floating_layer, FALSE); floating_sel_drawable = floating_layer->fs.drawable; floating_layer = NULL; } /* Copy the layers */ for (list = GIMP_LIST (image->layers)->list, count = 0; list; list = g_list_next (list)) { GimpLayer *layer = list->data; GimpLayer *new_layer; new_layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer), new_image, G_TYPE_FROM_INSTANCE (layer), FALSE)); /* Make sure the copied layer doesn't say: "<old layer> copy" */ gimp_object_set_name (GIMP_OBJECT (new_layer), gimp_object_get_name (GIMP_OBJECT (layer))); /* 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 (GIMP_OBJECT (layer->mask))); if (gimp_image_get_active_layer (image) == layer) active_layer = new_layer; if (image->floating_sel == layer) floating_layer = new_layer; if (floating_sel_drawable == GIMP_DRAWABLE (layer)) new_floating_sel_drawable = GIMP_DRAWABLE (new_layer); if (floating_layer != new_layer) gimp_image_add_layer (new_image, new_layer, count++); } /* Copy the channels */ for (list = GIMP_LIST (image->channels)->list, count = 0; list; list = g_list_next (list)) { GimpChannel *channel = list->data; GimpChannel *new_channel; new_channel = GIMP_CHANNEL (gimp_item_convert (GIMP_ITEM (channel), new_image, G_TYPE_FROM_INSTANCE (channel), FALSE)); /* Make sure the copied channel doesn't say: "<old channel> copy" */ gimp_object_set_name (GIMP_OBJECT (new_channel), gimp_object_get_name (GIMP_OBJECT (channel))); if (gimp_image_get_active_channel (image) == channel) active_channel = (new_channel); if (floating_sel_drawable == GIMP_DRAWABLE (channel)) new_floating_sel_drawable = GIMP_DRAWABLE (new_channel); gimp_image_add_channel (new_image, new_channel, count++); } /* Copy any vectors */ for (list = GIMP_LIST (image->vectors)->list, count = 0; list; list = g_list_next (list)) { GimpVectors *vectors = list->data; GimpVectors *new_vectors; new_vectors = GIMP_VECTORS (gimp_item_convert (GIMP_ITEM (vectors), new_image, G_TYPE_FROM_INSTANCE (vectors), FALSE)); /* Make sure the copied vectors doesn't say: "<old vectors> copy" */ gimp_object_set_name (GIMP_OBJECT (new_vectors), gimp_object_get_name (GIMP_OBJECT (vectors))); if (gimp_image_get_active_vectors (image) == vectors) active_vectors = new_vectors; gimp_image_add_vectors (new_image, new_vectors, count++); } /* Copy the selection mask */ { TileManager *src_tiles; TileManager *dest_tiles; PixelRegion srcPR, destPR; src_tiles = gimp_drawable_get_tiles (GIMP_DRAWABLE (image->selection_mask)); dest_tiles = gimp_drawable_get_tiles (GIMP_DRAWABLE (new_image->selection_mask)); pixel_region_init (&srcPR, src_tiles, 0, 0, image->width, image->height, FALSE); pixel_region_init (&destPR, dest_tiles, 0, 0, image->width, image->height, TRUE); copy_region (&srcPR, &destPR); new_image->selection_mask->bounds_known = FALSE; new_image->selection_mask->boundary_known = FALSE; } if (floating_layer) floating_sel_attach (floating_layer, new_floating_sel_drawable); /* Set active layer, active channel, active vectors */ if (active_layer) gimp_image_set_active_layer (new_image, active_layer); if (active_channel) gimp_image_set_active_channel (new_image, active_channel); if (active_vectors) gimp_image_set_active_vectors (new_image, active_vectors); /* Copy state of all color channels */ for (count = 0; count < MAX_CHANNELS; count++) { new_image->visible[count] = image->visible[count]; new_image->active[count] = image->active[count]; } /* Copy any guides */ for (list = image->guides; list; list = g_list_next (list)) { GimpGuide *guide = list->data; gint position = gimp_guide_get_position (guide); switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_HORIZONTAL: gimp_image_add_hguide (new_image, position, FALSE); break; case GIMP_ORIENTATION_VERTICAL: gimp_image_add_vguide (new_image, position, FALSE); break; default: g_error ("Unknown guide orientation.\n"); } } /* Copy any sample points */ for (list = image->sample_points; list; list = g_list_next (list)) { GimpSamplePoint *sample_point = list->data; gimp_image_add_sample_point_at_pos (new_image, sample_point->x, sample_point->y, FALSE); } /* Copy the grid */ if (image->grid) gimp_image_set_grid (new_image, image->grid, FALSE); /* Copy the quick mask info */ new_image->quick_mask_state = image->quick_mask_state; new_image->quick_mask_inverted = image->quick_mask_inverted; new_image->quick_mask_color = image->quick_mask_color; /* Copy parasites */ if (image->parasites) { g_object_unref (new_image->parasites); new_image->parasites = gimp_parasite_list_copy (image->parasites); } gimp_image_undo_enable (new_image); return new_image; }