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)));
}
Exemple #2
0
static GimpValueArray *
floating_sel_remove_invoker (GimpProcedure         *procedure,
                             Gimp                  *gimp,
                             GimpContext           *context,
                             GimpProgress          *progress,
                             const GimpValueArray  *args,
                             GError               **error)
{
  gboolean success = TRUE;
  GimpLayer *floating_sel;

  floating_sel = gimp_value_get_layer (gimp_value_array_index (args, 0), gimp);

  if (success)
    {
      if (gimp_layer_is_floating_sel (floating_sel))
        {
          gimp_image_remove_layer (gimp_item_get_image (GIMP_ITEM (floating_sel)),
                                   floating_sel, TRUE, NULL);
        }
      else
        {
          g_set_error_literal (error, GIMP_PDB_ERROR,
                               GIMP_PDB_ERROR_INVALID_ARGUMENT,
                               _("Cannot remove this layer because "
                                 "it is not a floating selection."));
          success = FALSE;
        }
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
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));
    }
}
void
floating_sel_remove (GimpLayer *layer)
{
  GimpImage *image;

  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->fs.drawable));

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_REMOVE,
                               _("Remove Floating Selection"));

  /*  store the affected area from the drawable in the backing store  */
  floating_sel_relax (layer, TRUE);

  /*  Invalidate the preview of the obscured drawable.  We do this here
   *  because it will not be done until the floating selection is removed,
   *  at which point the obscured drawable's preview will not be declared
   *  invalid.
   */
  gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer));

  /*  remove the layer from the image  */
  gimp_image_remove_layer (image, layer);

  gimp_image_undo_group_end (image);
}
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);
}
static GValueArray *
floating_sel_anchor_invoker (GimpProcedure      *procedure,
                             Gimp               *gimp,
                             GimpContext        *context,
                             GimpProgress       *progress,
                             const GValueArray  *args,
                             GError            **error)
{
  gboolean success = TRUE;
  GimpLayer *floating_sel;

  floating_sel = gimp_value_get_layer (&args->values[0], gimp);

  if (success)
    {
      if (gimp_layer_is_floating_sel (floating_sel))
        {
          floating_sel_anchor (floating_sel);
        }
      else
        {
          g_set_error_literal (error, GIMP_PDB_ERROR,
                               GIMP_PDB_ERROR_INVALID_ARGUMENT,
                               _("Cannot anchor this layer because "
                                 "it is not a floating selection."));
          success = FALSE;
        }
    }

  return gimp_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}
GimpLayer *
gimp_image_flatten (GimpImage    *image,
                    GimpContext  *context,
                    GError      **error)
{
  GList     *list;
  GSList    *merge_list = NULL;
  GimpLayer *layer;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  for (list = gimp_image_get_layer_iter (image);
       list;
       list = g_list_next (list))
    {
      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);
    }

  if (merge_list)
    {
      gimp_set_busy (image->gimp);

      gimp_image_undo_group_start (image,
                                   GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
                                   C_("undo-type", "Flatten Image"));

      /* 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,
                                       gimp_image_get_layers (image),
                                       merge_list, context,
                                       GIMP_FLATTEN_IMAGE);
      g_slist_free (merge_list);

      gimp_image_alpha_changed (image);

      gimp_image_undo_group_end (image);

      gimp_unset_busy (image->gimp);

      return layer;
    }

  g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                       _("Cannot flatten an image without any visible layer."));
  return NULL;
}
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);
}
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);
}
void
floating_sel_invalidate (GimpLayer *layer)
{
  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  /*  Invalidate the attached-to drawable's preview  */
  gimp_viewable_invalidate_preview (GIMP_VIEWABLE (gimp_layer_get_floating_sel_drawable (layer)));

  /*  Invalidate the boundary  */
  layer->fs.boundary_known = FALSE;
}
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_restore (GimpLayer *layer,
                      gint       x,
                      gint       y,
                      gint       w,
                      gint       h)
{
  PixelRegion srcPR, destPR;
  gint        offx, offy;
  gint        x1, y1, x2, y2;

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

  /*  What this function does is "uncover" the specified area in the
   *  drawable that this floating selection obscures.  We do this so
   *  that either the floating selection can be removed or it can be
   *  translated
   */

  /*  Find the minimum area we need to uncover -- 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)
    {
      /*  Copy the area from the backing store to the drawable  */
      pixel_region_init (&srcPR, layer->fs.backing_store,
                         (x1 - GIMP_ITEM (layer)->offset_x),
                         (y1 - GIMP_ITEM (layer)->offset_y),
                         (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_get_tiles (layer->fs.drawable),
                         (x1 - offx), (y1 - offy), (x2 - x1), (y2 - y1), TRUE);

      copy_region (&srcPR, &destPR);
    }
}
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);
}
void removeAllLayersExceptMain(void) {
    gint *pnLayers = NULL;
    gint numLayers = 0 ;
    gint nIndex = 0 ;
    gimp_image_set_active_layer(local_vals.image_ID, drawableBeginActiveLayer);
    pnLayers = gimp_image_get_layers(local_vals.image_ID, &numLayers);
    
    for (nIndex=0;nIndex< numLayers;nIndex++) {
        if (pnLayers[nIndex] != drawableBeginActiveLayer) {
            if (gimp_layer_is_floating_sel(pnLayers[nIndex]))
            {
                gimp_floating_sel_remove(pnLayers[nIndex]);
           } else {
                gimp_image_remove_layer(local_vals.image_ID, pnLayers[nIndex]);
            }
        }
    }
    
    gimp_drawable_set_visible(drawableBeginActiveLayer, TRUE);
}
void
floating_sel_rigor (GimpLayer *layer,
                    gboolean   push_undo)
{
  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  /*  store the affected area from the drawable in the backing store  */
  floating_sel_store (layer,
                      GIMP_ITEM (layer)->offset_x,
                      GIMP_ITEM (layer)->offset_y,
                      GIMP_ITEM (layer)->width,
                      GIMP_ITEM (layer)->height);
  layer->fs.initial = TRUE;

  if (push_undo)
    gimp_image_undo_push_fs_rigor (gimp_item_get_image (GIMP_ITEM (layer)),
                                   NULL,
                                   layer);
}
void
floating_sel_relax (GimpLayer *layer,
                    gboolean   push_undo)
{
  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  /*  restore the contents of drawable the floating layer is attached to  */
  if (layer->fs.initial == FALSE)
    floating_sel_restore (layer,
                          GIMP_ITEM (layer)->offset_x,
                          GIMP_ITEM (layer)->offset_y,
                          GIMP_ITEM (layer)->width,
                          GIMP_ITEM (layer)->height);
  layer->fs.initial = TRUE;

  if (push_undo)
    gimp_image_undo_push_fs_relax (gimp_item_get_image (GIMP_ITEM (layer)),
                                   NULL,
                                   layer);
}
Exemple #17
0
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;
}
void
floating_sel_store (GimpLayer *layer,
                    gint       x,
                    gint       y,
                    gint       w,
                    gint       h)
{
  PixelRegion srcPR, destPR;
  gint        offx, offy;
  gint        x1, y1, x2, y2;

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

  /*  Check the backing store & make sure it has the correct dimensions  */
  if ((tile_manager_width  (layer->fs.backing_store) !=
       gimp_item_width (GIMP_ITEM(layer)))  ||
      (tile_manager_height (layer->fs.backing_store) !=
       gimp_item_height (GIMP_ITEM(layer))) ||
      (tile_manager_bpp    (layer->fs.backing_store) !=
       gimp_drawable_bytes (layer->fs.drawable)))
    {
      /*  free the backing store and allocate anew  */
      tile_manager_unref (layer->fs.backing_store);

      layer->fs.backing_store =
        tile_manager_new (GIMP_ITEM (layer)->width,
                          GIMP_ITEM (layer)->height,
                          gimp_drawable_bytes (layer->fs.drawable));
    }

  /*  What this function does is save the specified area of the
   *  drawable that this floating selection obscures.  We do this so
   *  that it will be possible to subsequently restore the drawable's area
   */
  gimp_item_offsets (GIMP_ITEM (layer->fs.drawable), &offx, &offy);

  /*  Find the minimum area we need to uncover -- in image space  */
  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)
    {
      /*  Copy the area from the drawable to the backing store  */
      pixel_region_init (&srcPR, gimp_drawable_get_tiles (layer->fs.drawable),
                         (x1 - offx), (y1 - offy), (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, layer->fs.backing_store,
                         (x1 - GIMP_ITEM (layer)->offset_x),
                         (y1 - GIMP_ITEM (layer)->offset_y),
                         (x2 - x1), (y2 - y1), TRUE);

      copy_region (&srcPR, &destPR);
    }
}
void
layers_actions_update (GimpActionGroup *group,
                       gpointer         data)
{
  GimpImage     *image          = action_data_get_image (data);
  GimpLayer     *layer          = NULL;
  GimpLayerMask *mask           = NULL;     /*  layer mask             */
  gboolean       fs             = FALSE;    /*  floating sel           */
  gboolean       ac             = FALSE;    /*  active channel         */
  gboolean       sel            = FALSE;
  gboolean       alpha          = FALSE;    /*  alpha channel present  */
  gboolean       indexed        = FALSE;    /*  is indexed             */
  gboolean       lock_alpha     = FALSE;
  gboolean       can_lock_alpha = FALSE;
  gboolean       text_layer     = FALSE;
  gboolean       writable       = FALSE;
  gboolean       children       = FALSE;
  GList         *next           = NULL;
  GList         *next_visible   = NULL;
  GList         *prev           = NULL;

  if (image)
    {
      fs      = (gimp_image_get_floating_selection (image) != NULL);
      ac      = (gimp_image_get_active_channel (image) != NULL);
      sel     = ! gimp_channel_is_empty (gimp_image_get_mask (image));
      indexed = (gimp_image_base_type (image) == GIMP_INDEXED);

      layer = gimp_image_get_active_layer (image);

      if (layer)
        {
          GList *layer_list;
          GList *list;

          mask           = gimp_layer_get_mask (layer);
          lock_alpha     = gimp_layer_get_lock_alpha (layer);
          can_lock_alpha = gimp_layer_can_lock_alpha (layer);
          alpha          = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer));
          writable       = ! gimp_item_is_content_locked (GIMP_ITEM (layer));

          if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
            children = TRUE;

          layer_list = gimp_item_get_container_iter (GIMP_ITEM (layer));

          list = g_list_find (layer_list, layer);

          if (list)
            {
              prev = g_list_previous (list);
              next = g_list_next (list);

              for (next_visible = next;
                   next_visible;
                   next_visible = g_list_next (next_visible))
                {
                  if (gimp_item_get_visible (next_visible->data))
                    {
                      /*  "next_visible" is actually "next_visible" and
                       *  "writable" and "not group"
                       */
                      if (gimp_item_is_content_locked (next_visible->data) ||
                          gimp_viewable_get_children (next_visible->data))
                        next_visible = NULL;

                      break;
                    }
                }
            }

          text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
        }
    }

#define SET_VISIBLE(action,condition) \
        gimp_action_group_set_action_visible (group, action, (condition) != 0)
#define SET_SENSITIVE(action,condition) \
        gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
#define SET_ACTIVE(action,condition) \
        gimp_action_group_set_action_active (group, action, (condition) != 0)
#define SET_LABEL(action,label) \
        gimp_action_group_set_action_label (group, action, label)

  SET_VISIBLE   ("layers-text-tool",        text_layer && !ac);
  SET_SENSITIVE ("layers-edit-attributes",  layer && !fs && !ac);

  if (layer && gimp_layer_is_floating_sel (layer))
    {
      SET_LABEL ("layers-new",             C_("layers-action", "To _New Layer"));
      SET_LABEL ("layers-new-last-values", C_("layers-action", "To _New Layer"));
    }
  else
    {
      SET_LABEL ("layers-new",             C_("layers-action", "_New Layer..."));
      SET_LABEL ("layers-new-last-values", C_("layers-action", "_New Layer"));
    }

  SET_SENSITIVE ("layers-new",              image);
  SET_SENSITIVE ("layers-new-last-values",  image);
  SET_SENSITIVE ("layers-new-from-visible", image);
  SET_SENSITIVE ("layers-new-group",        image && !indexed);
  SET_SENSITIVE ("layers-duplicate",        layer && !fs && !ac);
  SET_SENSITIVE ("layers-delete",           layer && !ac);

  SET_SENSITIVE ("layers-select-top",       layer && !fs && !ac && prev);
  SET_SENSITIVE ("layers-select-bottom",    layer && !fs && !ac && next);
  SET_SENSITIVE ("layers-select-previous",  layer && !fs && !ac && prev);
  SET_SENSITIVE ("layers-select-next",      layer && !fs && !ac && next);

  SET_SENSITIVE ("layers-raise",            layer && !fs && !ac && prev);
  SET_SENSITIVE ("layers-raise-to-top",     layer && !fs && !ac && prev);
  SET_SENSITIVE ("layers-lower",            layer && !fs && !ac && next);
  SET_SENSITIVE ("layers-lower-to-bottom",  layer && !fs && !ac && next);

  SET_SENSITIVE ("layers-anchor",           layer &&  fs && !ac);
  SET_SENSITIVE ("layers-merge-down",       layer && !fs && !ac && next_visible);
  SET_VISIBLE   ("layers-merge-group",      children);
  SET_SENSITIVE ("layers-merge-group",      layer && !fs && !ac && children);
  SET_SENSITIVE ("layers-merge-layers",     layer && !fs && !ac);
  SET_SENSITIVE ("layers-flatten-image",    layer && !fs && !ac);

  SET_VISIBLE   ("layers-text-discard",             text_layer && !ac);
  SET_VISIBLE   ("layers-text-to-vectors",          text_layer && !ac);
  SET_VISIBLE   ("layers-text-along-vectors",       text_layer && !ac);

  SET_SENSITIVE ("layers-resize",          writable && !ac);
  SET_SENSITIVE ("layers-resize-to-image", writable && !ac);
  SET_SENSITIVE ("layers-scale",           writable && !ac);

  SET_SENSITIVE ("layers-crop",            writable && sel);

  SET_SENSITIVE ("layers-alpha-add",       writable && !children && !fs && !alpha);
  SET_SENSITIVE ("layers-alpha-remove",    writable && !children && !fs &&  alpha);

  SET_SENSITIVE ("layers-lock-alpha", can_lock_alpha);
  SET_ACTIVE    ("layers-lock-alpha", lock_alpha);

  SET_SENSITIVE ("layers-mask-add",    layer    && !fs && !ac && !mask && !children);
  SET_SENSITIVE ("layers-mask-apply",  writable && !fs && !ac &&  mask && !children);
  SET_SENSITIVE ("layers-mask-delete", layer    && !fs && !ac &&  mask);

  SET_SENSITIVE ("layers-mask-edit",    layer && !fs && !ac &&  mask);
  SET_SENSITIVE ("layers-mask-show",    layer && !fs && !ac &&  mask);
  SET_SENSITIVE ("layers-mask-disable", layer && !fs && !ac &&  mask);

  SET_ACTIVE ("layers-mask-edit",    mask && gimp_layer_mask_get_edit (mask));
  SET_ACTIVE ("layers-mask-show",    mask && gimp_layer_mask_get_show (mask));
  SET_ACTIVE ("layers-mask-disable", mask && !gimp_layer_mask_get_apply (mask));

  SET_SENSITIVE ("layers-mask-selection-replace",   layer && !fs && !ac && mask);
  SET_SENSITIVE ("layers-mask-selection-add",       layer && !fs && !ac && mask);
  SET_SENSITIVE ("layers-mask-selection-subtract",  layer && !fs && !ac && mask);
  SET_SENSITIVE ("layers-mask-selection-intersect", layer && !fs && !ac && mask);

  SET_SENSITIVE ("layers-alpha-selection-replace",   layer && !fs && !ac);
  SET_SENSITIVE ("layers-alpha-selection-add",       layer && !fs && !ac);
  SET_SENSITIVE ("layers-alpha-selection-subtract",  layer && !fs && !ac);
  SET_SENSITIVE ("layers-alpha-selection-intersect", layer && !fs && !ac);

#undef SET_VISIBLE
#undef SET_SENSITIVE
#undef SET_ACTIVE
#undef SET_LABEL
}
static void
gimp_move_tool_cursor_update (GimpTool         *tool,
                              const GimpCoords *coords,
                              GdkModifierType   state,
                              GimpDisplay      *display)
{
  GimpMoveOptions    *options     = GIMP_MOVE_TOOL_GET_OPTIONS (tool);
  GimpDisplayShell   *shell       = gimp_display_get_shell (display);
  GimpImage          *image       = gimp_display_get_image (display);
  GimpCursorType      cursor      = GIMP_CURSOR_MOUSE;
  GimpToolCursorType  tool_cursor = GIMP_TOOL_CURSOR_MOVE;
  GimpCursorModifier  modifier    = GIMP_CURSOR_MODIFIER_NONE;

  if (options->move_type == GIMP_TRANSFORM_TYPE_PATH)
    {
      tool_cursor = GIMP_TOOL_CURSOR_PATHS;
      modifier    = GIMP_CURSOR_MODIFIER_MOVE;

      if (options->move_current)
        {
          if (! gimp_image_get_active_vectors (image))
            modifier = GIMP_CURSOR_MODIFIER_BAD;
        }
      else
        {
          if (gimp_draw_tool_on_vectors (GIMP_DRAW_TOOL (tool), display,
                                         coords, 7, 7,
                                         NULL, NULL, NULL, NULL, NULL, NULL))
            {
              tool_cursor = GIMP_TOOL_CURSOR_HAND;
            }
          else
            {
              modifier = GIMP_CURSOR_MODIFIER_BAD;
            }
        }
    }
  else if (options->move_type == GIMP_TRANSFORM_TYPE_SELECTION)
    {
      tool_cursor = GIMP_TOOL_CURSOR_RECT_SELECT;
      modifier    = GIMP_CURSOR_MODIFIER_MOVE;

      if (gimp_channel_is_empty (gimp_image_get_mask (image)))
        modifier = GIMP_CURSOR_MODIFIER_BAD;
    }
  else if (options->move_current)
    {
      if (! gimp_image_get_active_drawable (image))
        modifier = GIMP_CURSOR_MODIFIER_BAD;
    }
  else
    {
      GimpGuide  *guide;
      GimpLayer  *layer;
      const gint  snap_distance = display->config->snap_distance;

      if (gimp_display_shell_get_show_guides (shell) &&
          (guide = gimp_image_find_guide (image, coords->x, coords->y,
                                          FUNSCALEX (shell, snap_distance),
                                          FUNSCALEY (shell, snap_distance))))
        {
          tool_cursor = GIMP_TOOL_CURSOR_HAND;
          modifier    = GIMP_CURSOR_MODIFIER_MOVE;
        }
      else if ((layer = gimp_image_pick_layer (image,
                                               coords->x, coords->y)))
        {
          /*  if there is a floating selection, and this aint it...  */
          if (gimp_image_get_floating_selection (image) &&
              ! gimp_layer_is_floating_sel (layer))
            {
              tool_cursor = GIMP_TOOL_CURSOR_MOVE;
              modifier    = GIMP_CURSOR_MODIFIER_ANCHOR;
            }
          else if (layer != gimp_image_get_active_layer (image))
            {
              tool_cursor = GIMP_TOOL_CURSOR_HAND;
              modifier    = GIMP_CURSOR_MODIFIER_MOVE;
            }
        }
      else
        {
          modifier = GIMP_CURSOR_MODIFIER_BAD;
        }
    }

  gimp_tool_control_set_cursor          (tool->control, cursor);
  gimp_tool_control_set_tool_cursor     (tool->control, tool_cursor);
  gimp_tool_control_set_cursor_modifier (tool->control, modifier);

  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
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);
        }
    }
}
const BoundSeg *
floating_sel_boundary (GimpLayer *layer,
                       gint      *n_segs)
{
  PixelRegion bPR;
  gint        i;

  g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
  g_return_val_if_fail (gimp_layer_is_floating_sel (layer), NULL);
  g_return_val_if_fail (n_segs != NULL, NULL);

  if (layer->fs.boundary_known == FALSE)
    {
      gint width, height;
      gint off_x, off_y;

      width  = gimp_item_width  (GIMP_ITEM (layer));
      height = gimp_item_height (GIMP_ITEM (layer));
      gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y);

      if (layer->fs.segs)
        g_free (layer->fs.segs);

      if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
        {
          /*  find the segments  */
          pixel_region_init (&bPR,
                             gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
                             0, 0, width, height, FALSE);
          layer->fs.segs = boundary_find (&bPR, BOUNDARY_WITHIN_BOUNDS,
                                          0, 0, width, height,
                                          BOUNDARY_HALF_WAY,
                                          &layer->fs.num_segs);

          /*  offset the segments  */
          for (i = 0; i < layer->fs.num_segs; i++)
            {
              layer->fs.segs[i].x1 += off_x;
              layer->fs.segs[i].y1 += off_y;
              layer->fs.segs[i].x2 += off_x;
              layer->fs.segs[i].y2 += off_y;
            }
        }
      else
        {
          layer->fs.num_segs = 4;
          layer->fs.segs     = g_new0 (BoundSeg, 4);

          /* top */
          layer->fs.segs[0].x1 = off_x;
          layer->fs.segs[0].y1 = off_y;
          layer->fs.segs[0].x2 = off_x + width;
          layer->fs.segs[0].y2 = off_y;

          /* left */
          layer->fs.segs[1].x1 = off_x;
          layer->fs.segs[1].y1 = off_y;
          layer->fs.segs[1].x2 = off_x;
          layer->fs.segs[1].y2 = off_y + height;

          /* right */
          layer->fs.segs[2].x1 = off_x + width;
          layer->fs.segs[2].y1 = off_y;
          layer->fs.segs[2].x2 = off_x + width;
          layer->fs.segs[2].y2 = off_y + height;

          /* bottom */
          layer->fs.segs[3].x1 = off_x;
          layer->fs.segs[3].y1 = off_y + height;
          layer->fs.segs[3].x2 = off_x + width;
          layer->fs.segs[3].y2 = off_y + height;
        }

      layer->fs.boundary_known = TRUE;
    }

  *n_segs = layer->fs.num_segs;

  return layer->fs.segs;
}
static void
gimp_move_tool_button_press (GimpTool            *tool,
                             const GimpCoords    *coords,
                             guint32              time,
                             GdkModifierType      state,
                             GimpButtonPressType  press_type,
                             GimpDisplay         *display)
{
  GimpMoveTool     *move    = GIMP_MOVE_TOOL (tool);
  GimpMoveOptions  *options = GIMP_MOVE_TOOL_GET_OPTIONS (tool);
  GimpDisplayShell *shell   = gimp_display_get_shell (display);
  GimpImage        *image   = gimp_display_get_image (display);

  tool->display = display;

  move->floating_layer     = NULL;
  move->guide              = NULL;
  move->moving_guide       = FALSE;
  move->old_active_layer   = NULL;
  move->old_active_vectors = NULL;

  if (! options->move_current)
    {
      if (options->move_type == GIMP_TRANSFORM_TYPE_PATH)
        {
          GimpVectors *vectors;

          if (gimp_draw_tool_on_vectors (GIMP_DRAW_TOOL (tool), display,
                                         coords, 7, 7,
                                         NULL, NULL, NULL, NULL, NULL,
                                         &vectors))
            {
              move->old_active_vectors =
                gimp_image_get_active_vectors (image);

              gimp_image_set_active_vectors (image, vectors);
            }
          else
            {
              /*  no path picked  */
              return;
            }
        }
      else if (options->move_type == GIMP_TRANSFORM_TYPE_LAYER)
        {
          GimpGuide  *guide;
          GimpLayer  *layer;
          const gint  snap_distance = display->config->snap_distance;

          if (gimp_display_shell_get_show_guides (shell) &&
              (guide = gimp_image_find_guide (image,
                                              coords->x, coords->y,
                                              FUNSCALEX (shell, snap_distance),
                                              FUNSCALEY (shell, snap_distance))))
            {
              move->guide             = guide;
              move->moving_guide      = TRUE;
              move->guide_position    = gimp_guide_get_position (guide);
              move->guide_orientation = gimp_guide_get_orientation (guide);

              gimp_tool_control_set_scroll_lock (tool->control, TRUE);
              gimp_tool_control_set_precision   (tool->control,
                                                 GIMP_CURSOR_PRECISION_PIXEL_BORDER);

              gimp_tool_control_activate (tool->control);

              gimp_display_shell_selection_pause (shell);

              gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);

              gimp_tool_push_status_length (tool, display,
                                            _("Move Guide: "),
                                            SWAP_ORIENT (move->guide_orientation),
                                            move->guide_position,
                                            NULL);

              return;
            }
          else if ((layer = gimp_image_pick_layer (image,
                                                   coords->x,
                                                   coords->y)))
            {
              if (gimp_image_get_floating_selection (image) &&
                  ! gimp_layer_is_floating_sel (layer))
                {
                  /*  If there is a floating selection, and this aint it,
                   *  use the move tool to anchor it.
                   */
                  move->floating_layer =
                    gimp_image_get_floating_selection (image);

                  gimp_tool_control_activate (tool->control);

                  return;
                }
              else
                {
                  move->old_active_layer = gimp_image_get_active_layer (image);

                  gimp_image_set_active_layer (image, layer);
                }
            }
          else
            {
              /*  no guide and no layer picked  */

              return;
            }
        }
    }

  switch (options->move_type)
    {
    case GIMP_TRANSFORM_TYPE_PATH:
      if (gimp_image_get_active_vectors (image))
        gimp_edit_selection_tool_start (tool, display, coords,
                                        GIMP_TRANSLATE_MODE_VECTORS, TRUE);
      break;

    case GIMP_TRANSFORM_TYPE_SELECTION:
      if (! gimp_channel_is_empty (gimp_image_get_mask (image)))
        gimp_edit_selection_tool_start (tool, display, coords,
                                        GIMP_TRANSLATE_MODE_MASK, TRUE);
      break;

    case GIMP_TRANSFORM_TYPE_LAYER:
      {
        GimpDrawable *drawable = gimp_image_get_active_drawable (image);

        if (GIMP_IS_LAYER_MASK (drawable))
          gimp_edit_selection_tool_start (tool, display, coords,
                                          GIMP_TRANSLATE_MODE_LAYER_MASK, TRUE);
        else if (GIMP_IS_CHANNEL (drawable))
          gimp_edit_selection_tool_start (tool, display, coords,
                                          GIMP_TRANSLATE_MODE_CHANNEL, TRUE);
        else if (GIMP_IS_LAYER (drawable))
          gimp_edit_selection_tool_start (tool, display, coords,
                                          GIMP_TRANSLATE_MODE_LAYER, TRUE);
      }
      break;
    }
}
Exemple #24
0
/* The main rotate function */
static void
rotate (void)
{
  GimpDrawable *drawable;
  gint32       *layers;
  gint          i;
  gint          nlayers;
  gint32        guide_ID;
  GuideInfo    *guide;
  GList        *guides = NULL;
  GList        *list;

  if (rotvals.angle == 0) return;

  /* if there's a selection and we try to rotate the whole image */
  /* create an error message and exit                            */
  if (rotvals.everything)
    {
      if (! gimp_selection_is_empty (image_ID))
        {
          gimp_message (_("You can not rotate the whole image if there's a selection."));
          gimp_drawable_detach (active_drawable);
          return;
        }
      if (gimp_item_is_layer (active_drawable->drawable_id) &&
          gimp_layer_is_floating_sel (active_drawable->drawable_id))
        {
          gimp_message (_("You can not rotate the whole image if there's a floating selection."));
          gimp_drawable_detach (active_drawable);
          return;
        }
    }
  else
    /* if we are trying to rotate a channel or a mask,
       create an error message and exit */
    {
      if (! gimp_item_is_layer (active_drawable->drawable_id))
        {
          gimp_message (_("Sorry, channels and masks can not be rotated."));
          gimp_drawable_detach (active_drawable);
          return;
        }
    }

  gimp_progress_init (_("Rotating"));

  gimp_image_undo_group_start (image_ID);

  if (rotvals.everything)  /* rotate the whole image */
    {
      gint32 width = gimp_image_width (image_ID);
      gint32 height = gimp_image_height (image_ID);

      gimp_drawable_detach (active_drawable);
      layers = gimp_image_get_layers (image_ID, &nlayers);
      for (i = 0; i < nlayers; i++)
        {
          drawable = gimp_drawable_get (layers[i]);
          rotate_drawable (drawable);
          gimp_drawable_detach (drawable);
        }
      g_free (layers);

      /* build a list of all guides and remove them */
      guide_ID = 0;
      while ((guide_ID = gimp_image_find_next_guide (image_ID, guide_ID)) != 0)
        {
          guide = g_new (GuideInfo, 1);
          guide->ID = guide_ID;
          guide->orientation = gimp_image_get_guide_orientation (image_ID,
                                                                 guide_ID);
          guide->position = gimp_image_get_guide_position (image_ID, guide_ID);
          guides = g_list_prepend (guides, guide);
        }
      for (list = guides; list; list = list->next)
        {
          guide = (GuideInfo *) list->data;
          gimp_image_delete_guide (image_ID, guide->ID);
        }

      /* if rotation is not 180 degrees, resize the image */
      /*    Do it now after the guides are removed, since */
      /*    gimp_image_resize() moves the guides.         */
      if (rotvals.angle != 2)
        gimp_image_resize (image_ID, height, width, 0, 0);

      /* add the guides back to the image */
      if (guides)
        {
          switch (rotvals.angle)
            {
            case 1:
              for (list = guides; list; list = list->next)
                {
                  guide = (GuideInfo *)list->data;
                  if (guide->orientation == GIMP_ORIENTATION_HORIZONTAL)
                    gimp_image_add_vguide (image_ID, height - guide->position);
                  else
                    gimp_image_add_hguide (image_ID, guide->position);
                  g_free (guide);
                }
              break;
            case 2:
              for (list = guides; list; list = list->next)
                {
                  guide = (GuideInfo *)list->data;
                  if (guide->orientation == GIMP_ORIENTATION_HORIZONTAL)
                    gimp_image_add_hguide (image_ID, height - guide->position);
                  else
                    gimp_image_add_vguide (image_ID, width - guide->position);
                  g_free (guide);
                }
              break;
            case 3:
              for (list = guides; list; list = list->next)
                {
                  guide = (GuideInfo *)list->data;
                  if (guide->orientation == GIMP_ORIENTATION_HORIZONTAL)
                    gimp_image_add_vguide (image_ID, guide->position);
                  else
                    gimp_image_add_hguide (image_ID, width - guide->position);
                  g_free (guide);
                }
              break;
            default:
              break;
            }
          g_list_free (guides);
        }
    }
  else  /* rotate only the active layer */
    {

      /* check for active selection and float it */
      if (! gimp_selection_is_empty (image_ID) &&
          ! gimp_layer_is_floating_sel (active_drawable->drawable_id))
        {
          active_drawable =
            gimp_drawable_get (gimp_selection_float (image_ID,
                                                     active_drawable->drawable_id,
                                                     0, 0));
        }

      rotate_drawable (active_drawable);
      gimp_drawable_detach (active_drawable);
    }

  gimp_image_undo_group_end (image_ID);

  return;
}
const GimpBoundSeg *
floating_sel_boundary (GimpLayer *layer,
                       gint      *n_segs)
{
  g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
  g_return_val_if_fail (gimp_layer_is_floating_sel (layer), NULL);
  g_return_val_if_fail (n_segs != NULL, NULL);

  if (layer->fs.boundary_known == FALSE)
    {
      gint width, height;
      gint off_x, off_y;

      width  = gimp_item_get_width  (GIMP_ITEM (layer));
      height = gimp_item_get_height (GIMP_ITEM (layer));
      gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y);

      if (layer->fs.segs)
        g_free (layer->fs.segs);

      if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
        {
          GeglBuffer *buffer;
          gint        i;

          /*  find the segments  */
          buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));

          layer->fs.segs = gimp_boundary_find (buffer, NULL,
                                               babl_format ("A float"),
                                               GIMP_BOUNDARY_WITHIN_BOUNDS,
                                               0, 0, width, height,
                                               GIMP_BOUNDARY_HALF_WAY,
                                               &layer->fs.num_segs);

          /*  offset the segments  */
          for (i = 0; i < layer->fs.num_segs; i++)
            {
              layer->fs.segs[i].x1 += off_x;
              layer->fs.segs[i].y1 += off_y;
              layer->fs.segs[i].x2 += off_x;
              layer->fs.segs[i].y2 += off_y;
            }
        }
      else
        {
          layer->fs.num_segs = 4;
          layer->fs.segs     = g_new0 (GimpBoundSeg, 4);

          /* top */
          layer->fs.segs[0].x1 = off_x;
          layer->fs.segs[0].y1 = off_y;
          layer->fs.segs[0].x2 = off_x + width;
          layer->fs.segs[0].y2 = off_y;

          /* left */
          layer->fs.segs[1].x1 = off_x;
          layer->fs.segs[1].y1 = off_y;
          layer->fs.segs[1].x2 = off_x;
          layer->fs.segs[1].y2 = off_y + height;

          /* right */
          layer->fs.segs[2].x1 = off_x + width;
          layer->fs.segs[2].y1 = off_y;
          layer->fs.segs[2].x2 = off_x + width;
          layer->fs.segs[2].y2 = off_y + height;

          /* bottom */
          layer->fs.segs[3].x1 = off_x;
          layer->fs.segs[3].y1 = off_y + height;
          layer->fs.segs[3].x2 = off_x + width;
          layer->fs.segs[3].y2 = off_y + height;
        }

      layer->fs.boundary_known = TRUE;
    }

  *n_segs = layer->fs.num_segs;

  return layer->fs.segs;
}
Exemple #26
0
/* Compose a roll film image from several images */
static gint32
film (void)
{
  gint          width, height;
  guchar       *hole;
  gint          film_height, film_width;
  gint          picture_width, picture_height;
  gint          picture_space, picture_x0, picture_y0;
  gint          hole_offset, hole_width, hole_height, hole_space, hole_x;
  gint          number_height, num_images, num_pictures;
  gint          j, k, picture_count;
  gdouble       f;
  gint          num_layers;
  gint32       *image_ID_src, image_ID_dst, layer_ID_src, layer_ID_dst;
  gint          image_ID_tmp;
  gint32       *layers;
  GimpDrawable *drawable_dst;
  GimpPixelRgn  pixel_rgn_dst;
  gint          new_layer;
  gint          floating_sel;

  /* initialize */

  layers = NULL;

  num_images = filmvals.num_images;
  image_ID_src = filmvals.image;

  if (num_images <= 0)
    return (-1);

  gimp_context_push ();
  gimp_context_set_foreground (&filmvals.number_color);
  gimp_context_set_background (&filmvals.film_color);

  if (filmvals.keep_height) /* Search maximum picture height */
    {
      picture_height = 0;
      for (j = 0; j < num_images; j++)
        {
          height = gimp_image_height (image_ID_src[j]);
          if (height > picture_height) picture_height = height;
        }
      film_height = (int)(picture_height / filmvals.picture_height + 0.5);
      filmvals.film_height = film_height;
    }
  else
    {
      film_height = filmvals.film_height;
      picture_height = (int)(film_height * filmvals.picture_height + 0.5);
    }

  picture_space = (int)(film_height * filmvals.picture_space + 0.5);
  picture_y0 = (film_height - picture_height)/2;

  number_height = film_height * filmvals.number_height;

  /* Calculate total film width */
  film_width = 0;
  num_pictures = 0;
  for (j = 0; j < num_images; j++)
    {
      layers = gimp_image_get_layers (image_ID_src[j], &num_layers);
      /* Get scaled image size */
      width = gimp_image_width (image_ID_src[j]);
      height = gimp_image_height (image_ID_src[j]);
      f = ((double)picture_height) / (double)height;
      picture_width = width * f;

      for (k = 0; k < num_layers; k++)
        {
          if (gimp_layer_is_floating_sel (layers[k]))
            continue;

          film_width += (picture_space/2);  /* Leading space */
          film_width += picture_width;      /* Scaled image width */
          film_width += (picture_space/2);  /* Trailing space */
          num_pictures++;
        }

      g_free (layers);
    }

#ifdef FILM_DEBUG
  g_printerr ("film_height = %d, film_width = %d\n", film_height, film_width);
  g_printerr ("picture_height = %d, picture_space = %d, picture_y0 = %d\n",
              picture_height, picture_space, picture_y0);
  g_printerr ("Number of pictures = %d\n", num_pictures);
#endif

  image_ID_dst = create_new_image (_("Untitled"),
                                   (guint) film_width, (guint) film_height,
                                   GIMP_RGB_IMAGE, &layer_ID_dst,
                                   &drawable_dst, &pixel_rgn_dst);

  /* Fill film background */
  gimp_drawable_fill (layer_ID_dst, GIMP_FILL_BACKGROUND);

  /* Draw all the holes */
  hole_offset = film_height * filmvals.hole_offset;
  hole_width = film_height * filmvals.hole_width;
  hole_height = film_height * filmvals.hole_height;
  hole_space = film_height * filmvals.hole_space;
  hole_x = hole_space / 2;

#ifdef FILM_DEBUG
  g_printerr ("hole_x %d hole_offset %d hole_width %d hole_height %d hole_space %d\n",
              hole_x, hole_offset, hole_width, hole_height, hole_space );
#endif

  hole = create_hole_rgb (hole_width, hole_height);
  if (hole)
    {
      while (hole_x < film_width)
        {
          draw_hole_rgb (drawable_dst, hole_x,
                         hole_offset,
                         hole_width, hole_height, hole);
          draw_hole_rgb (drawable_dst, hole_x,
                         film_height-hole_offset-hole_height,
                         hole_width, hole_height, hole);

          hole_x += hole_width + hole_space;
        }
      g_free (hole);
    }
  gimp_drawable_detach (drawable_dst);


  /* Compose all images and layers */
  picture_x0 = 0;
  picture_count = 0;
  for (j = 0; j < num_images; j++)
    {
      image_ID_tmp = gimp_image_duplicate (image_ID_src[j]);
      width = gimp_image_width (image_ID_tmp);
      height = gimp_image_height (image_ID_tmp);
      f = ((gdouble) picture_height) / (gdouble) height;
      picture_width = width * f;
      if (gimp_image_base_type (image_ID_tmp) != GIMP_RGB)
        gimp_image_convert_rgb (image_ID_tmp);
      gimp_image_scale (image_ID_tmp, picture_width, picture_height);

      layers = gimp_image_get_layers (image_ID_tmp, &num_layers);
      for (k = 0; k < num_layers; k++)
        {
          if (gimp_layer_is_floating_sel (layers[k]))
            continue;

          picture_x0 += picture_space / 2;

          layer_ID_src = layers[k];
          gimp_layer_resize_to_image_size (layer_ID_src);
          new_layer = gimp_layer_new_from_drawable (layer_ID_src,
                                                    image_ID_dst);
          gimp_image_insert_layer (image_ID_dst, new_layer, -1, -1);
          gimp_layer_set_offsets (new_layer, picture_x0, picture_y0);

          /* Draw picture numbers */
          if ((number_height > 0) &&
              (filmvals.number_pos[0] || filmvals.number_pos[1]))
            {
              if (filmvals.number_pos[0])
                draw_number (layer_ID_dst,
                             filmvals.number_start + picture_count,
                             picture_x0 + picture_width/2,
                             (hole_offset-number_height)/2, number_height);
              if (filmvals.number_pos[1])
                draw_number (layer_ID_dst,
                             filmvals.number_start + picture_count,
                             picture_x0 + picture_width/2,
                             film_height - (hole_offset + number_height)/2,
                             number_height);
            }

          picture_x0 += picture_width + (picture_space/2);

          gimp_progress_update (((gdouble) (picture_count + 1)) /
                                (gdouble) num_pictures);

          picture_count++;
        }

      g_free (layers);
      gimp_image_delete (image_ID_tmp);
    }
  gimp_progress_update (1.0);

  gimp_image_flatten (image_ID_dst);

  /* Drawing text/numbers leaves us with a floating selection. Stop it */
  floating_sel = gimp_image_get_floating_sel (image_ID_dst);
  if (floating_sel != -1)
    gimp_floating_sel_anchor (floating_sel);

  gimp_context_pop ();

  return image_ID_dst;
}
static void
gimp_projection_construct_legacy (GimpProjection *proj,
                                  gboolean        with_layers,
                                  gint            x,
                                  gint            y,
                                  gint            w,
                                  gint            h)
{
    GList *list;
    GList *reverse_list = NULL;
    gint   proj_off_x;
    gint   proj_off_y;

    for (list = gimp_projectable_get_channels (proj->projectable);
            list;
            list = g_list_next (list))
    {
        if (gimp_item_get_visible (GIMP_ITEM (list->data)))
        {
            reverse_list = g_list_prepend (reverse_list, list->data);
        }
    }

    if (with_layers)
    {
        for (list = gimp_projectable_get_layers (proj->projectable);
                list;
                list = g_list_next (list))
        {
            GimpLayer *layer = list->data;

            if (! gimp_layer_is_floating_sel (layer) &&
                    gimp_item_get_visible (GIMP_ITEM (layer)))
            {
                /*  only add layers that are visible and not floating selections
                 *  to the list
                 */
                reverse_list = g_list_prepend (reverse_list, layer);
            }
        }
    }

    gimp_projectable_get_offset (proj->projectable, &proj_off_x, &proj_off_y);

    for (list = reverse_list; list; list = g_list_next (list))
    {
        GimpItem    *item = list->data;
        PixelRegion  projPR;
        gint         x1, y1;
        gint         x2, y2;
        gint         off_x;
        gint         off_y;

        gimp_item_get_offset (item, &off_x, &off_y);

        /*  subtract the projectable's offsets because the list of
         *  update areas is in tile-pyramid coordinates, but our
         *  external API is always in terms of image coordinates.
         */
        off_x -= proj_off_x;
        off_y -= proj_off_y;

        x1 = CLAMP (off_x,                               x, x + w);
        y1 = CLAMP (off_y,                               y, y + h);
        x2 = CLAMP (off_x + gimp_item_get_width  (item), x, x + w);
        y2 = CLAMP (off_y + gimp_item_get_height (item), y, y + h);

        pixel_region_init (&projPR,
                           gimp_pickable_get_tiles (GIMP_PICKABLE (proj)),
                           x1, y1, x2 - x1, y2 - y1,
                           TRUE);

        gimp_drawable_project_region (GIMP_DRAWABLE (item),
                                      x1 - off_x, y1 - off_y,
                                      x2 - x1,    y2 - y1,
                                      &projPR,
                                      proj->construct_flag);

        proj->construct_flag = TRUE;  /*  something was projected  */
    }

    g_list_free (reverse_list);
}
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);
}