home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / free_select.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  9.3 KB  |  381 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 <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <glib.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "draw_core.h"
  30. #include "edit_selection.h"
  31. #include "errors.h"
  32. #include "floating_sel.h"
  33. #include "free_select.h"
  34. #include "gimage_mask.h"
  35. #include "gdisplay.h"
  36. #include "rect_select.h"
  37. #include "selection_options.h"
  38. #include "scan_convert.h"
  39.  
  40. #include "libgimp/gimpmath.h"
  41.  
  42.  
  43. #define DEFAULT_MAX_INC  1024
  44. #define SUPERSAMPLE      3
  45. #define SUPERSAMPLE2     9
  46.  
  47. /*  the free selection structures  */
  48.  
  49. typedef struct _FreeSelect FreeSelect;
  50. struct _FreeSelect
  51. {
  52.   DrawCore  *core;      /*  Core select object                      */
  53.  
  54.   SelectOps  op;        /*  selection operation (ADD, SUB, etc)     */
  55.  
  56.   gint      current_x;  /*  these values are updated on every motion event  */
  57.   gint      current_y;  /*  (enables immediate cursor updating on modifier
  58.              *   key events).  */
  59.  
  60.   gint      num_pts;    /*  Number of points in the polygon         */
  61. };
  62.  
  63.  
  64.  
  65. /*  the free selection tool options  */
  66. static SelectionOptions * free_options = NULL;
  67.  
  68. /*  The global array of XPoints for drawing the polygon...  */
  69. static GdkPoint *global_pts = NULL;
  70. static gint      max_segs = 0;
  71.  
  72.  
  73. /*  functions  */
  74.  
  75. static gint
  76. add_point (gint num_pts,
  77.        gint x,
  78.        gint y)
  79. {
  80.   if (num_pts >= max_segs)
  81.     {
  82.       max_segs += DEFAULT_MAX_INC;
  83.  
  84.       global_pts = (GdkPoint *) g_realloc ((void *) global_pts, sizeof (GdkPoint) * max_segs);
  85.  
  86.       if (!global_pts)
  87.     gimp_fatal_error ("add_point(): Unable to reallocate points array in free_select.");
  88.     }
  89.  
  90.   global_pts[num_pts].x = x;
  91.   global_pts[num_pts].y = y;
  92.  
  93.   return 1;
  94. }
  95.  
  96.  
  97. static Channel *
  98. scan_convert (GimpImage        *gimage,
  99.           gint              num_pts,
  100.           ScanConvertPoint *pts,
  101.           gint              width,
  102.           gint              height,
  103.           gboolean          antialias)
  104. {
  105.   Channel       *mask;
  106.   ScanConverter *sc;
  107.  
  108.   sc = scan_converter_new (width, height, antialias ? SUPERSAMPLE : 1);
  109.   scan_converter_add_points (sc, num_pts, pts);
  110.  
  111.   mask = scan_converter_to_channel (sc, gimage);
  112.   scan_converter_free (sc);
  113.  
  114.   return mask;
  115. }
  116.  
  117.  
  118. /*************************************/
  119. /*  Polygonal selection apparatus    */
  120.  
  121. void
  122. free_select (GImage           *gimage,
  123.          gint              num_pts,
  124.          ScanConvertPoint *pts,
  125.          SelectOps         op,
  126.          gboolean          antialias,
  127.          gboolean          feather,
  128.          gdouble           feather_radius)
  129. {
  130.   Channel *mask;
  131.  
  132.   /*  if applicable, replace the current selection  */
  133.   /*  or insure that a floating selection is anchored down...  */
  134.   if (op == SELECTION_REPLACE)
  135.     gimage_mask_clear (gimage);
  136.   else
  137.     gimage_mask_undo (gimage);
  138.  
  139.   mask = scan_convert (gimage, num_pts, pts,
  140.                gimage->width, gimage->height, antialias);
  141.  
  142.   if (mask)
  143.     {
  144.       if (feather)
  145.     channel_feather (mask, gimage_get_mask (gimage),
  146.              feather_radius,
  147.              feather_radius,
  148.              op, 0, 0);
  149.       else
  150.     channel_combine_mask (gimage_get_mask (gimage),
  151.                   mask, op, 0, 0);
  152.       channel_delete (mask);
  153.     }
  154. }
  155.  
  156. void
  157. free_select_button_press (Tool           *tool,
  158.               GdkEventButton *bevent,
  159.               gpointer        gdisp_ptr)
  160. {
  161.   GDisplay   *gdisp;
  162.   FreeSelect *free_sel;
  163.  
  164.   gdisp = (GDisplay *) gdisp_ptr;
  165.   free_sel = (FreeSelect *) tool->private;
  166.  
  167.   gdk_pointer_grab (gdisp->canvas->window, FALSE,
  168.             GDK_POINTER_MOTION_HINT_MASK |
  169.             GDK_BUTTON1_MOTION_MASK |
  170.             GDK_BUTTON_RELEASE_MASK,
  171.             NULL, NULL, bevent->time);
  172.  
  173.   tool->state = ACTIVE;
  174.   tool->gdisp_ptr = gdisp_ptr;
  175.  
  176.   switch (free_sel->op)
  177.     {
  178.     case SELECTION_MOVE_MASK:
  179.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TRANSLATE);
  180.       return;
  181.     case SELECTION_MOVE:
  182.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
  183.       return;
  184.     default:
  185.       break;
  186.     }
  187.  
  188.   add_point (0, bevent->x, bevent->y);
  189.   free_sel->num_pts = 1;
  190.  
  191.   draw_core_start (free_sel->core,
  192.            gdisp->canvas->window,
  193.            tool);
  194. }
  195.  
  196. void
  197. free_select_button_release (Tool           *tool,
  198.                 GdkEventButton *bevent,
  199.                 gpointer        gdisp_ptr)
  200. {
  201.   FreeSelect       *free_sel;
  202.   ScanConvertPoint *pts;
  203.   GDisplay         *gdisp;
  204.   gint              i;
  205.  
  206.   gdisp = (GDisplay *) gdisp_ptr;
  207.   free_sel = (FreeSelect *) tool->private;
  208.  
  209.   gdk_pointer_ungrab (bevent->time);
  210.   gdk_flush ();
  211.  
  212.   draw_core_stop (free_sel->core, tool);
  213.  
  214.   tool->state = INACTIVE;
  215.  
  216.   /*  First take care of the case where the user "cancels" the action  */
  217.   if (! (bevent->state & GDK_BUTTON3_MASK))
  218.     {
  219.       if (free_sel->op == SELECTION_ANCHOR)
  220.     {
  221.       /*  If there is a floating selection, anchor it  */
  222.       if (gimage_floating_sel (gdisp->gimage))
  223.         floating_sel_anchor (gimage_floating_sel (gdisp->gimage));
  224.       /*  Otherwise, clear the selection mask  */
  225.       else
  226.         gimage_mask_clear (gdisp->gimage);
  227.       
  228.       gdisplays_flush ();
  229.       return;
  230.     }
  231.  
  232.       pts = g_new (ScanConvertPoint, free_sel->num_pts);
  233.  
  234.       for (i = 0; i < free_sel->num_pts; i++)
  235.     {
  236.       gdisplay_untransform_coords_f (gdisp, global_pts[i].x, global_pts[i].y,
  237.                      &pts[i].x, &pts[i].y, FALSE);
  238.     }
  239.  
  240.       free_select (gdisp->gimage, free_sel->num_pts, pts, free_sel->op,
  241.            free_options->antialias, free_options->feather,
  242.            free_options->feather_radius);
  243.  
  244.       g_free (pts);
  245.  
  246.       gdisplays_flush ();
  247.     }
  248. }
  249.  
  250. void
  251. free_select_motion (Tool           *tool,
  252.             GdkEventMotion *mevent,
  253.             gpointer        gdisp_ptr)
  254. {
  255.   FreeSelect *free_sel;
  256.   GDisplay   *gdisp;
  257.  
  258.   gdisp = (GDisplay *) gdisp_ptr;
  259.   free_sel = (FreeSelect *) tool->private;
  260.  
  261.   /*  needed for immediate cursor update on modifier event  */
  262.   free_sel->current_x = mevent->x;
  263.   free_sel->current_y = mevent->y;
  264.  
  265.   if (tool->state != ACTIVE)
  266.     return;
  267.  
  268.   if (free_sel->op == SELECTION_ANCHOR)
  269.     {
  270.       free_sel->op = SELECTION_REPLACE;
  271.  
  272.       rect_select_cursor_update (tool, mevent, gdisp_ptr);
  273.     }
  274.  
  275.   if (add_point (free_sel->num_pts, mevent->x, mevent->y))
  276.     {
  277.       gdk_draw_line (free_sel->core->win, free_sel->core->gc,
  278.              global_pts[free_sel->num_pts - 1].x,
  279.              global_pts[free_sel->num_pts - 1].y,
  280.              global_pts[free_sel->num_pts].x,
  281.              global_pts[free_sel->num_pts].y);
  282.  
  283.       free_sel->num_pts ++;
  284.     }
  285. }
  286.  
  287. static void
  288. free_select_control (Tool       *tool,
  289.              ToolAction  action,
  290.              gpointer    gdisp_ptr)
  291. {
  292.   FreeSelect *free_sel;
  293.  
  294.   free_sel = (FreeSelect *) tool->private;
  295.  
  296.   switch (action)
  297.     {
  298.     case PAUSE:
  299.       draw_core_pause (free_sel->core, tool);
  300.       break;
  301.  
  302.     case RESUME:
  303.       draw_core_resume (free_sel->core, tool);
  304.       break;
  305.  
  306.     case HALT:
  307.       draw_core_stop (free_sel->core, tool);
  308.       break;
  309.  
  310.     default:
  311.       break;
  312.     }
  313. }
  314.  
  315. void
  316. free_select_draw (Tool *tool)
  317. {
  318.   FreeSelect *free_sel;
  319.   gint        i;
  320.  
  321.   free_sel = (FreeSelect *) tool->private;
  322.  
  323.   for (i = 1; i < free_sel->num_pts; i++)
  324.     gdk_draw_line (free_sel->core->win, free_sel->core->gc,
  325.            global_pts[i - 1].x, global_pts[i - 1].y,
  326.            global_pts[i].x, global_pts[i].y);
  327. }
  328.  
  329. static void
  330. free_select_options_reset (void)
  331. {
  332.   selection_options_reset (free_options);
  333. }
  334.  
  335. Tool *
  336. tools_new_free_select (void)
  337. {
  338.   Tool       *tool;
  339.   FreeSelect *private;
  340.  
  341.   /*  The tool options  */
  342.   if (!free_options)
  343.     {
  344.       free_options =
  345.     selection_options_new (FREE_SELECT, free_select_options_reset);
  346.       tools_register (FREE_SELECT, (ToolOptions *) free_options);
  347.     }
  348.  
  349.   tool = tools_new_tool (FREE_SELECT);
  350.   private = g_new0 (FreeSelect, 1);
  351.  
  352.   private->core    = draw_core_new (free_select_draw);
  353.   private->num_pts = 0;
  354.   private->op      = SELECTION_REPLACE;
  355.  
  356.   tool->scroll_lock = TRUE;   /*  Do not allow scrolling  */
  357.  
  358.   tool->private = (void *) private;
  359.  
  360.   tool->button_press_func   = free_select_button_press;
  361.   tool->button_release_func = free_select_button_release;
  362.   tool->motion_func         = free_select_motion;
  363.   tool->modifier_key_func   = rect_select_modifier_update;
  364.   tool->cursor_update_func  = rect_select_cursor_update;
  365.   tool->oper_update_func    = rect_select_oper_update;
  366.   tool->control_func        = free_select_control;
  367.  
  368.   return tool;
  369. }
  370.  
  371. void
  372. tools_free_free_select (Tool *tool)
  373. {
  374.   FreeSelect *free_sel;
  375.  
  376.   free_sel = (FreeSelect *) tool->private;
  377.  
  378.   draw_core_free (free_sel->core);
  379.   g_free (free_sel);
  380. }
  381.