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;
}
Exemple #2
0
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);
    }
}
Exemple #4
0
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;
    }
}
Exemple #6
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;
}