home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / floating_sel.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  16.0 KB  |  529 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <glib.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "drawable.h"
  27. #include "layer.h"
  28. #include "floating_sel.h"
  29. #include "gdisplay.h"
  30. #include "gimage.h"
  31. #include "gimage_mask.h"
  32. #include "paint_funcs.h"
  33. #include "undo.h"
  34.  
  35. #include "layer_pvt.h"
  36. #include "tile_manager_pvt.h"        /* ick. */
  37.  
  38. #include "libgimp/gimpmath.h"
  39.  
  40. #include "libgimp/gimpintl.h"
  41.  
  42.  
  43. void
  44. floating_sel_attach (Layer        *layer,
  45.              GimpDrawable *drawable)
  46. {
  47.   GImage *gimage;
  48.   Layer *floating_sel;
  49.  
  50.   if (! (gimage = drawable_gimage (drawable)))
  51.     return;
  52.  
  53.   /*  If there is already a floating selection, anchor it  */
  54.   if (gimage->floating_sel != NULL)
  55.     {
  56.       floating_sel = gimage->floating_sel;
  57.       floating_sel_anchor (gimage_floating_sel (gimage));
  58.  
  59.       /*  if we were pasting to the old floating selection, paste now to the drawable  */
  60.       if (drawable == GIMP_DRAWABLE (floating_sel))
  61.     drawable = gimage_active_drawable (gimage);
  62.     }
  63.  
  64.   /*  set the drawable and allocate a backing store  */
  65.   layer->preserve_trans = TRUE;
  66.   layer->fs.drawable = drawable;
  67.   layer->fs.backing_store =
  68.     tile_manager_new (GIMP_DRAWABLE (layer)->width,
  69.               GIMP_DRAWABLE (layer)->height,
  70.               drawable_bytes (drawable));
  71.  
  72.   /*  because setting the sensitivity in the layers_dialog lock call redraws the
  73.    *  previews, we need to lock the dialogs before the floating sel is actually added.
  74.    *  however, they won't lock unless we set the gimage's floating sel pointer
  75.    */
  76.   gimage->floating_sel = layer;
  77.  
  78.   /*  add the layer to the gimage  */
  79.   gimage_add_layer (gimage, layer, 0);
  80.  
  81.   /*  store the affected area from the drawable in the backing store  */
  82.   floating_sel_rigor (layer, TRUE);
  83. }
  84.  
  85. void
  86. floating_sel_remove (Layer *layer)
  87. {
  88.   GImage *gimage;
  89.  
  90.   if (! (gimage = drawable_gimage (layer->fs.drawable)))
  91.     return;
  92.  
  93.   /*  store the affected area from the drawable in the backing store  */
  94.   floating_sel_relax (layer, TRUE);
  95.  
  96.   /*  invalidate the preview of the obscured drawable.  We do this here
  97.    *  because it will not be done until the floating selection is removed,
  98.    *  at which point the obscured drawable's preview will not be declared invalid
  99.    */
  100.   gimp_drawable_invalidate_preview (GIMP_DRAWABLE (layer), TRUE);
  101.  
  102.   /*  remove the layer from the gimage  */
  103.   gimage_remove_layer (gimage, layer);
  104. }
  105.  
  106. void
  107. floating_sel_anchor (Layer *layer)
  108. {
  109.   GImage *gimage;
  110.  
  111.   if (! (gimage = drawable_gimage (GIMP_DRAWABLE (layer))))
  112.     return;
  113.   if (! layer_is_floating_sel (layer))
  114.     {
  115.       g_message (_("Cannot anchor this layer because\nit is not a floating selection."));
  116.       return;
  117.     }
  118.  
  119.   /*  Start a floating selection anchoring undo  */
  120.   undo_push_group_start (gimage, FS_ANCHOR_UNDO);
  121.  
  122.   /* Invalidate the previews of the layer that will be composited with the floating section. */
  123.  
  124.   gimp_drawable_invalidate_preview (layer->fs.drawable, TRUE);
  125.  
  126.   /*  Relax the floating selection  */
  127.   floating_sel_relax (layer, TRUE);
  128.  
  129.   /*  Composite the floating selection contents  */
  130.   floating_sel_composite (layer,
  131.               GIMP_DRAWABLE (layer)->offset_x,
  132.               GIMP_DRAWABLE (layer)->offset_y,
  133.               GIMP_DRAWABLE (layer)->width,
  134.               GIMP_DRAWABLE (layer)->height, TRUE);
  135.  
  136.   /*  remove the floating selection  */
  137.   gimage_remove_layer (gimage, layer);
  138.  
  139.   /*  end the group undo  */
  140.   undo_push_group_end (gimage);
  141.  
  142.   /*  invalidate the boundaries  */
  143.   gimage_mask_invalidate (gimage);
  144. }
  145.  
  146. void
  147. floating_sel_reset (Layer *layer)
  148. {
  149.   GImage *gimage;
  150.  
  151.   if (! (gimage = drawable_gimage (GIMP_DRAWABLE (layer))))
  152.     return;
  153.  
  154.   /*  set the underlying drawable to active  */
  155.   if (GIMP_IS_LAYER (layer->fs.drawable))
  156.     gimage_set_active_layer (gimage, GIMP_LAYER (layer->fs.drawable));
  157.   else if (GIMP_IS_LAYER_MASK (layer->fs.drawable))
  158.     gimage_set_active_layer (gimage,
  159.                  GIMP_LAYER_MASK (layer->fs.drawable)->layer);
  160.   else if (GIMP_IS_CHANNEL (layer->fs.drawable))
  161.     {
  162.       gimage_set_active_channel (gimage, GIMP_CHANNEL (layer->fs.drawable));
  163.       if (gimage->layers)
  164.     gimage->active_layer = (((Layer *) gimage->layer_stack->data));
  165.       else
  166.     gimage->active_layer = NULL;
  167.     }
  168. }
  169.  
  170. void
  171. floating_sel_to_layer (Layer *layer)
  172. {
  173.   FStoLayerUndo *fsu;
  174.   int off_x, off_y;
  175.   int width, height;
  176.  
  177.   GImage *gimage;
  178.  
  179.   if (! (gimage = drawable_gimage (GIMP_DRAWABLE (layer))))
  180.     return;
  181.  
  182.   /*  Check if the floating layer belongs to a channel...  */
  183.   if (GIMP_IS_CHANNEL (layer->fs.drawable))
  184.     {
  185.       g_message (_("Cannot create a new layer from the floating\n"
  186.          "selection because it belongs to a\n"
  187.          "layer mask or channel."));
  188.       return;
  189.     }
  190.  
  191.   /*  restore the contents of the drawable  */
  192.   floating_sel_restore (layer,
  193.             GIMP_DRAWABLE (layer)->offset_x,
  194.             GIMP_DRAWABLE (layer)->offset_y,
  195.             GIMP_DRAWABLE (layer)->width,
  196.             GIMP_DRAWABLE (layer)->height);
  197.  
  198.   /*  determine whether the resulting layer needs an update  */
  199.   drawable_offsets (layer->fs.drawable, &off_x, &off_y);
  200.   width = drawable_width (layer->fs.drawable);
  201.   height = drawable_height (layer->fs.drawable);
  202.  
  203.   /*  update the fs drawable--this updates the gimage composite preview
  204.    *  as well as the underlying drawable's
  205.    */
  206.   gimp_drawable_invalidate_preview (GIMP_DRAWABLE (layer), TRUE);
  207.  
  208.   /*  allocate the undo structure  */
  209.   fsu = g_new (FStoLayerUndo, 1);
  210.   fsu->layer    = layer;
  211.   fsu->drawable = layer->fs.drawable;
  212.  
  213.   undo_push_fs_to_layer (gimage, fsu);
  214.  
  215.   /*  clear the selection  */
  216.   layer_invalidate_boundary (layer);
  217.  
  218.   /*  Set pointers  */
  219.   layer->fs.drawable = NULL;
  220.   gimage->floating_sel = NULL;
  221.   GIMP_DRAWABLE (layer)->visible = TRUE;
  222.  
  223.   /*  if the floating selection exceeds the attached layer's extents,
  224.       update the new layer  */
  225.  
  226.   /*  I don't think that the preview is ever valid as is, since the layer
  227.       will be added on top of the others.  Revert this if I'm wrong.
  228.       msw@gimp.org
  229.   */
  230.  
  231.   drawable_update (GIMP_DRAWABLE (layer),
  232.            0, 0,
  233.            GIMP_DRAWABLE (layer)->width,
  234.            GIMP_DRAWABLE (layer)->height);
  235.   
  236.   /* This may be undesirable when invoked non-interactively... we'll see. */
  237.   /*reinit_layer_idlerender (gimage, layer);*/
  238. }
  239.  
  240. void
  241. floating_sel_store (Layer *layer,
  242.             int    x,
  243.             int    y,
  244.             int    w,
  245.             int    h)
  246. {
  247.   PixelRegion srcPR, destPR;
  248.   int offx, offy;
  249.   int x1, y1, x2, y2;
  250.  
  251.   /*  Check the backing store & make sure it has the correct dimensions  */
  252.   if (layer->fs.backing_store->width != drawable_width (GIMP_DRAWABLE(layer)) ||
  253.       layer->fs.backing_store->height != drawable_height (GIMP_DRAWABLE(layer)) ||
  254.       layer->fs.backing_store->bpp != drawable_bytes (layer->fs.drawable))
  255.     {
  256.       /*  free the backing store and allocate anew  */
  257.       tile_manager_destroy (layer->fs.backing_store);
  258.  
  259.       layer->fs.backing_store = tile_manager_new (GIMP_DRAWABLE (layer)->width,
  260.                           GIMP_DRAWABLE (layer)->height,
  261.                           drawable_bytes (layer->fs.drawable));
  262.     }
  263.  
  264.   /*  What this function does is save the specified area of the
  265.    *  drawable that this floating selection obscures.  We do this so
  266.    *  that it will be possible to subsequently restore the drawable's area
  267.    */
  268.   drawable_offsets (layer->fs.drawable, &offx, &offy);
  269.  
  270.   /*  Find the minimum area we need to uncover -- in gimage space  */
  271.   x1 = MAX (GIMP_DRAWABLE (layer)->offset_x, offx);
  272.   y1 = MAX (GIMP_DRAWABLE (layer)->offset_y, offy);
  273.   x2 = MIN (GIMP_DRAWABLE (layer)->offset_x + GIMP_DRAWABLE (layer)->width,
  274.         offx + drawable_width (layer->fs.drawable));
  275.   y2 = MIN (GIMP_DRAWABLE (layer)->offset_y + GIMP_DRAWABLE (layer)->height,
  276.         offy + drawable_height (layer->fs.drawable));
  277.  
  278.   x1 = CLAMP (x, x1, x2);
  279.   y1 = CLAMP (y, y1, y2);
  280.   x2 = CLAMP (x + w, x1, x2);
  281.   y2 = CLAMP (y + h, y1, y2);
  282.  
  283.   if ((x2 - x1) > 0 && (y2 - y1) > 0)
  284.     {
  285.       /*  Copy the area from the drawable to the backing store  */
  286.       pixel_region_init (&srcPR, drawable_data (layer->fs.drawable),
  287.              (x1 - offx), (y1 - offy), (x2 - x1), (y2 - y1), FALSE);
  288.       pixel_region_init (&destPR, layer->fs.backing_store,
  289.              (x1 - GIMP_DRAWABLE (layer)->offset_x),
  290.              (y1 - GIMP_DRAWABLE(layer)->offset_y),
  291.              (x2 - x1), (y2 - y1), TRUE);
  292.  
  293.       copy_region (&srcPR, &destPR);
  294.     }
  295. }
  296.  
  297. void
  298. floating_sel_restore (Layer *layer,
  299.               int    x,
  300.               int    y,
  301.               int    w,
  302.               int    h)
  303. {
  304.   PixelRegion srcPR, destPR;
  305.   int offx, offy;
  306.   int x1, y1, x2, y2;
  307.  
  308.   /*  What this function does is "uncover" the specified area in the
  309.    *  drawable that this floating selection obscures.  We do this so
  310.    *  that either the floating selection can be removed or it can be
  311.    *  translated
  312.    */
  313.  
  314.   /*  Find the minimum area we need to uncover -- in gimage space  */
  315.   drawable_offsets (layer->fs.drawable, &offx, &offy);
  316.   x1 = MAX (GIMP_DRAWABLE (layer)->offset_x, offx);
  317.   y1 = MAX (GIMP_DRAWABLE (layer)->offset_y, offy);
  318.   x2 = MIN (GIMP_DRAWABLE (layer)->offset_x + GIMP_DRAWABLE (layer)->width,
  319.         offx + drawable_width (layer->fs.drawable));
  320.   y2 = MIN (GIMP_DRAWABLE(layer)->offset_y + GIMP_DRAWABLE (layer)->height,
  321.         offy + drawable_height (layer->fs.drawable));
  322.  
  323.   x1 = CLAMP (x, x1, x2);
  324.   y1 = CLAMP (y, y1, y2);
  325.   x2 = CLAMP (x + w, x1, x2);
  326.   y2 = CLAMP (y + h, y1, y2);
  327.  
  328.   if ((x2 - x1) > 0 && (y2 - y1) > 0)
  329.     {
  330.       /*  Copy the area from the backing store to the drawable  */
  331.       pixel_region_init (&srcPR, layer->fs.backing_store,
  332.              (x1 - GIMP_DRAWABLE (layer)->offset_x),
  333.              (y1 - GIMP_DRAWABLE (layer)->offset_y),
  334.              (x2 - x1), (y2 - y1), FALSE);
  335.       pixel_region_init (&destPR, drawable_data (layer->fs.drawable),
  336.              (x1 - offx), (y1 - offy), (x2 - x1), (y2 - y1), TRUE);
  337.  
  338.       copy_region (&srcPR, &destPR);
  339.     }
  340. }
  341.  
  342. void
  343. floating_sel_rigor (Layer *layer,
  344.             int    undo)
  345. {
  346.   GImage *gimage = GIMP_DRAWABLE(layer)->gimage;
  347.  
  348.   /*  store the affected area from the drawable in the backing store  */
  349.   floating_sel_store (layer,
  350.               GIMP_DRAWABLE (layer)->offset_x,
  351.               GIMP_DRAWABLE (layer)->offset_y,
  352.               GIMP_DRAWABLE (layer)->width,
  353.               GIMP_DRAWABLE (layer)->height);
  354.   layer->fs.initial = TRUE;
  355.  
  356.   if (undo)
  357.     undo_push_fs_rigor (gimage, GIMP_DRAWABLE (layer)->ID);
  358. }
  359.  
  360. void
  361. floating_sel_relax (Layer *layer,
  362.             int    undo)
  363. {
  364.   GImage *gimage = GIMP_DRAWABLE(layer)->gimage;
  365.  
  366.   /*  restore the contents of drawable the floating layer is attached to  */
  367.   if (layer->fs.initial == FALSE)
  368.     floating_sel_restore (layer,
  369.               GIMP_DRAWABLE (layer)->offset_x,
  370.               GIMP_DRAWABLE (layer)->offset_y,
  371.               GIMP_DRAWABLE (layer)->width,
  372.               GIMP_DRAWABLE (layer)->height);
  373.   layer->fs.initial = TRUE;
  374.  
  375.   if (undo)
  376.     undo_push_fs_relax (gimage, GIMP_DRAWABLE (layer)->ID);
  377. }
  378.  
  379. void
  380. floating_sel_composite (Layer *layer,
  381.             int    x,
  382.             int    y,
  383.             int    w,
  384.             int    h,
  385.             int    undo)
  386. {
  387.   PixelRegion fsPR;
  388.   GImage *gimage;
  389.   Layer *d_layer;
  390.   int preserve_trans;
  391.   int active[MAX_CHANNELS];
  392.   int offx, offy;
  393.   int x1, y1, x2, y2;
  394.   int i;
  395.  
  396.   d_layer = NULL;
  397.  
  398.   if (! (gimage = drawable_gimage (GIMP_DRAWABLE (layer))))
  399.     return;
  400.  
  401.   /*  What this function does is composite the specified area of the
  402.    *  drawble with the floating selection.  We do this when the gimage
  403.    *  is constructed, before any other composition takes place.
  404.    */
  405.  
  406.   /*  If this isn't the first composite, restore the image underneath  */
  407.   if (! layer->fs.initial)
  408.     floating_sel_restore (layer, x, y, w, h);
  409.   else if (GIMP_DRAWABLE(layer)->visible)
  410.     layer->fs.initial = FALSE;
  411.  
  412.   /*  First restore what's behind the image if necessary, then check for visibility  */
  413.   if (GIMP_DRAWABLE(layer)->visible)
  414.     {
  415.       /*  Find the minimum area we need to composite -- in gimage space  */
  416.       drawable_offsets (layer->fs.drawable, &offx, &offy);
  417.       x1 = MAX (GIMP_DRAWABLE (layer)->offset_x, offx);
  418.       y1 = MAX (GIMP_DRAWABLE (layer)->offset_y, offy);
  419.       x2 = MIN (GIMP_DRAWABLE (layer)->offset_x +
  420.         GIMP_DRAWABLE (layer)->width,
  421.         offx + drawable_width (layer->fs.drawable));
  422.       y2 = MIN (GIMP_DRAWABLE (layer)->offset_y +
  423.         GIMP_DRAWABLE (layer)->height,
  424.         offy + drawable_height (layer->fs.drawable));
  425.  
  426.       x1 = CLAMP (x, x1, x2);
  427.       y1 = CLAMP (y, y1, y2);
  428.       x2 = CLAMP (x + w, x1, x2);
  429.       y2 = CLAMP (y + h, y1, y2);
  430.  
  431.       if ((x2 - x1) > 0 && (y2 - y1) > 0)
  432.     {
  433.       /*  composite the area from the layer to the drawable  */
  434.       pixel_region_init (&fsPR, GIMP_DRAWABLE (layer)->tiles,
  435.                  (x1 - GIMP_DRAWABLE (layer)->offset_x),
  436.                  (y1 - GIMP_DRAWABLE (layer)->offset_y),
  437.                  (x2 - x1), (y2 - y1), FALSE);
  438.  
  439.       /*  a kludge here to prevent the case of the drawable
  440.        *  underneath having preserve transparency on, and disallowing
  441.        *  the composited floating selection from being shown
  442.        */
  443.       if (GIMP_IS_LAYER (layer->fs.drawable))
  444.         {
  445.           d_layer = GIMP_LAYER (layer->fs.drawable);
  446.           if ((preserve_trans = d_layer->preserve_trans))
  447.         d_layer->preserve_trans = FALSE;
  448.         }
  449.       else
  450.         preserve_trans = FALSE;
  451.  
  452.       /*  We need to set all gimage channels to active to make sure that
  453.        *  nothing strange happens while applying the floating selection.
  454.        *  It wouldn't make sense for the floating selection to be affected
  455.        *  by the active gimage channels.
  456.        */
  457.       for (i = 0; i < MAX_CHANNELS; i++)
  458.         {
  459.           active[i] = gimage->active[i];
  460.           gimage->active[i] = 1;
  461.         }
  462.  
  463.       /*  apply the fs with the undo specified by the value
  464.        *  passed to this function
  465.        */
  466.       gimage_apply_image (gimage, layer->fs.drawable, &fsPR,
  467.                   undo, layer->opacity, layer->mode,
  468.                   NULL,
  469.                   (x1 - offx), (y1 - offy));
  470.  
  471.       /*  restore preserve transparency  */
  472.       if (preserve_trans)
  473.         d_layer->preserve_trans = TRUE;
  474.  
  475.       /*  restore gimage active channels  */
  476.       for (i = 0; i < MAX_CHANNELS; i++)
  477.         gimage->active[i] = active[i];
  478.     }
  479.     }
  480. }
  481.  
  482. BoundSeg *
  483. floating_sel_boundary (Layer *layer,
  484.                int   *num_segs)
  485. {
  486.   PixelRegion bPR;
  487.   int i;
  488.  
  489.   if (layer->fs.boundary_known == FALSE)
  490.     {
  491.       if (layer->fs.segs)
  492.     g_free (layer->fs.segs);
  493.  
  494.       /*  find the segments  */
  495.       pixel_region_init (&bPR, GIMP_DRAWABLE (layer)->tiles,
  496.              0, 0,
  497.              GIMP_DRAWABLE (layer)->width,
  498.              GIMP_DRAWABLE (layer)->height, FALSE);
  499.       layer->fs.segs = find_mask_boundary (&bPR, &layer->fs.num_segs,
  500.                        WithinBounds, 0, 0,
  501.                        GIMP_DRAWABLE (layer)->width,
  502.                        GIMP_DRAWABLE (layer)->height);
  503.  
  504.       /*  offset the segments  */
  505.       for (i = 0; i < layer->fs.num_segs; i++)
  506.     {
  507.       layer->fs.segs[i].x1 += GIMP_DRAWABLE (layer)->offset_x;
  508.       layer->fs.segs[i].y1 += GIMP_DRAWABLE (layer)->offset_y;
  509.       layer->fs.segs[i].x2 += GIMP_DRAWABLE (layer)->offset_x;
  510.       layer->fs.segs[i].y2 += GIMP_DRAWABLE (layer)->offset_y;
  511.     }
  512.  
  513.       layer->fs.boundary_known = TRUE;
  514.     }
  515.  
  516.   *num_segs = layer->fs.num_segs;
  517.   return layer->fs.segs;
  518. }
  519.  
  520. void
  521. floating_sel_invalidate (Layer *layer)
  522. {
  523.   /*  Invalidate the attached-to drawable's preview  */
  524.   gimp_drawable_invalidate_preview (layer->fs.drawable, TRUE);
  525.  
  526.   /*  Invalidate the boundary  */
  527.   layer->fs.boundary_known = FALSE;
  528. }
  529.