400 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			400 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* PIKA - Photo and Image Kooker Application
							 | 
						||
| 
								 | 
							
								 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
							 | 
						||
| 
								 | 
							
								 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Original copyright, applying to most contents (license remains unchanged): 
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * pikaregionselecttool.c
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software: you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								 * it under the terms of the GNU General Public License as published by
							 | 
						||
| 
								 | 
							
								 * the Free Software Foundation; either version 3 of the License, or
							 | 
						||
| 
								 | 
							
								 * (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								 * but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						||
| 
								 | 
							
								 * GNU General Public License for more details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * You should have received a copy of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "config.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <gegl.h>
							 | 
						||
| 
								 | 
							
								#include <gtk/gtk.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "libpikawidgets/pikawidgets.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "tools-types.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "core/pika-utils.h"
							 | 
						||
| 
								 | 
							
								#include "core/pikaboundary.h"
							 | 
						||
| 
								 | 
							
								#include "core/pikachannel.h"
							 | 
						||
| 
								 | 
							
								#include "core/pikachannel-select.h"
							 | 
						||
| 
								 | 
							
								#include "core/pikaimage.h"
							 | 
						||
| 
								 | 
							
								#include "core/pikalayer-floating-selection.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "display/pikadisplay.h"
							 | 
						||
| 
								 | 
							
								#include "display/pikadisplayshell.h"
							 | 
						||
| 
								 | 
							
								#include "display/pikadisplayshell-cursor.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "pikaregionselectoptions.h"
							 | 
						||
| 
								 | 
							
								#include "pikaregionselecttool.h"
							 | 
						||
| 
								 | 
							
								#include "pikatoolcontrol.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "pika-intl.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_finalize       (GObject               *object);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_button_press   (PikaTool              *tool,
							 | 
						||
| 
								 | 
							
								                                                      const PikaCoords      *coords,
							 | 
						||
| 
								 | 
							
								                                                      guint32                time,
							 | 
						||
| 
								 | 
							
								                                                      GdkModifierType        state,
							 | 
						||
| 
								 | 
							
								                                                      PikaButtonPressType    press_type,
							 | 
						||
| 
								 | 
							
								                                                      PikaDisplay           *display);
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_button_release (PikaTool              *tool,
							 | 
						||
| 
								 | 
							
								                                                      const PikaCoords      *coords,
							 | 
						||
| 
								 | 
							
								                                                      guint32                time,
							 | 
						||
| 
								 | 
							
								                                                      GdkModifierType        state,
							 | 
						||
| 
								 | 
							
								                                                      PikaButtonReleaseType  release_type,
							 | 
						||
| 
								 | 
							
								                                                      PikaDisplay           *display);
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_motion         (PikaTool              *tool,
							 | 
						||
| 
								 | 
							
								                                                      const PikaCoords      *coords,
							 | 
						||
| 
								 | 
							
								                                                      guint32                time,
							 | 
						||
| 
								 | 
							
								                                                      GdkModifierType        state,
							 | 
						||
| 
								 | 
							
								                                                      PikaDisplay           *display);
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_cursor_update  (PikaTool              *tool,
							 | 
						||
| 
								 | 
							
								                                                      const PikaCoords      *coords,
							 | 
						||
| 
								 | 
							
								                                                      GdkModifierType        state,
							 | 
						||
| 
								 | 
							
								                                                      PikaDisplay           *display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_draw           (PikaDrawTool          *draw_tool);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void   pika_region_select_tool_get_mask       (PikaRegionSelectTool  *region_sel,
							 | 
						||
| 
								 | 
							
								                                                      PikaDisplay           *display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								G_DEFINE_TYPE (PikaRegionSelectTool, pika_region_select_tool,
							 | 
						||
| 
								 | 
							
								               PIKA_TYPE_SELECTION_TOOL)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define parent_class pika_region_select_tool_parent_class
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_class_init (PikaRegionSelectToolClass *klass)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
							 | 
						||
| 
								 | 
							
								  PikaToolClass     *tool_class      = PIKA_TOOL_CLASS (klass);
							 | 
						||
| 
								 | 
							
								  PikaDrawToolClass *draw_tool_class = PIKA_DRAW_TOOL_CLASS (klass);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  object_class->finalize     = pika_region_select_tool_finalize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  tool_class->button_press   = pika_region_select_tool_button_press;
							 | 
						||
| 
								 | 
							
								  tool_class->button_release = pika_region_select_tool_button_release;
							 | 
						||
| 
								 | 
							
								  tool_class->motion         = pika_region_select_tool_motion;
							 | 
						||
| 
								 | 
							
								  tool_class->cursor_update  = pika_region_select_tool_cursor_update;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  draw_tool_class->draw      = pika_region_select_tool_draw;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_init (PikaRegionSelectTool *region_select)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaTool *tool = PIKA_TOOL (region_select);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_tool_control_set_scroll_lock (tool->control, TRUE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  region_select->x               = 0;
							 | 
						||
| 
								 | 
							
								  region_select->y               = 0;
							 | 
						||
| 
								 | 
							
								  region_select->saved_threshold = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  region_select->region_mask     = NULL;
							 | 
						||
| 
								 | 
							
								  region_select->segs            = NULL;
							 | 
						||
| 
								 | 
							
								  region_select->n_segs          = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_finalize (GObject *object)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectTool *region_sel = PIKA_REGION_SELECT_TOOL (object);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_clear_object (®ion_sel->region_mask);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_clear_pointer (®ion_sel->segs, g_free);
							 | 
						||
| 
								 | 
							
								  region_sel->n_segs = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  G_OBJECT_CLASS (parent_class)->finalize (object);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_button_press (PikaTool            *tool,
							 | 
						||
| 
								 | 
							
								                                      const PikaCoords    *coords,
							 | 
						||
| 
								 | 
							
								                                      guint32              time,
							 | 
						||
| 
								 | 
							
								                                      GdkModifierType      state,
							 | 
						||
| 
								 | 
							
								                                      PikaButtonPressType  press_type,
							 | 
						||
| 
								 | 
							
								                                      PikaDisplay         *display)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectTool    *region_sel = PIKA_REGION_SELECT_TOOL (tool);
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectOptions *options    = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  region_sel->x               = coords->x;
							 | 
						||
| 
								 | 
							
								  region_sel->y               = coords->y;
							 | 
						||
| 
								 | 
							
								  region_sel->saved_threshold = options->threshold;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (pika_selection_tool_start_edit (PIKA_SELECTION_TOOL (region_sel),
							 | 
						||
| 
								 | 
							
								                                      display, coords))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_tool_control_activate (tool->control);
							 | 
						||
| 
								 | 
							
								  tool->display = display;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_tool_push_status (tool, display,
							 | 
						||
| 
								 | 
							
								                         _("Move the mouse to change threshold"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_region_select_tool_get_mask (region_sel, display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_draw_tool_start (PIKA_DRAW_TOOL (tool), display);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_button_release (PikaTool              *tool,
							 | 
						||
| 
								 | 
							
								                                        const PikaCoords      *coords,
							 | 
						||
| 
								 | 
							
								                                        guint32                time,
							 | 
						||
| 
								 | 
							
								                                        GdkModifierType        state,
							 | 
						||
| 
								 | 
							
								                                        PikaButtonReleaseType  release_type,
							 | 
						||
| 
								 | 
							
								                                        PikaDisplay           *display)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectTool    *region_sel  = PIKA_REGION_SELECT_TOOL (tool);
							 | 
						||
| 
								 | 
							
								  PikaSelectionOptions    *sel_options = PIKA_SELECTION_TOOL_GET_OPTIONS (tool);
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectOptions *options     = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
							 | 
						||
| 
								 | 
							
								  PikaImage               *image       = pika_display_get_image (display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_tool_pop_status (tool, display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_draw_tool_stop (PIKA_DRAW_TOOL (tool));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_tool_control_halt (tool->control);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (options->draw_mask)
							 | 
						||
| 
								 | 
							
								    pika_display_shell_set_mask (pika_display_get_shell (display),
							 | 
						||
| 
								 | 
							
								                                 NULL, 0, 0, NULL, FALSE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (release_type != PIKA_BUTTON_RELEASE_CANCEL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (PIKA_SELECTION_TOOL (tool)->function == SELECTION_ANCHOR)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          if (pika_image_get_floating_selection (image))
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              /*  If there is a floating selection, anchor it  */
							 | 
						||
| 
								 | 
							
								              floating_sel_anchor (pika_image_get_floating_selection (image));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              /*  Otherwise, clear the selection mask  */
							 | 
						||
| 
								 | 
							
								              pika_channel_clear (pika_image_get_mask (image), NULL, TRUE);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          pika_image_flush (image);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else if (region_sel->region_mask)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          gint off_x = 0;
							 | 
						||
| 
								 | 
							
								          gint off_y = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (! options->sample_merged)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              GList *drawables = pika_image_get_selected_drawables (image);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              if (g_list_length (drawables) == 1)
							 | 
						||
| 
								 | 
							
								                pika_item_get_offset (drawables->data, &off_x, &off_y);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              g_list_free (drawables);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          pika_channel_select_buffer (pika_image_get_mask (image),
							 | 
						||
| 
								 | 
							
								                                      PIKA_REGION_SELECT_TOOL_GET_CLASS (tool)->undo_desc,
							 | 
						||
| 
								 | 
							
								                                      region_sel->region_mask,
							 | 
						||
| 
								 | 
							
								                                      off_x,
							 | 
						||
| 
								 | 
							
								                                      off_y,
							 | 
						||
| 
								 | 
							
								                                      sel_options->operation,
							 | 
						||
| 
								 | 
							
								                                      sel_options->feather,
							 | 
						||
| 
								 | 
							
								                                      sel_options->feather_radius,
							 | 
						||
| 
								 | 
							
								                                      sel_options->feather_radius);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          pika_image_flush (image);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_clear_object (®ion_sel->region_mask);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_clear_pointer (®ion_sel->segs, g_free);
							 | 
						||
| 
								 | 
							
								  region_sel->n_segs = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /*  Restore the original threshold  */
							 | 
						||
| 
								 | 
							
								  g_object_set (options,
							 | 
						||
| 
								 | 
							
								                "threshold", region_sel->saved_threshold,
							 | 
						||
| 
								 | 
							
								                NULL);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_motion (PikaTool         *tool,
							 | 
						||
| 
								 | 
							
								                                const PikaCoords *coords,
							 | 
						||
| 
								 | 
							
								                                guint32           time,
							 | 
						||
| 
								 | 
							
								                                GdkModifierType   state,
							 | 
						||
| 
								 | 
							
								                                PikaDisplay      *display)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectTool    *region_sel = PIKA_REGION_SELECT_TOOL (tool);
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectOptions *options    = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
							 | 
						||
| 
								 | 
							
								  gint                     diff_x, diff_y;
							 | 
						||
| 
								 | 
							
								  gdouble                  diff;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  static guint32 last_time = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* don't let the events come in too fast, ignore below a delay of 100 ms */
							 | 
						||
| 
								 | 
							
								  if (time - last_time < 100)
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  last_time = time;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  diff_x = coords->x - region_sel->x;
							 | 
						||
| 
								 | 
							
								  diff_y = coords->y - region_sel->y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  diff = ((ABS (diff_x) > ABS (diff_y)) ? diff_x : diff_y) / 2.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_object_set (options,
							 | 
						||
| 
								 | 
							
								                "threshold", CLAMP (region_sel->saved_threshold + diff, 0, 255),
							 | 
						||
| 
								 | 
							
								                NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_region_select_tool_get_mask (region_sel, display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_cursor_update (PikaTool         *tool,
							 | 
						||
| 
								 | 
							
								                                       const PikaCoords *coords,
							 | 
						||
| 
								 | 
							
								                                       GdkModifierType   state,
							 | 
						||
| 
								 | 
							
								                                       PikaDisplay      *display)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectOptions *options  = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
							 | 
						||
| 
								 | 
							
								  PikaCursorModifier       modifier = PIKA_CURSOR_MODIFIER_NONE;
							 | 
						||
| 
								 | 
							
								  PikaImage               *image    = pika_display_get_image (display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (! pika_image_coords_in_active_pickable (image, coords,
							 | 
						||
| 
								 | 
							
								                                              FALSE, options->sample_merged,
							 | 
						||
| 
								 | 
							
								                                              FALSE))
							 | 
						||
| 
								 | 
							
								    modifier = PIKA_CURSOR_MODIFIER_BAD;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_tool_control_set_cursor_modifier (tool->control, modifier);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_draw (PikaDrawTool *draw_tool)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectTool    *region_sel = PIKA_REGION_SELECT_TOOL (draw_tool);
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectOptions *options    = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (draw_tool);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (! options->draw_mask && region_sel->region_mask)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (! region_sel->segs)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          /*  calculate and allocate a new segment array which represents
							 | 
						||
| 
								 | 
							
								           *  the boundary of the contiguous region
							 | 
						||
| 
								 | 
							
								           */
							 | 
						||
| 
								 | 
							
								          region_sel->segs = pika_boundary_find (region_sel->region_mask, NULL,
							 | 
						||
| 
								 | 
							
								                                                 babl_format ("Y float"),
							 | 
						||
| 
								 | 
							
								                                                 PIKA_BOUNDARY_WITHIN_BOUNDS,
							 | 
						||
| 
								 | 
							
								                                                 0, 0,
							 | 
						||
| 
								 | 
							
								                                                 gegl_buffer_get_width  (region_sel->region_mask),
							 | 
						||
| 
								 | 
							
								                                                 gegl_buffer_get_height (region_sel->region_mask),
							 | 
						||
| 
								 | 
							
								                                                 PIKA_BOUNDARY_HALF_WAY,
							 | 
						||
| 
								 | 
							
								                                                 ®ion_sel->n_segs);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (region_sel->segs)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          gint off_x = 0;
							 | 
						||
| 
								 | 
							
								          gint off_y = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (! options->sample_merged)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              PikaImage *image     = pika_display_get_image (draw_tool->display);
							 | 
						||
| 
								 | 
							
								              GList     *drawables = pika_image_get_selected_drawables (image);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              if (g_list_length (drawables) == 1)
							 | 
						||
| 
								 | 
							
								                pika_item_get_offset (drawables->data, &off_x, &off_y);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              g_list_free (drawables);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          pika_draw_tool_add_boundary (draw_tool,
							 | 
						||
| 
								 | 
							
								                                       region_sel->segs,
							 | 
						||
| 
								 | 
							
								                                       region_sel->n_segs,
							 | 
						||
| 
								 | 
							
								                                       NULL,
							 | 
						||
| 
								 | 
							
								                                       off_x, off_y);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								pika_region_select_tool_get_mask (PikaRegionSelectTool *region_sel,
							 | 
						||
| 
								 | 
							
								                                  PikaDisplay          *display)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  PikaRegionSelectOptions *options = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (region_sel);
							 | 
						||
| 
								 | 
							
								  PikaDisplayShell        *shell   = pika_display_get_shell (display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_display_shell_set_override_cursor (shell, (PikaCursorType) GDK_WATCH);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  g_clear_pointer (®ion_sel->segs, g_free);
							 | 
						||
| 
								 | 
							
								  region_sel->n_segs = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (region_sel->region_mask)
							 | 
						||
| 
								 | 
							
								    g_object_unref (region_sel->region_mask);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  region_sel->region_mask =
							 | 
						||
| 
								 | 
							
								    PIKA_REGION_SELECT_TOOL_GET_CLASS (region_sel)->get_mask (region_sel,
							 | 
						||
| 
								 | 
							
								                                                              display);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (options->draw_mask)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (region_sel->region_mask)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          PikaRGB color = { 1.0, 0.0, 1.0, 1.0 };
							 | 
						||
| 
								 | 
							
								          gint    off_x = 0;
							 | 
						||
| 
								 | 
							
								          gint    off_y = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (! options->sample_merged)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              PikaImage *image     = pika_display_get_image (display);
							 | 
						||
| 
								 | 
							
								              GList     *drawables = pika_image_get_selected_drawables (image);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              if (g_list_length (drawables) == 1)
							 | 
						||
| 
								 | 
							
								                pika_item_get_offset (drawables->data, &off_x, &off_y);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              g_list_free (drawables);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          pika_display_shell_set_mask (shell, region_sel->region_mask,
							 | 
						||
| 
								 | 
							
								                                       off_x, off_y, &color, FALSE);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          pika_display_shell_set_mask (shell, NULL, 0, 0, NULL, FALSE);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pika_display_shell_unset_override_cursor (shell);
							 | 
						||
| 
								 | 
							
								}
							 |