Beispiel #1
0
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 ();
    }
}
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);
}
gboolean
floating_sel_to_layer (GimpLayer  *layer,
                       GError    **error)
{
  GimpItem  *item;
  GimpImage *image;

  g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
  g_return_val_if_fail (gimp_layer_is_floating_sel (layer), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  item  = GIMP_ITEM (layer);
  image = gimp_item_get_image (item);

  /*  Check if the floating layer belongs to a channel  */
  if (GIMP_IS_CHANNEL (gimp_layer_get_floating_sel_drawable (layer)))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			   _("Cannot create a new layer from the floating "
			     "selection because it belongs to a layer mask "
			     "or channel."));
      return FALSE;
    }

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_TO_LAYER,
                               C_("undo-type", "Floating Selection to Layer"));

  gimp_image_undo_push_fs_to_layer (image, NULL, layer);

  gimp_drawable_detach_floating_sel (gimp_layer_get_floating_sel_drawable (layer));
  gimp_layer_set_floating_sel_drawable (layer, NULL);

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

  gimp_image_undo_group_end (image);

  /* 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 (layer));

  gimp_drawable_update (GIMP_DRAWABLE (layer),
                        0, 0,
                        gimp_item_get_width  (item),
                        gimp_item_get_height (item));

  return TRUE;
}
void
floating_sel_attach (GimpLayer    *layer,
                     GimpDrawable *drawable)
{
  GimpImage *image;
  GimpLayer *floating_sel;

  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (drawable != GIMP_DRAWABLE (layer));
  g_return_if_fail (gimp_item_get_image (GIMP_ITEM (layer)) ==
                    gimp_item_get_image (GIMP_ITEM (drawable)));

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  floating_sel = gimp_image_floating_sel (image);

  /*  If there is already a floating selection, anchor it  */
  if (floating_sel)
    {
      floating_sel_anchor (floating_sel);

      /*  if we were pasting to the old floating selection, paste now
       *  to the drawable
       */
      if (drawable == (GimpDrawable *) floating_sel)
        drawable = gimp_image_get_active_drawable (image);
    }

  /*  set the drawable and allocate a backing store  */
  gimp_layer_set_lock_alpha (layer, TRUE, FALSE);
  layer->fs.drawable      = drawable;
  layer->fs.backing_store = tile_manager_new (GIMP_ITEM (layer)->width,
                                              GIMP_ITEM (layer)->height,
                                              gimp_drawable_bytes (drawable));

  /*  add the layer to the image  */
  gimp_image_add_layer (image, layer, 0);

  /*  store the affected area from the drawable in the backing store  */
  floating_sel_rigor (layer, TRUE);
}
Beispiel #5
0
/**
 * 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);
}
void
floating_sel_attach (GimpLayer    *layer,
                     GimpDrawable *drawable)
{
  GimpImage *image;
  GimpLayer *floating_sel;

  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (drawable != GIMP_DRAWABLE (layer));
  g_return_if_fail (gimp_item_get_image (GIMP_ITEM (layer)) ==
                    gimp_item_get_image (GIMP_ITEM (drawable)));

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  floating_sel = gimp_image_get_floating_selection (image);

  /*  If there is already a floating selection, anchor it  */
  if (floating_sel)
    {
      floating_sel_anchor (floating_sel);

      /*  if we were pasting to the old floating selection, paste now
       *  to the drawable
       */
      if (drawable == (GimpDrawable *) floating_sel)
        drawable = gimp_image_get_active_drawable (image);
    }

  gimp_layer_set_lock_alpha (layer, TRUE, FALSE);

  gimp_layer_set_floating_sel_drawable (layer, drawable);

  gimp_image_add_layer (image, layer, NULL, 0, TRUE);
}
Beispiel #7
0
/**
 * gimp_layer_set_preserve_trans:
 * @layer_ID: The layer.
 * @preserve_trans: The new layer's preserve transperancy setting.
 *
 * This procedure is deprecated! Use gimp_layer_set_lock_alpha() instead.
 *
 * Returns: TRUE on success.
 */
gboolean
gimp_layer_set_preserve_trans (gint32   layer_ID,
                               gboolean preserve_trans)
{
  return gimp_layer_set_lock_alpha (layer_ID, preserve_trans);
}
Beispiel #8
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam   values[1];
  GimpDrawable      *drawable;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  GimpRunMode        run_mode;
  gint32             image_ID;

  run_mode = param[0].data.d_int32;

  *nreturn_vals = 1;
  *return_vals  = values;

  INIT_I18N ();

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = status;

  image_ID = param[1].data.d_image;
  drawable = gimp_drawable_get (param[2].data.d_drawable);

  switch (run_mode)
    {
    case GIMP_RUN_INTERACTIVE:
      gimp_get_data (PLUG_IN_PROC, &pvals);
      if (! color_to_alpha_dialog (drawable))
        {
          gimp_drawable_detach (drawable);
          return;
        }
      break;

    case GIMP_RUN_NONINTERACTIVE:
      if (nparams != 4)
        status = GIMP_PDB_CALLING_ERROR;

      if (status == GIMP_PDB_SUCCESS)
        pvals.color = param[3].data.d_color;
      break;

    case GIMP_RUN_WITH_LAST_VALS:
      gimp_get_data (PLUG_IN_PROC, &pvals);
      break;

    default:
      break;
    }

  if (status == GIMP_PDB_SUCCESS &&
      gimp_drawable_is_rgb (drawable->drawable_id) &&
      gimp_item_is_layer (drawable->drawable_id))
    {
      gboolean lock_alpha;

      gimp_image_undo_group_start (image_ID);

      /*  Add alpha if not present */
      gimp_layer_add_alpha (drawable->drawable_id);

      /*  Reget the drawable, bpp might have changed  */
      drawable = gimp_drawable_get (drawable->drawable_id);

      /*  Unset 'Lock alpha'  */
      lock_alpha = gimp_layer_get_lock_alpha (drawable->drawable_id);
      gimp_layer_set_lock_alpha (drawable->drawable_id, FALSE);

      gimp_progress_init (_("Removing color"));
      gimp_rgn_iterate2 (drawable, 0 /* unused */, to_alpha_func, NULL);

      gimp_layer_set_lock_alpha (drawable->drawable_id, lock_alpha);

      gimp_image_undo_group_end (image_ID);

      if (run_mode != GIMP_RUN_NONINTERACTIVE)
        gimp_displays_flush ();
    }

  gimp_drawable_detach (drawable);

  if (run_mode == GIMP_RUN_INTERACTIVE)
    gimp_set_data (PLUG_IN_PROC, &pvals, sizeof (pvals));

  values[0].data.d_status = status;
}
Beispiel #9
0
static void
rotate_drawable (GimpDrawable *drawable)
{
  GimpPixelRgn  srcPR, destPR;
  gint          width, height;
  gint          longside;
  gint          bytes;
  gint          row, col;
  gint          offsetx, offsety;
  gboolean      was_lock_alpha = FALSE;
  guchar       *buffer;
  guchar       *src_row, *dest_row;

  /* initialize */

  row = 0;

  /* Get the size of the input drawable. */
  width = drawable->width;
  height = drawable->height;
  bytes = drawable->bpp;

  if (gimp_layer_get_lock_alpha (drawable->drawable_id))
    {
      was_lock_alpha = TRUE;
      gimp_layer_set_lock_alpha (drawable->drawable_id, FALSE);
    }

  if (rotvals.angle == 2)  /* we're rotating by 180° */
    {
      gimp_tile_cache_ntiles (2 * (width / gimp_tile_width() + 1));

      gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height,
                           FALSE, FALSE);
      gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height,
                           TRUE, TRUE);

      src_row  = (guchar *) g_malloc (width * bytes);
      dest_row = (guchar *) g_malloc (width * bytes);

      for (row = 0; row < height; row++)
        {
          gimp_pixel_rgn_get_row (&srcPR, src_row, 0, row, width);
          for (col = 0; col < width; col++)
            {
              memcpy (dest_row + col * bytes,
                      src_row + (width - 1 - col) * bytes,
                      bytes);
            }
          gimp_pixel_rgn_set_row (&destPR, dest_row, 0, (height - row - 1),
                                  width);

          if ((row % 5) == 0)
            gimp_progress_update ((double) row / (double) height);
        }

      g_free (src_row);
      g_free (dest_row);

      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, 0, 0, width, height);

    }
  else                     /* we're rotating by 90° or 270° */
    {
      (width > height) ? (longside = width) : (longside = height);

      gimp_layer_resize (drawable->drawable_id, longside, longside, 0, 0);
      drawable = gimp_drawable_get (drawable->drawable_id);
      gimp_drawable_flush (drawable);

      gimp_tile_cache_ntiles ((longside / gimp_tile_width () + 1) +
                              (longside / gimp_tile_height () + 1));

      gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, longside, longside,
                           FALSE, FALSE);
      gimp_pixel_rgn_init (&destPR, drawable, 0, 0, longside, longside,
                           TRUE, TRUE);

      buffer = g_malloc (longside * bytes);

      if (rotvals.angle == 1)     /* we're rotating by 90° */
        {
          for (row = 0; row < height; row++)
            {
              gimp_pixel_rgn_get_row (&srcPR, buffer, 0, row, width);
              gimp_pixel_rgn_set_col (&destPR, buffer, (height - row - 1), 0,
                                      width);

              if ((row % 5) == 0)
                gimp_progress_update ((double) row / (double) height);
            }
        }
      else                        /* we're rotating by 270° */
        {
          for (col = 0; col < width; col++)
            {
              gimp_pixel_rgn_get_col (&srcPR, buffer, col, 0, height);
              gimp_pixel_rgn_set_row (&destPR, buffer, 0, (width - col - 1),
                                      height);

              if ((col % 5) == 0)
                gimp_progress_update ((double) col / (double) width);
            }
        }

      g_free (buffer);

      gimp_progress_update (1.0);

      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, 0, 0, height, width);

      gimp_layer_resize (drawable->drawable_id, height, width, 0, 0);
      drawable = gimp_drawable_get (drawable->drawable_id);
      gimp_drawable_flush (drawable);
      gimp_drawable_update (drawable->drawable_id, 0, 0, height, width);
    }

  gimp_drawable_offsets (drawable->drawable_id, &offsetx, &offsety);
  rotate_compute_offsets (&offsetx, &offsety,
                          gimp_image_width (image_ID),
                          gimp_image_height (image_ID),
                          width, height);
  gimp_layer_set_offsets (drawable->drawable_id, offsetx, offsety);

  if (was_lock_alpha)
    gimp_layer_set_lock_alpha (drawable->drawable_id, TRUE);

  return;
}
void
floating_sel_composite (GimpLayer *layer,
                        gint       x,
                        gint       y,
                        gint       w,
                        gint       h,
                        gboolean   push_undo)
{
  GimpImage *image;

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

  if (! (image = gimp_item_get_image (GIMP_ITEM (layer))))
    return;

  /*  What this function does is composite the specified area of the
   *  drawble with the floating selection.  We do this when the image
   *  is constructed, before any other composition takes place.
   */

  /*  If this isn't the first composite,
   *  restore the image underneath
   */
  if (! layer->fs.initial)
    floating_sel_restore (layer, x, y, w, h);
  else if (gimp_item_get_visible (GIMP_ITEM (layer)))
    layer->fs.initial = FALSE;

  /*  First restore what's behind the image if necessary,
   *  then check for visibility
   */
  if (gimp_item_get_visible (GIMP_ITEM (layer)))
    {
      gint offx, offy;
      gint x1, y1, x2, y2;

      /*  Find the minimum area we need to composite -- in image space  */
      gimp_item_offsets (GIMP_ITEM (layer->fs.drawable), &offx, &offy);

      x1 = MAX (GIMP_ITEM (layer)->offset_x, offx);
      y1 = MAX (GIMP_ITEM (layer)->offset_y, offy);
      x2 = MIN (GIMP_ITEM (layer)->offset_x +
                GIMP_ITEM (layer)->width,
                offx + gimp_item_width  (GIMP_ITEM (layer->fs.drawable)));
      y2 = MIN (GIMP_ITEM (layer)->offset_y +
                GIMP_ITEM (layer)->height,
                offy + gimp_item_height (GIMP_ITEM (layer->fs.drawable)));

      x1 = CLAMP (x, x1, x2);
      y1 = CLAMP (y, y1, y2);
      x2 = CLAMP (x + w, x1, x2);
      y2 = CLAMP (y + h, y1, y2);

      if ((x2 - x1) > 0 && (y2 - y1) > 0)
        {
          PixelRegion  fsPR;
          GimpLayer   *d_layer = NULL;
          gboolean     lock_alpha;

          /*  composite the area from the layer to the drawable  */
          pixel_region_init (&fsPR, GIMP_DRAWABLE (layer)->tiles,
                             (x1 - GIMP_ITEM (layer)->offset_x),
                             (y1 - GIMP_ITEM (layer)->offset_y),
                             (x2 - x1), (y2 - y1), FALSE);

          /*  a kludge here to prevent the case of the drawable
           *  underneath having lock alpha on, and disallowing
           *  the composited floating selection from being shown
           */
          if (GIMP_IS_LAYER (layer->fs.drawable))
            {
              d_layer = GIMP_LAYER (layer->fs.drawable);
              if ((lock_alpha = gimp_layer_get_lock_alpha (d_layer)))
                gimp_layer_set_lock_alpha (d_layer, FALSE, FALSE);
            }
          else
            lock_alpha = FALSE;

          /*  apply the fs with the undo specified by the value
           *  passed to this function
           */
          gimp_drawable_apply_region (layer->fs.drawable, &fsPR,
                                      push_undo, NULL,
                                      layer->opacity,
                                      layer->mode,
                                      NULL,
                                      (x1 - offx), (y1 - offy));

          /*  restore lock alpha  */
          if (lock_alpha)
            gimp_layer_set_lock_alpha (d_layer, TRUE, FALSE);
        }
    }
}