Пример #1
0
void
floating_sel_anchor (GimpLayer *layer)
{
  GimpImage    *image;
  GimpDrawable *drawable;
  GimpFilter   *filter = NULL;
  gint          off_x, off_y;
  gint          dr_off_x, dr_off_y;

  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  /* Don't let gimp_image_remove_layer free the layer while we still need it */
  g_object_ref (layer);

  image = gimp_item_get_image (GIMP_ITEM (layer));

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_ANCHOR,
                               C_("undo-type", "Anchor Floating Selection"));

  drawable = gimp_layer_get_floating_sel_drawable (layer);

  gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y);
  gimp_item_get_offset (GIMP_ITEM (drawable), &dr_off_x, &dr_off_y);

  if (gimp_item_get_visible (GIMP_ITEM (layer)) &&
      gimp_rectangle_intersect (off_x, off_y,
                                gimp_item_get_width  (GIMP_ITEM (layer)),
                                gimp_item_get_height (GIMP_ITEM (layer)),
                                dr_off_x, dr_off_y,
                                gimp_item_get_width  (GIMP_ITEM (drawable)),
                                gimp_item_get_height (GIMP_ITEM (drawable)),
                                NULL, NULL, NULL, NULL))
    {
      filter = gimp_drawable_get_floating_sel_filter (drawable);
      g_object_ref (filter);
    }

  /*  first remove the filter, then merge it, or we will get warnings
   *  about already connected nodes
   */
  gimp_image_remove_layer (image, layer, TRUE, NULL);

  if (filter)
    {
      gimp_drawable_merge_filter (drawable, filter, NULL, NULL);
      g_object_unref (filter);
    }

  gimp_image_undo_group_end (image);

  /*  invalidate the boundaries  */
  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (gimp_image_get_mask (image)));

  g_object_unref (layer);
}
Пример #2
0
void
floating_sel_to_layer (GimpLayer *layer)
{
  GimpItem  *item;
  GimpImage *image;

  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  item = GIMP_ITEM (layer);

  if (! (image = gimp_item_get_image (item)))
    return;

  /*  Check if the floating layer belongs to a channel...  */
  if (GIMP_IS_CHANNEL (layer->fs.drawable))
    {
      gimp_message (image->gimp, NULL, GIMP_MESSAGE_WARNING,
                    _("Cannot create a new layer from the floating selection "
                      "because it belongs to a layer mask or channel."));
      return;
    }

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_TO_LAYER,
                               _("Floating Selection to Layer"));

  /*  restore the contents of the drawable  */
  floating_sel_restore (layer,
                        item->offset_x,
                        item->offset_y,
                        item->width,
                        item->height);

  gimp_image_undo_push_fs_to_layer (image, NULL, layer);

  /*  clear the selection  */
  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));

  /*  Set pointers  */
  layer->fs.drawable   = NULL;
  image->floating_sel = NULL;

  gimp_item_set_visible (GIMP_ITEM (layer), TRUE, TRUE);
  gimp_layer_set_lock_alpha (layer, FALSE, TRUE);

  gimp_image_undo_group_end (image);

  gimp_object_name_changed (GIMP_OBJECT (layer));

  gimp_drawable_update (GIMP_DRAWABLE (layer),
                        0, 0,
                        GIMP_ITEM (layer)->width,
                        GIMP_ITEM (layer)->height);

  gimp_image_floating_selection_changed (image);
}
Пример #3
0
void
floating_sel_anchor (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));

  if (! gimp_layer_is_floating_sel (layer))
    {
      gimp_message (image->gimp, NULL, GIMP_MESSAGE_WARNING,
                    _("Cannot anchor this layer because "
                      "it is not a floating selection."));
      return;
    }

  /*  Start a floating selection anchoring undo  */
  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_ANCHOR,
                               _("Anchor Floating Selection"));

  /* Invalidate the previews of the layer that will be composited
   * with the floating section.
   */
  gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer->fs.drawable));

  /*  Relax the floating selection  */
  floating_sel_relax (layer, TRUE);

  /*  Composite the floating selection contents  */
  floating_sel_composite (layer,
                          GIMP_ITEM (layer)->offset_x,
                          GIMP_ITEM (layer)->offset_y,
                          GIMP_ITEM (layer)->width,
                          GIMP_ITEM (layer)->height, TRUE);

  drawable = layer->fs.drawable;

  /*  remove the floating selection  */
  gimp_image_remove_layer (image, layer);

  /*  end the group undo  */
  gimp_image_undo_group_end (image);

  /*  invalidate the boundaries  */
  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (gimp_image_get_mask (image)));
}
Пример #4
0
static void
gimp_image_undo_pop (GimpUndo            *undo,
                     GimpUndoMode         undo_mode,
                     GimpUndoAccumulator *accum)
{
  GimpImageUndo    *image_undo = GIMP_IMAGE_UNDO (undo);
  GimpImage        *image      = undo->image;
  GimpImagePrivate *private    = GIMP_IMAGE_GET_PRIVATE (image);

  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);

  switch (undo->undo_type)
    {
    case GIMP_UNDO_IMAGE_TYPE:
      {
        GimpImageBaseType base_type;

        base_type = image_undo->base_type;
        image_undo->base_type = gimp_image_base_type (image);
        g_object_set (image, "base-type", base_type, NULL);

        gimp_image_colormap_changed (image, -1);

        if (image_undo->base_type != gimp_image_base_type (image))
          accum->mode_changed = TRUE;
      }
      break;

    case GIMP_UNDO_IMAGE_SIZE:
      {
        gint width;
        gint height;
        gint previous_origin_x;
        gint previous_origin_y;
        gint previous_width;
        gint previous_height;

        width             = image_undo->width;
        height            = image_undo->height;
        previous_origin_x = image_undo->previous_origin_x;
        previous_origin_y = image_undo->previous_origin_y;
        previous_width    = image_undo->previous_width;
        previous_height   = image_undo->previous_height;

        /* Transform to a redo */
        image_undo->width             = gimp_image_get_width  (image);
        image_undo->height            = gimp_image_get_height (image);
        image_undo->previous_origin_x = -previous_origin_x;
        image_undo->previous_origin_y = -previous_origin_y;
        image_undo->previous_width    = width;
        image_undo->previous_height   = height;

        g_object_set (image,
                      "width",  width,
                      "height", height,
                      NULL);

        gimp_drawable_invalidate_boundary
          (GIMP_DRAWABLE (gimp_image_get_mask (image)));

        if (gimp_image_get_width  (image) != image_undo->width ||
            gimp_image_get_height (image) != image_undo->height)
          {
            accum->size_changed      = TRUE;
            accum->previous_origin_x = previous_origin_x;
            accum->previous_origin_y = previous_origin_y;
            accum->previous_width    = previous_width;
            accum->previous_height   = previous_height;
          }
      }
      break;

    case GIMP_UNDO_IMAGE_RESOLUTION:
      {
        gdouble xres;
        gdouble yres;

        gimp_image_get_resolution (image, &xres, &yres);

        if (ABS (image_undo->xresolution - xres) >= 1e-5 ||
            ABS (image_undo->yresolution - yres) >= 1e-5)
          {
            private->xresolution = image_undo->xresolution;
            private->yresolution = image_undo->yresolution;

            image_undo->xresolution = xres;
            image_undo->yresolution = yres;

            accum->resolution_changed = TRUE;
          }
      }
Пример #5
0
static void
gimp_mask_undo_pop (GimpUndo            *undo,
                    GimpUndoMode         undo_mode,
                    GimpUndoAccumulator *accum)
{
  GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (undo);
  GimpChannel  *channel   = GIMP_CHANNEL (GIMP_ITEM_UNDO (undo)->item);
  GimpDrawable *drawable  = GIMP_DRAWABLE (channel);
  GeglBuffer   *new_buffer;
  const Babl   *format;
  gint          x1, y1, x2, y2;
  gint          width  = 0;
  gint          height = 0;

  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);

  if (gimp_channel_bounds (channel, &x1, &y1, &x2, &y2))
    {
      new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1),
                                    gimp_drawable_get_format (drawable));

      gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
                        GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                        new_buffer,
                        GEGL_RECTANGLE (0, 0, 0, 0));

      gegl_buffer_clear (gimp_drawable_get_buffer (drawable),
                         GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1));
    }
  else
    {
      new_buffer = NULL;
    }

  format = gimp_drawable_get_format (drawable);

  if (mask_undo->convert_format)
    {
      GeglBuffer *buffer;
      gint        width  = gimp_item_get_width  (GIMP_ITEM (channel));
      gint        height = gimp_item_get_height (GIMP_ITEM (channel));

      buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
                                     mask_undo->format);
      gegl_buffer_clear (buffer, NULL);

      gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
      g_object_unref (buffer);
    }

  if (mask_undo->buffer)
    {
      width  = gegl_buffer_get_width  (mask_undo->buffer);
      height = gegl_buffer_get_height (mask_undo->buffer);

      gegl_buffer_copy (mask_undo->buffer,
                        NULL,
                        gimp_drawable_get_buffer (drawable),
                        GEGL_RECTANGLE (mask_undo->x, mask_undo->y, 0, 0));

      g_object_unref (mask_undo->buffer);
    }

  /* invalidate the current bounds and boundary of the mask */
  gimp_drawable_invalidate_boundary (drawable);

  if (mask_undo->buffer)
    {
      channel->empty = FALSE;
      channel->x1    = mask_undo->x;
      channel->y1    = mask_undo->y;
      channel->x2    = mask_undo->x + width;
      channel->y2    = mask_undo->y + height;
    }
  else
    {
      channel->empty = TRUE;
      channel->x1    = 0;
      channel->y1    = 0;
      channel->x2    = gimp_item_get_width  (GIMP_ITEM (channel));
      channel->y2    = gimp_item_get_height (GIMP_ITEM (channel));
    }

  /* we know the bounds */
  channel->bounds_known = TRUE;

  /*  set the new mask undo parameters  */
  mask_undo->buffer = new_buffer;
  mask_undo->x      = x1;
  mask_undo->y      = y1;
  mask_undo->format = format;

  gimp_drawable_update (GIMP_DRAWABLE (channel),
                        0, 0,
                        gimp_item_get_width  (GIMP_ITEM (channel)),
                        gimp_item_get_height (GIMP_ITEM (channel)));
}