From fafae590e3bb435f419d56166b93256d13848770 Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Mon, 22 Jan 2001 01:46:28 +0000 Subject: [PATCH] configure.in app/Makefile.am moved all tool sources to app/tools 2001-01-22 Sven Neumann * configure.in * app/Makefile.am * app/tools/Makefile.am: moved all tool sources to app/tools * app/app_procs.c * app/brush_select.c * app/commands.c * app/context_manager.c * app/convert.c * app/cursorutil.c * app/devices.c * app/disp_callbacks.c * app/edit_selection.c * app/gdisplay.c * app/gimage.c * app/gimage_mask.c * app/gimpbrush.c * app/gimpbrushgenerated.c * app/gimpbrushpipe.c * app/gimpdnd.c * app/gimprc.c * app/global_edit.c * app/info_window.c * app/interface.c * app/menus.c * app/path.c * app/paths_dialog.c * app/paths_dialogP.h * app/scale.c * app/scroll.c * app/undo.c * app/pdb/color_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * po/POTFILES.in * tools/kernelgen.c * tools/pdbgen/Makefile.am * tools/pdbgen/enums.pl * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/tools.pdb: changed accordingly --- ChangeLog | 44 + TODO.xml | 4 +- app/Makefile.am | 93 +- app/actions/help-commands.c | 3 +- app/airbrush.c | 440 --- app/airbrush.h | 35 - app/airbrush_blob.c | 1841 ----------- app/airbrush_blob.h | 153 - app/app_procs.c | 9 +- app/bezier_select.c | 3676 ---------------------- app/bezier_select.h | 29 - app/bezier_selectP.h | 116 - app/blend.c | 1695 ---------- app/blend.h | 78 - app/blob.c | 774 ----- app/blob.h | 82 - app/brightness_contrast.c | 499 --- app/brightness_contrast.h | 31 - app/brush_select.c | 3 +- app/bucket_fill.c | 663 ---- app/bucket_fill.h | 54 - app/by_color_select.c | 1262 -------- app/by_color_select.h | 40 - app/clone.c | 773 ----- app/clone.h | 44 - app/color_balance.c | 749 ----- app/color_balance.h | 68 - app/color_picker.c | 824 ----- app/color_picker.h | 39 - app/commands.c | 3 +- app/context_manager.c | 5 +- app/convert.c | 15 +- app/convolve.c | 696 ---- app/convolve.h | 44 - app/core/gimp-edit.c | 3 +- app/core/gimpbrush-load.c | 4 +- app/core/gimpbrush.c | 4 +- app/core/gimpbrushgenerated-load.c | 4 +- app/core/gimpbrushgenerated-save.c | 4 +- app/core/gimpbrushgenerated.c | 4 +- app/core/gimpbrushpipe-load.c | 4 +- app/core/gimpbrushpipe.c | 4 +- app/core/gimpedit.c | 3 +- app/core/gimpimage-convert.c | 15 +- app/core/gimpimage-mask.c | 6 +- app/core/gimpimage-undo-push.c | 9 +- app/core/gimpprojection.c | 4 +- app/crop.c | 1598 ---------- app/crop.h | 43 - app/cursorutil.c | 3 +- app/curves.c | 1821 ----------- app/curves.h | 76 - app/devices.c | 3 +- app/dialogs/info-window.c | 3 +- app/disp_callbacks.c | 7 +- app/display/gimpdisplay-callbacks.c | 7 +- app/display/gimpdisplay-scale.c | 3 +- app/display/gimpdisplay-scroll.c | 3 +- app/display/gimpdisplay.c | 4 +- app/display/gimpdisplayshell-callbacks.c | 7 +- app/display/gimpdisplayshell-draw.c | 3 +- app/display/gimpdisplayshell-scale.c | 3 +- app/display/gimpdisplayshell-scroll.c | 3 +- app/display/gimpdisplayshell.c | 3 +- app/dodgeburn.c | 667 ---- app/dodgeburn.h | 51 - app/edit_selection.c | 3 +- app/ellipse_select.c | 165 - app/ellipse_select.h | 38 - app/eraser.c | 364 --- app/eraser.h | 37 - app/flip_tool.c | 324 -- app/flip_tool.h | 33 - app/free_select.c | 391 --- app/free_select.h | 38 - app/fuzzy_select.c | 688 ---- app/fuzzy_select.h | 43 - app/gdisplay.c | 4 +- app/gimage.c | 3 +- app/gimage_mask.c | 6 +- app/gimpbrush.c | 4 +- app/gimpbrushgenerated.c | 4 +- app/gimpbrushpipe.c | 4 +- app/gimpdnd.c | 3 +- app/gimpimage-convert.c | 15 +- app/gimprc.c | 3 +- app/global_edit.c | 3 +- app/gui/brush-select.c | 3 +- app/gui/commands.c | 3 +- app/gui/device-status-dialog.c | 3 +- app/gui/help-commands.c | 3 +- app/gui/info-window.c | 3 +- app/gui/input-dialog.c | 3 +- app/gui/menus.c | 5 +- app/gui/paths-dialog.c | 5 +- app/histogram_tool.c | 470 --- app/histogram_tool.h | 64 - app/hue_saturation.c | 854 ----- app/hue_saturation.h | 71 - app/info_window.c | 3 +- app/ink.c | 1618 ---------- app/ink.h | 31 - app/interface.c | 3 +- app/iscissors.c | 1975 ------------ app/iscissors.h | 27 - app/levels.c | 1610 ---------- app/levels.h | 31 - app/magnify.c | 467 --- app/magnify.h | 29 - app/measure.c | 838 ----- app/measure.h | 27 - app/menus.c | 5 +- app/menus/menus.c | 5 +- app/move.c | 553 ---- app/move.h | 32 - app/paint_core.c | 2151 ------------- app/paint_core.h | 194 -- app/paint_core_kernels.h | 49 - app/paint_options.h | 108 - app/paintbrush.c | 775 ----- app/paintbrush.h | 37 - app/path.c | 3 +- app/path_tool.c | 1900 ----------- app/path_tool.h | 33 - app/path_toolP.h | 134 - app/paths_dialog.c | 5 +- app/paths_dialogP.h | 3 +- app/pdb/color_cmds.c | 10 +- app/pdb/text_tool_cmds.c | 2 +- app/pdb/tools_cmds.c | 46 +- app/pencil.c | 267 -- app/pencil.h | 31 - app/perspective_tool.c | 325 -- app/perspective_tool.h | 36 - app/posterize.c | 402 --- app/posterize.h | 30 - app/rect_select.c | 741 ----- app/rect_select.h | 61 - app/rect_selectP.h | 47 - app/rotate_tool.c | 417 --- app/rotate_tool.h | 35 - app/scale.c | 3 +- app/scale_tool.c | 527 ---- app/scale_tool.h | 35 - app/scroll.c | 3 +- app/shear_tool.c | 373 --- app/shear_tool.h | 34 - app/smudge.c | 511 --- app/smudge.h | 49 - app/text_tool.c | 1064 ------- app/text_tool.h | 52 - app/threshold.c | 579 ---- app/threshold.h | 56 - app/tool_options.c | 971 ------ app/tool_options.h | 47 - app/tools.c | 1762 ----------- app/tools.h | 159 - app/tools/.cvsignore | 6 + app/tools/Makefile.am | 113 + app/tools/edit_selection.c | 3 +- app/tools/gimpeditselectiontool.c | 3 +- app/transform_core.c | 1723 ---------- app/transform_core.h | 157 - app/transform_tool.c | 458 --- app/transform_tool.h | 39 - app/undo.c | 9 +- app/widgets/gimpcursor.c | 3 +- app/widgets/gimpdeviceinfo.c | 3 +- app/widgets/gimpdevices.c | 3 +- app/widgets/gimpdnd.c | 3 +- app/widgets/gimpitemfactory.c | 5 +- app/xinput_airbrush.c | 3271 ------------------- app/xinput_airbrush.h | 30 - configure.in | 1 + po/POTFILES.in | 76 +- tools/kernelgen.c | 2 +- tools/pdbgen/Makefile.am | 40 +- tools/pdbgen/enums.pl | 204 +- tools/pdbgen/pdb/color.pdb | 12 +- tools/pdbgen/pdb/misc_tools.pdb | 63 +- tools/pdbgen/pdb/paint_tools.pdb | 63 +- tools/pdbgen/pdb/text_tool.pdb | 2 +- tools/pdbgen/pdb/tools.pdb | 63 +- tools/pdbgen/pdb/transform_tools.pdb | 63 +- 184 files changed, 683 insertions(+), 49976 deletions(-) delete mode 100644 app/airbrush.c delete mode 100644 app/airbrush.h delete mode 100644 app/airbrush_blob.c delete mode 100644 app/airbrush_blob.h delete mode 100644 app/bezier_select.c delete mode 100644 app/bezier_select.h delete mode 100644 app/bezier_selectP.h delete mode 100644 app/blend.c delete mode 100644 app/blend.h delete mode 100644 app/blob.c delete mode 100644 app/blob.h delete mode 100644 app/brightness_contrast.c delete mode 100644 app/brightness_contrast.h delete mode 100644 app/bucket_fill.c delete mode 100644 app/bucket_fill.h delete mode 100644 app/by_color_select.c delete mode 100644 app/by_color_select.h delete mode 100644 app/clone.c delete mode 100644 app/clone.h delete mode 100644 app/color_balance.c delete mode 100644 app/color_balance.h delete mode 100644 app/color_picker.c delete mode 100644 app/color_picker.h delete mode 100644 app/convolve.c delete mode 100644 app/convolve.h delete mode 100644 app/crop.c delete mode 100644 app/crop.h delete mode 100644 app/curves.c delete mode 100644 app/curves.h delete mode 100644 app/dodgeburn.c delete mode 100644 app/dodgeburn.h delete mode 100644 app/ellipse_select.c delete mode 100644 app/ellipse_select.h delete mode 100644 app/eraser.c delete mode 100644 app/eraser.h delete mode 100644 app/flip_tool.c delete mode 100644 app/flip_tool.h delete mode 100644 app/free_select.c delete mode 100644 app/free_select.h delete mode 100644 app/fuzzy_select.c delete mode 100644 app/fuzzy_select.h delete mode 100644 app/histogram_tool.c delete mode 100644 app/histogram_tool.h delete mode 100644 app/hue_saturation.c delete mode 100644 app/hue_saturation.h delete mode 100644 app/ink.c delete mode 100644 app/ink.h delete mode 100644 app/iscissors.c delete mode 100644 app/iscissors.h delete mode 100644 app/levels.c delete mode 100644 app/levels.h delete mode 100644 app/magnify.c delete mode 100644 app/magnify.h delete mode 100644 app/measure.c delete mode 100644 app/measure.h delete mode 100644 app/move.c delete mode 100644 app/move.h delete mode 100644 app/paint_core.c delete mode 100644 app/paint_core.h delete mode 100644 app/paint_core_kernels.h delete mode 100644 app/paint_options.h delete mode 100644 app/paintbrush.c delete mode 100644 app/paintbrush.h delete mode 100644 app/path_tool.c delete mode 100644 app/path_tool.h delete mode 100644 app/path_toolP.h delete mode 100644 app/pencil.c delete mode 100644 app/pencil.h delete mode 100644 app/perspective_tool.c delete mode 100644 app/perspective_tool.h delete mode 100644 app/posterize.c delete mode 100644 app/posterize.h delete mode 100644 app/rect_select.c delete mode 100644 app/rect_select.h delete mode 100644 app/rect_selectP.h delete mode 100644 app/rotate_tool.c delete mode 100644 app/rotate_tool.h delete mode 100644 app/scale_tool.c delete mode 100644 app/scale_tool.h delete mode 100644 app/shear_tool.c delete mode 100644 app/shear_tool.h delete mode 100644 app/smudge.c delete mode 100644 app/smudge.h delete mode 100644 app/text_tool.c delete mode 100644 app/text_tool.h delete mode 100644 app/threshold.c delete mode 100644 app/threshold.h delete mode 100644 app/tool_options.c delete mode 100644 app/tool_options.h delete mode 100644 app/tools.c delete mode 100644 app/tools.h create mode 100644 app/tools/.cvsignore create mode 100644 app/tools/Makefile.am delete mode 100644 app/transform_core.c delete mode 100644 app/transform_core.h delete mode 100644 app/transform_tool.c delete mode 100644 app/transform_tool.h delete mode 100644 app/xinput_airbrush.c delete mode 100644 app/xinput_airbrush.h diff --git a/ChangeLog b/ChangeLog index fdc462f43c..0bc457161f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2001-01-22 Sven Neumann + + * configure.in + * app/Makefile.am + * app/tools/Makefile.am: moved all tool sources to app/tools + + * app/app_procs.c + * app/brush_select.c + * app/commands.c + * app/context_manager.c + * app/convert.c + * app/cursorutil.c + * app/devices.c + * app/disp_callbacks.c + * app/edit_selection.c + * app/gdisplay.c + * app/gimage.c + * app/gimage_mask.c + * app/gimpbrush.c + * app/gimpbrushgenerated.c + * app/gimpbrushpipe.c + * app/gimpdnd.c + * app/gimprc.c + * app/global_edit.c + * app/info_window.c + * app/interface.c + * app/menus.c + * app/path.c + * app/paths_dialog.c + * app/paths_dialogP.h + * app/scale.c + * app/scroll.c + * app/undo.c + * app/pdb/color_cmds.c + * app/pdb/text_tool_cmds.c + * app/pdb/tools_cmds.c + * po/POTFILES.in + * tools/kernelgen.c + * tools/pdbgen/Makefile.am + * tools/pdbgen/enums.pl + * tools/pdbgen/pdb/color.pdb + * tools/pdbgen/pdb/text_tool.pdb + * tools/pdbgen/pdb/tools.pdb: changed accordingly + 2001-01-22 Daniel Egger * libgimp/gimpcolor.c: #include "gimppalette_pdb.h" diff --git a/TODO.xml b/TODO.xml index 394ac6b53a..38f44939cb 100644 --- a/TODO.xml +++ b/TODO.xml @@ -49,7 +49,7 @@ - + Code reorganization

@@ -63,7 +63,7 @@ - + Unify color data types

diff --git a/app/Makefile.am b/app/Makefile.am index 21386862d5..bbd4eb6313 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = pdb +SUBDIRS = pdb tools scriptdata = @@ -15,8 +15,6 @@ bin_PROGRAMS = gimp gimp_SOURCES = \ about_dialog.c \ about_dialog.h \ - airbrush.c \ - airbrush.h \ app_procs.c \ app_procs.h \ appenums.h \ @@ -27,17 +25,8 @@ gimp_SOURCES = \ authors.h \ batch.c \ batch.h \ - bezier_select.c \ - bezier_select.h \ - bezier_selectP.h \ - blend.c \ - blend.h \ - blob.c \ - blob.h \ boundary.c \ boundary.h \ - brightness_contrast.c \ - brightness_contrast.h \ brush_edit.c \ brush_edit.h \ brush_header.h \ @@ -45,28 +34,18 @@ gimp_SOURCES = \ brush_scale.h \ brush_select.c \ brush_select.h \ - bucket_fill.c \ - bucket_fill.h \ - by_color_select.c \ - by_color_select.h \ channel.c \ channel.h \ channels_dialog.c \ channels_dialog.h \ channel_ops.c \ channel_ops.h \ - clone.c \ - clone.h \ color_area.c \ color_area.h \ - color_balance.c \ - color_balance.h \ color_notebook.c \ color_notebook.h \ color_panel.c \ color_panel.h \ - color_picker.c \ - color_picker.h \ color_select.c \ color_select.h \ color_transfer.c \ @@ -81,14 +60,8 @@ gimp_SOURCES = \ context_manager.h \ convert.c \ convert.h \ - convolve.c \ - convolve.h \ - crop.c \ - crop.h \ cursorutil.c \ cursorutil.h \ - curves.c \ - curves.h \ datafiles.c \ datafiles.h \ desaturate.c \ @@ -102,8 +75,6 @@ gimp_SOURCES = \ disp_callbacks.h \ docindex.c \ docindex.h \ - dodgeburn.c \ - dodgeburn.h \ draw_core.c \ draw_core.h \ drawable.c \ @@ -111,10 +82,6 @@ gimp_SOURCES = \ drawable_pvt.h \ edit_selection.c \ edit_selection.h \ - ellipse_select.c \ - ellipse_select.h \ - eraser.c \ - eraser.h \ errorconsole.c \ errorconsole.h \ errors.c \ @@ -124,17 +91,11 @@ gimp_SOURCES = \ fileops.c \ fileops.h \ fileopsP.h \ - flip_tool.c \ - flip_tool.h \ floating_sel.c \ floating_sel.h \ file_new_dialog.c \ file_new_dialog.h \ - free_select.c \ - free_select.h \ fsdither.h \ - fuzzy_select.c \ - fuzzy_select.h \ gdisplay.c \ gdisplay.h \ gdisplay_ops.c \ @@ -208,10 +169,6 @@ gimp_SOURCES = \ gximage.h \ histogramwidget.c \ histogramwidget.h \ - histogram_tool.c \ - histogram_tool.h \ - hue_saturation.c \ - hue_saturation.h \ image_map.c \ image_map.h \ image_new.c \ @@ -224,14 +181,10 @@ gimp_SOURCES = \ info_dialog.h \ info_window.c \ info_window.h \ - ink.c \ - ink.h \ interface.c \ interface.h \ invert.c \ invert.h \ - iscissors.c \ - iscissors.h \ layer.c \ layer.h \ layer_select.c \ @@ -242,22 +195,14 @@ gimp_SOURCES = \ lc_dialog.c \ lc_dialog.h \ lc_dialogP.h \ - levels.c \ - levels.h \ lut_funcs.c \ lut_funcs.h \ - magnify.c \ - magnify.h \ main.c \ marching_ants.h \ - measure.c \ - measure.h \ menus.c \ menus.h \ module_db.c \ module_db.h \ - move.c \ - move.h \ nav_window.c \ nav_window.h \ ops_buttons.c \ @@ -269,14 +214,8 @@ gimp_SOURCES = \ palette_select.c \ palette_select.h \ paletteP.h \ - paint_core.c \ - paint_core.h \ - paint_core_kernels.h \ paint_funcs.c \ paint_funcs.h \ - paint_options.h \ - paintbrush.c \ - paintbrush.h \ parasitelist.c \ parasitelist.h \ path.c \ @@ -291,10 +230,6 @@ gimp_SOURCES = \ pattern_select.h \ patterns.c \ patterns.h \ - pencil.c \ - pencil.h \ - perspective_tool.c \ - perspective_tool.h \ pixel_processor.c \ pixel_processor.h \ pixel_region.c \ @@ -303,25 +238,16 @@ gimp_SOURCES = \ pixmaps2.h \ plug_in.c \ plug_in.h \ - posterize.c \ - posterize.h \ preferences_dialog.c \ preferences_dialog.h \ qmask.c \ qmask.h \ - rect_select.c \ - rect_select.h \ - rect_selectP.h \ resolution_calibrate.c \ resolution_calibrate.h \ resize.c \ resize.h \ - rotate_tool.c \ - rotate_tool.h \ scale.c \ scale.h \ - scale_tool.c \ - scale_tool.h \ scan_convert.c \ scan_convert.h \ scroll.c \ @@ -331,16 +257,8 @@ gimp_SOURCES = \ selection_options.h \ session.h \ session.c \ - shear_tool.c \ - shear_tool.h \ - smudge.c \ - smudge.h \ temp_buf.c \ temp_buf.h \ - text_tool.c \ - text_tool.h \ - threshold.c \ - threshold.h \ tile.c \ tile.h \ tile_pvt.h \ @@ -353,14 +271,6 @@ gimp_SOURCES = \ tile_swap.h \ tips_dialog.c \ tips_dialog.h \ - tool_options.c \ - tool_options.h \ - tools.c \ - tools.h \ - transform_core.c \ - transform_core.h \ - transform_tool.c \ - transform_tool.h \ undo.c \ undo.h \ undo_history.c \ @@ -400,6 +310,7 @@ INCLUDES = \ gimp_LDADD = \ pdb/libapppdb.la \ + tools/libapptools.la \ $(top_builddir)/libgimp/libgimpi.a \ $(GTK_LIBS) \ $(GIMP_THREAD_LIBS) \ diff --git a/app/actions/help-commands.c b/app/actions/help-commands.c index 2b9a4f109e..9763a89629 100644 --- a/app/actions/help-commands.c +++ b/app/actions/help-commands.c @@ -68,13 +68,14 @@ #include "scale.h" #include "selection.h" #include "tips_dialog.h" -#include "tools.h" #include "undo.h" #ifdef DISPLAY_FILTERS #include "gdisplay_color_ui.h" #endif /* DISPLAY_FILTERS */ +#include "tools/tools.h" + #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/airbrush.c b/app/airbrush.c deleted file mode 100644 index 47b307737c..0000000000 --- a/app/airbrush.c +++ /dev/null @@ -1,440 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "airbrush.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gradient.h" -#include "gimpimage.h" -#include "gimpbrush.h" -#include "gimpcontext.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" - -#include "libgimp/gimpintl.h" - - -/* The maximum amount of pressure that can be exerted */ -#define MAX_PRESSURE 0.075 - -/* Default pressure setting */ -#define AIRBRUSH_PRESSURE_DEFAULT 10.0 -#define AIRBRUSH_INCREMENTAL_DEFAULT FALSE - -#define OFF 0 -#define ON 1 - -/* the airbrush structures */ - -typedef struct _AirbrushTimeout AirbrushTimeout; - -struct _AirbrushTimeout -{ - PaintCore *paint_core; - GimpDrawable *drawable; -}; - -typedef struct _AirbrushOptions AirbrushOptions; - -struct _AirbrushOptions -{ - PaintOptions paint_options; - - gdouble rate; - gdouble rate_d; - GtkObject *rate_w; - - gdouble pressure; - gdouble pressure_d; - GtkObject *pressure_w; -}; - - -/* local function prototypes */ - -static gpointer airbrush_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); -static gpointer airbrush_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); - - -/* the airbrush tool options */ -static AirbrushOptions *airbrush_options = NULL; - -/* local variables */ -static gint timer; /* timer for successive paint applications */ -static gint timer_state = OFF; /* state of airbrush tool */ -static AirbrushTimeout airbrush_timeout; - -static gdouble non_gui_pressure; -static gboolean non_gui_incremental; - -/* forward function declarations */ -static void airbrush_motion (PaintCore *, GimpDrawable *, - PaintPressureOptions *, - gdouble, PaintApplicationMode); -static gint airbrush_time_out (gpointer); - - -/* functions */ - -static void -airbrush_options_reset (void) -{ - AirbrushOptions *options = airbrush_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w), - options->rate_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->pressure_w), - options->pressure_d); -} - -static AirbrushOptions * -airbrush_options_new (void) -{ - AirbrushOptions *options; - - GtkWidget *vbox; - GtkWidget *table; - GtkWidget *scale; - - /* the new airbrush tool options structure */ - options = g_new (AirbrushOptions, 1); - paint_options_init ((PaintOptions *) options, - AIRBRUSH, - airbrush_options_reset); - options->rate = options->rate_d = 80.0; - options->pressure = options->pressure_d = AIRBRUSH_PRESSURE_DEFAULT; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* the rate scale */ - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 1); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - options->rate_w = - gtk_adjustment_new (options->rate_d, 0.0, 150.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w)); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->rate); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, - _("Rate:"), 1.0, 1.0, - scale, 1, FALSE); - - /* the pressure scale */ - options->pressure_w = - gtk_adjustment_new (options->pressure_d, 0.0, 100.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->pressure_w)); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->pressure_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->pressure); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Pressure:"), 1.0, 1.0, - scale, 1, FALSE); - - gtk_widget_show (table); - - return options; -} - -Tool * -tools_new_airbrush (void) -{ - Tool * tool; - PaintCore * private; - - /* The tool options */ - if (! airbrush_options) - { - airbrush_options = airbrush_options_new (); - tools_register (AIRBRUSH, (ToolOptions *) airbrush_options); - } - - tool = paint_core_new (AIRBRUSH); - - private = (PaintCore *) tool->private; - private->paint_func = airbrush_paint_func; - private->pick_colors = TRUE; - private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - return tool; -} - -static gpointer -airbrush_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - GimpBrush *brush; - gdouble rate; - - if (!drawable) - return NULL; - - brush = gimp_context_get_brush (NULL); - switch (state) - { - case INIT_PAINT : - /* timer_state = OFF; */ - if (timer_state == ON) - { - g_warning ("killing stray timer, please report to lewing@gimp.org"); - gtk_timeout_remove (timer); - } - timer_state = OFF; - break; - - case MOTION_PAINT : - if (timer_state == ON) - gtk_timeout_remove (timer); - timer_state = OFF; - - airbrush_motion (paint_core, drawable, - airbrush_options->paint_options.pressure_options, - airbrush_options->pressure, - airbrush_options->paint_options.incremental ? - INCREMENTAL : CONSTANT); - - if (airbrush_options->rate != 0.0) - { - airbrush_timeout.paint_core = paint_core; - airbrush_timeout.drawable = drawable; - rate = airbrush_options->paint_options.pressure_options->rate ? - (10000 / (airbrush_options->rate * 2.0 * paint_core->curpressure)) : - (10000 / airbrush_options->rate); - timer = gtk_timeout_add (rate, airbrush_time_out, NULL); - timer_state = ON; - } - break; - - case FINISH_PAINT : - if (timer_state == ON) - gtk_timeout_remove (timer); - timer_state = OFF; - break; - - default : - break; - } - - return NULL; -} - - -void -tools_free_airbrush (Tool *tool) -{ - if (timer_state == ON) - gtk_timeout_remove (timer); - timer_state = OFF; - - paint_core_free (tool); -} - - -static gint -airbrush_time_out (gpointer client_data) -{ - /* service the timer */ - airbrush_motion (airbrush_timeout.paint_core, - airbrush_timeout.drawable, - airbrush_options->paint_options.pressure_options, - airbrush_options->pressure, - airbrush_options->paint_options.incremental ? - INCREMENTAL : CONSTANT); - gdisplays_flush (); - - /* restart the timer */ - if (airbrush_options->rate != 0.0) - { - if (airbrush_options->paint_options.pressure_options->rate) - { - /* set a new timer */ - timer = gtk_timeout_add ((10000 / (airbrush_options->rate * 2.0 * airbrush_timeout.paint_core->curpressure)), - airbrush_time_out, NULL); - return FALSE; - } - else - return TRUE; - } - else - return FALSE; -} - - -static void -airbrush_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - double pressure, - PaintApplicationMode mode) -{ - GImage *gimage; - TempBuf *area; - guchar col[MAX_CHANNELS]; - gdouble scale; - - if (!drawable) - return; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - /* color the pixels */ - if (pressure_options->color) - { - GimpRGB color; - - gradient_get_color_at (gimp_context_get_gradient (NULL), - paint_core->curpressure, &color); - - gimp_rgba_get_uchar (&color, - &col[RED_PIX], - &col[GREEN_PIX], - &col[BLUE_PIX], - &col[ALPHA_PIX]); - - mode = INCREMENTAL; - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - } - else if (paint_core->brush && paint_core->brush->pixmap) - { - mode = INCREMENTAL; - paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area, - scale, SOFT); - } - else - { - gimp_image_get_foreground (gimage, drawable, col); - col[area->bytes - 1] = OPAQUE_OPACITY; - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - } - - if (pressure_options->pressure) - pressure = pressure * 2.0 * paint_core->curpressure; - - /* paste the newly painted area to the image */ - paint_core_paste_canvas (paint_core, drawable, - MIN (pressure, 255), - (gint) (gimp_context_get_opacity (NULL) * 255), - gimp_context_get_paint_mode (NULL), - SOFT, scale, mode); -} - -static gpointer -airbrush_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - airbrush_motion (paint_core, drawable, &non_gui_pressure_options, - non_gui_pressure, non_gui_incremental); - - return NULL; -} - -gboolean -airbrush_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array) -{ - AirbrushOptions *options = airbrush_options; - gdouble pressure = AIRBRUSH_PRESSURE_DEFAULT; - - if(options) - pressure = options->pressure; - - return airbrush_non_gui (drawable, pressure, num_strokes, stroke_array); -} - -gboolean -airbrush_non_gui (GimpDrawable *drawable, - gdouble pressure, - gint num_strokes, - gdouble *stroke_array) -{ - gint i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = airbrush_non_gui_paint_func; - - non_gui_pressure = pressure; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - airbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - - return TRUE; - } - - return FALSE; -} diff --git a/app/airbrush.h b/app/airbrush.h deleted file mode 100644 index 6eb5528f0f..0000000000 --- a/app/airbrush.h +++ /dev/null @@ -1,35 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __AIRBRUSH_H__ -#define __AIRBRUSH_H__ - - -gboolean airbrush_non_gui (GimpDrawable *drawable, - gdouble pressure, - gint num_strokes, - gdouble *stroke_array); -gboolean airbrush_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array); - -Tool * tools_new_airbrush (void); -void tools_free_airbrush (Tool *tool); - - -#endif /* __AIRBRUSH_H__ */ diff --git a/app/airbrush_blob.c b/app/airbrush_blob.c deleted file mode 100644 index 81051e2cfc..0000000000 --- a/app/airbrush_blob.c +++ /dev/null @@ -1,1841 +0,0 @@ -/* airbrush_blob.c: routines for manipulating scan converted convex - * polygons. - * - * Copyright 1998-1999, Owen Taylor - * - * > Please contact the above author before modifying the copy < - * > of this file in the GIMP distribution. Thanks. < - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include -#include -#include - -#include - -#include "airbrush_blob.h" - - -#define SUBSAMPLE 8.0 -#define SU 8.0 - - -static AirBrushBlob * -airbrush_blob_new (int y, int height) -{ - - AirBrushBlob *result; - - result = g_malloc (sizeof (AirBrushBlob) + sizeof(AirBrushBlobSpan) * (height-1)); - result->y = y; - result->height = height; - return result; -} - - -static AirBlob * -airblob_new(int y) -{ - AirBlob *result; - - result = g_malloc (sizeof (AirBlob)); - return result; -} - -static AirLine * -airline_new(int y) -{ - AirLine *result; - - result = g_malloc(sizeof (AirLine)); - return result; -} - - - - - -typedef enum { - EDGE_NONE = 0, - EDGE_LEFT = 1 << 0, - EDGE_RIGHT = 1 << 1 -} EdgeType; - -static void -airbrush_blob_fill (AirBrushBlob *b, EdgeType *present) -{ - - int start; - int x1, x2, i1, i2; - int i; - - /* Mark empty lines at top and bottom as unused */ - - start = 0; - while (!(present[start])) - { - b->data[start].left = 0; - b->data[start].right = -1; - start++; - } - if (present[start] != (EDGE_RIGHT | EDGE_LEFT)) - { - if (present[start] == EDGE_RIGHT) - b->data[start].left = b->data[start].right; - else - b->data[start].right = b->data[start].left; - - present[start] = EDGE_RIGHT | EDGE_LEFT; - } - - for (i=b->height-1;!present[i];i--) - { - b->data[i].left = 0; - b->data[i].right = -1; - } - if (present[i] != (EDGE_RIGHT | EDGE_LEFT)) - { - if (present[i] == EDGE_RIGHT) - b->data[i].left = b->data[i].right; - else - b->data[i].right = b->data[i].left; - - present[i] = EDGE_RIGHT | EDGE_LEFT; - } - - - /* Restore missing edges */ - - /* We fill only interior regions of convex hull, as if we were filling - polygons. But since we draw ellipses with nearest points, not interior - points, maybe it would look better if we did the same here. Probably - not a big deal either way after anti-aliasing */ - - /* left edge */ - for (i1=start; i1height-2; i1++) - { - /* Find empty gaps */ - if (!(present[i1+1] & EDGE_LEFT)) - { - int increment; /* fractional part */ - int denom; /* denominator of fraction */ - int step; /* integral step */ - int frac; /* fractional step */ - int reverse; - - /* find bottom of gap */ - i2 = i1+2; - while (!(present[i2] & EDGE_LEFT) && i2 < b->height) i2++; - - if (i2 < b->height) - { - denom = i2-i1; - x1 = b->data[i1].left; - x2 = b->data[i2].left; - step = (x2-x1)/denom; - frac = x2-x1 - step*denom; - if (frac < 0) - { - frac = -frac; - reverse = 1; - } - else - reverse = 0; - - increment = 0; - for (i=i1+1; i= denom) - { - increment -= denom; - x1 += reverse ? -1 : 1; - } - if (increment == 0 || reverse) - b->data[i].left = x1; - else - b->data[i].left = x1 + 1; - } - } - i1 = i2-1; /* advance to next possibility */ - } - } - - /* right edge */ - for (i1=start; i1height-2; i1++) - { - /* Find empty gaps */ - if (!(present[i1+1] & EDGE_RIGHT)) - { - int increment; /* fractional part */ - int denom; /* denominator of fraction */ - int step; /* integral step */ - int frac; /* fractional step */ - int reverse; - - /* find bottom of gap */ - i2 = i1+2; - while (!(present[i2] & EDGE_RIGHT) && i2 < b->height) i2++; - - if (i2 < b->height) - { - denom = i2-i1; - x1 = b->data[i1].right; - x2 = b->data[i2].right; - step = (x2-x1)/denom; - frac = x2-x1 - step*denom; - if (frac < 0) - { - frac = -frac; - reverse = 1; - } - else - reverse = 0; - - increment = 0; - for (i=i1+1; i= denom) - { - increment -= denom; - x1 += reverse ? -1 : 1; - } - if (reverse && increment != 0) - b->data[i].right = x1 - 1; - else - b->data[i].right = x1; - } - } - i1 = i2-1; /* advance to next possibility */ - } - } - -} - -static void -airbrush_blob_make_convex (AirBrushBlob *b, EdgeType *present) -{ - int x1, x2, y1, y2, i1, i2; - int i; - int start; - - /* Walk through edges, deleting points that aren't on convex hull */ - - start = 0; - while (!(present[start])) start++; - - /* left edge */ - - i1 = start-1; - i2 = start; - x1 = b->data[start].left - b->data[start].right; - y1 = 0; - - for (i=start+1;iheight;i++) - { - if (!(present[i] & EDGE_LEFT)) - continue; - - x2 = b->data[i].left - b->data[i2].left; - y2 = i-i2; - - while (x2*y1 - x1*y2 < 0) /* clockwise rotation */ - { - present[i2] &= ~EDGE_LEFT; - i2 = i1; - while (!(present[--i1] & EDGE_LEFT) && i1>=start); - - if (i1data[start].left - b->data[start].right; - y1 = 0; - } - else - { - x1 = b->data[i2].left - b->data[i1].left; - y1 = i2 - i1; - } - x2 = b->data[i].left - b->data[i2].left; - y2 = i - i2; - } - x1 = x2; - y1 = y2; - i1 = i2; - i2 = i; - } - - /* Right edge */ - - i1 = start -1; - i2 = start; - x1 = b->data[start].right - b->data[start].left; - y1 = 0; - - for (i=start+1;iheight;i++) - { - if (!(present[i] & EDGE_RIGHT)) - continue; - - x2 = b->data[i].right - b->data[i2].right; - y2 = i-i2; - - while (x2*y1 - x1*y2 > 0) /* counter-clockwise rotation */ - { - present[i2] &= ~EDGE_RIGHT; - i2 = i1; - while (!(present[--i1] & EDGE_RIGHT) && i1>=start); - - if (i1data[start].right - b->data[start].left; - y1 = 0; - } - else - { - x1 = b->data[i2].right - b->data[i1].right; - y1 = i2 - i1; - } - x2 = b->data[i].right - b->data[i2].right; - y2 = i - i2; - } - x1 = x2; - y1 = y2; - i1 = i2; - i2 = i; - } - - airbrush_blob_fill (b, present); -} - -AirBrushBlob * -airbrush_blob_convex_union (AirBrushBlob *b1, AirBrushBlob *b2) -{ - AirBrushBlob *result; - int y; - int i, j; - EdgeType *present; - - - /* Create the storage for the result */ - - y = MIN(b1->y,b2->y); - result = airbrush_blob_new (y, MAX(b1->y+b1->height,b2->y+b2->height)-y); - - if (result->height == 0) - return result; - - present = g_new0 (EdgeType, result->height); - - /* Initialize spans from original objects */ - - for (i=0, j=b1->y-y; iheight; i++,j++) - { - if (b1->data[i].right >= b1->data[i].left) - { - present[j] = EDGE_LEFT | EDGE_RIGHT; - result->data[j].left = b1->data[i].left; - result->data[j].right = b1->data[i].right; - } - } - - for (i=0, j=b2->y-y; iheight; i++,j++) - { - if (b2->data[i].right >= b2->data[i].left) - { - if (present[j]) - { - if (result->data[j].left > b2->data[i].left) - result->data[j].left = b2->data[i].left; - if (result->data[j].right < b2->data[i].right) - result->data[j].right = b2->data[i].right; - } - else - { - present[j] = EDGE_LEFT | EDGE_RIGHT; - result->data[j].left = b2->data[i].left; - result->data[j].right = b2->data[i].right; - } - } - } - - airbrush_blob_make_convex (result, present); - - g_free (present); - return result; -} - -/* You must be able to divide TABLE_SIZE with 4*/ - -#define TABLE_SIZE 256 -#define TABLE_QUARTER TABLE_SIZE/4 - -#define ELLIPSE_SHIFT 2 -#define TABLE_SHIFT 14 -#define TOTAL_SHIFT (ELLIPSE_SHIFT + TABLE_SHIFT) - -static int trig_initialized = 0; -static int trig_table[TABLE_SIZE]; -#define POWFAC 0.999 - - - -/* Scan convert an ellipse specified by _offsets_ of major and - minor axes, and by center into a airbrush_blob */ - -/* Warning UGLY code ahead :-)*/ - -AirBrushBlob * -airbrush_blob_ellipse (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl) -{ - int i; - AirBrushBlob *rma, *rmi, *rtot; - gint maxyma, minyma, maxymi, minymi; - gint step; - double max_radius; - double ma_ang1, ma_ang2; - double x1, x2, y1, y2; - double xtotma, ytotma; - double xcma, ycma, ytma, xrma, ybma, xlma; - double xcmi, ycmi, ytmi, xrmi, ybmi, xlmi; - double mapoint_i, mapoint; - - gint xcma_shift, ycma_shift; - gint xcmi_shift, ycmi_shift; - gint ytma_shift, ytmi_shift; - gint xrma_shift, xrmi_shift; - gint ybma_shift, ybmi_shift; - gint xlma_shift, xlmi_shift; - - EdgeType *presentma; - EdgeType *presentmi; - - - if ((yt == yb) && (xr == xl) && (yt == xr)) - { - /*Zero*/ - - ytma = ytmi = xrma = xrmi = ybma = ybmi = xlma = xlmi = yt; - ycma = ycmi = yc; - xcma = xcmi = xc; - - } - else if (xr == xl) - { - if (yt > yb) - { - /*South*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = xl; - mapoint_i = (((yt * yt) / yb) - yt); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc; - ycma = yc + mapoint; - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = xl/2; - xcmi = xc; - ycmi = yc - mapoint/2; - - } - else - { - /*North*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = xl; - mapoint_i = (((yb * yb) / yt) - yb); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc; - ycma = yc - mapoint; - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = xl/2; - xcmi = xc; - ycmi = yc + mapoint/2; - - } - } - else if (yt == yb) - { - if (xr > xl) - { - /*East*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = yt; - mapoint_i = (((xr * xr) /xl) -xr); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = mapoint + xc; - ycma = yc; - - /*The Min Circle*/ - ytmi = ybmi = xrmi = xlmi = yt/2; - xcmi = xc - mapoint/2; - ycmi = yc; - - } - else - { - /*West*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = yt; - mapoint_i = (((xl * xl) /xr) - xl); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc - mapoint; - ycma = yc; - - - /*The Min Circle*/ - ytmi = ybmi = xrmi = xlmi = yt/2; - xcmi = xc + mapoint/2; - ycmi = yc; - - } - } - else if ((yt > yb) && (xr > xl)) - { - /*SouthEast*/ - - /*The Max circle*/ - ma_ang1 = atan(yt/xr); - x1 = cos(ma_ang1) * xl; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xr; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yt * yt + xr * xr) / hypot(yb, xl)) - hypot(yt, xr)); - mapoint = mapoint_i * pow(POWFAC , mapoint_i); - xcma = xc + (cos(ma_ang1) * mapoint); - ycma = yc + (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yb, xl)/2; - xcmi = xc - (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc - (sin(ma_ang1) * mapoint * 0.5); - - } - else if ((yt > yb) && (xl > xr)) - { - /*SouthWest*/ - - /*The Max circle*/ - ma_ang1 = atan(yt/xl); - x1 = cos(ma_ang1) * xr; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xl; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yt * yt + xl * xl) / hypot(yb, xr)) - hypot(yt, xl)); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc - (cos(ma_ang1) * mapoint); - ycma = yc + (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yb, xr)/2; - xcmi = xc + (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc - (sin(ma_ang1) * mapoint * 0.5); - - } - else if ((yb > yt) && (xl > xr)) - { - /*NorthWest*/ - - /*The Max circle*/ - ma_ang1 = atan(yb/xl); - x1 = cos(ma_ang1) * xl; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xr; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yb * yb + xl * xl) / hypot(yt, xr)) - hypot(yb, xl)); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc - (cos(ma_ang1) * mapoint); - ycma = yc - (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yt, xr)/2; - xcmi = xc + (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc + (sin(ma_ang1) * mapoint * 0.5); - - } - else -/*if ((yb > yt) && (xr > xl))*/ - { - /*NorthEast*/ - - /*The Max circle*/ - ma_ang1 = atan(yb/xr); - x1 = cos(ma_ang1) * xr; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xl; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yb * yb + xr * xr) / hypot(yt, xl)) - hypot(yb, xr)); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc + (cos(ma_ang1) * mapoint); - ycma = yc - (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yt, xl)/2; - xcmi = xc - (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc + (sin(ma_ang1) * mapoint * 0.5); - - } - if (ytmi <= 0) - { - ytmi = ybmi = xrmi = xlmi = 1; - } - - if (ytma <= 0) - { - ytma = ybma = xrma = xlma = 1; - } - - if (!trig_initialized) - { - trig_initialized = 1; - for (i=0; i<256; i++) - trig_table[i] = 0.5 + sin(i * (G_PI / 128.0)) * (1 << TABLE_SHIFT); - } - - -/*Make the Max circle*/ - - maxyma = ceil (ycma + fabs (ytma)); - minyma = floor (ycma - fabs (ybma)); - - - - rma = airbrush_blob_new (minyma, maxyma - minyma + 1); - - - presentma = g_new0 (EdgeType, rma->height); - - max_radius = ytma; - - step = TABLE_SIZE; - - while (step > 1 && (TABLE_SIZE / step < 4*max_radius)) - step >>= 1; - - /* Fill in the edge points */ - - xcma_shift = 0.5 + xcma * (1 << TOTAL_SHIFT); - ycma_shift = 0.5 + ycma * (1 << TOTAL_SHIFT); - ytma_shift = 0.5 + ytma * (1 << ELLIPSE_SHIFT); - xrma_shift = 0.5 + xrma * (1 << ELLIPSE_SHIFT); - ybma_shift = 0.5 + ybma * (1 << ELLIPSE_SHIFT); - xlma_shift = 0.5 + xlma * (1 << ELLIPSE_SHIFT); - - - for (i = 0 ; i < TABLE_SIZE ; i += step) - { - - gint x, y, yi, dydi; - - gint s = trig_table[i]; - gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE]; - - if (i < TABLE_QUARTER ) - { - x = (xcma_shift + c * xrma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - yi = (ycma_shift + s * ytma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - y = yi - rma->y; - dydi = 1; - - } - else if ( i < (2 * TABLE_QUARTER) ) - { - x = (xcma_shift + c * xlma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - yi = (ycma_shift + s * ytma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - - y = yi - rma->y; - - dydi = -1; - } - else if ( i < (3 * TABLE_QUARTER) ) - { - x = (xcma_shift + c * xlma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - yi = (ycma_shift + s * ybma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - y = yi - rma->y; - dydi = -1; - - } - else - { - x = (xcma_shift + c * xrma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - y = ((ycma_shift + s * ybma_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - rma->y; - - dydi = 1; - - } - - - - - if (dydi <= 0) /* left edge */ - { - if (presentma[y] & EDGE_LEFT) - { - rma->data[y].left = MIN (rma->data[y].left, x); - } - else - { - presentma[y] |= EDGE_LEFT; - rma->data[y].left = x; - } - } - - if (dydi > 0) /* right edge */ - { - if (presentma[y] & EDGE_RIGHT) - { - rma->data[y].right = MAX (rma->data[y].right, x); - } - else - { - presentma[y] |= EDGE_RIGHT; - rma->data[y].right = x; - } - } - } - - /* Now fill in missing points */ - - airbrush_blob_fill (rma, presentma); - g_free (presentma); - -/*Make the Min circle*/ - - - maxymi = ceil (ycmi + fabs (ytmi)); - minymi = floor (ycmi - fabs (ybmi)); - - - rmi = airbrush_blob_new (minymi, maxymi - minymi + 1); - - - presentmi = g_new0 (EdgeType, rmi->height); - - max_radius = ytmi; - - step = TABLE_SIZE; - - while (step > 1 && (TABLE_SIZE / step < 4*max_radius)) - step >>= 1; - - /* Fill in the edge points */ - - xcmi_shift = 0.5 + xcmi * (1 << TOTAL_SHIFT); - ycmi_shift = 0.5 + ycmi * (1 << TOTAL_SHIFT); - ytmi_shift = 0.5 + ytmi * (1 << ELLIPSE_SHIFT); - xrmi_shift = 0.5 + xrmi * (1 << ELLIPSE_SHIFT); - ybmi_shift = 0.5 + ybmi * (1 << ELLIPSE_SHIFT); - xlmi_shift = 0.5 + xlmi * (1 << ELLIPSE_SHIFT); - - - - for (i = 0 ; i < TABLE_SIZE ; i += step) - { - - gint x, y, yi, dydi; - - gint s = trig_table[i]; - gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE]; - - if (i < TABLE_QUARTER ) - { - x = (xcmi_shift + c * xrmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - yi = (ycmi_shift + s * ytmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - y = yi - rmi->y; - dydi = 1; - - } - else if ( i < (2 * TABLE_QUARTER) ) - { - x = (xcmi_shift + c * xlmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - yi = (ycmi_shift + s * ytmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - - y = yi - rmi->y; - - dydi = -1; - } - else if ( i < (3 * TABLE_QUARTER) ) - { - x = (xcmi_shift + c * xlmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - yi = (ycmi_shift + s * ybmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - y = yi - rmi->y; - dydi = -1; - - } - else - { - x = (xcmi_shift + c * xrmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - y = ((ycmi_shift + s * ybmi_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - rmi->y; - - dydi = 1; - - } - - - - - if (dydi <= 0) /* left edge */ - { - if (presentmi[y] & EDGE_LEFT) - { - rmi->data[y].left = MIN (rmi->data[y].left, x); - } - else - { - presentmi[y] |= EDGE_LEFT; - rmi->data[y].left = x; - } - } - - if (dydi > 0) /* right edge */ - { - if (presentmi[y] & EDGE_RIGHT) - { - rmi->data[y].right = MAX (rmi->data[y].right, x); - } - else - { - presentmi[y] |= EDGE_RIGHT; - rmi->data[y].right = x; - } - } - } - - /* Now fill in missing points */ - - airbrush_blob_fill (rmi, presentmi); - g_free (presentmi); - - rtot = airbrush_blob_convex_union(rma, rmi); - - g_free (rma); - g_free (rmi); - - return rtot; -} - -void -airbrush_blob_bounds(AirBrushBlob *b, int *x, int *y, int *width, int *height) -{ - int i; - int x0, x1, y0, y1; - - i = 0; - while (iheight && b->data[i].left > b->data[i].right) - i++; - - if (iheight) - { - y0 = b->y + i; - x0 = b->data[i].left; - x1 = b->data[i].right + 1; - while (iheight && b->data[i].left <= b->data[i].right) - { - x0 = MIN(b->data[i].left, x0); - x1 = MAX(b->data[i].right+1, x1); - i++; - } - y1 = b->y + i; - } - else - { - x0 = y0 = 0; - x1 = y1 = 0; - } - - *x = x0; - *y = y0; - *width = x1 - x0; - *height = y1 - y0; -} - -void -airbrush_blob_dump(AirBrushBlob *b) { - - int i,j; - - - for (i=0; iheight; i++) - { - for (j=0;jdata[i].left;j++) - putchar(' '); - for (j=b->data[i].left;j<=b->data[i].right;j++) - putchar('*'); - putchar('\n'); - } -} - -/* This is just a first try to see how it works i.e ugly code :-) */ - - -AirBlob * -create_air_blob (double xc, - double yc, - double xt, - double yt, - double xr, - double yr, - double xb, - double yb, - double xl, - double yl, - double direction_abs, - double direction) -{ - AirBlob *air_blob; - double ma_ang1, ma_ang2; - double x1, x2, y1, y2; - double xtotma, ytotma; - double xcma, ycma, ytma, xrma, ybma, xlma; - double xcmi, ycmi, ytmi, xrmi, ybmi, xlmi; - double mapoint_i, mapoint; - - air_blob = airblob_new(1); - - air_blob->direction_abs = direction_abs; - air_blob->direction = direction; - air_blob->ycenter = yc; - air_blob->xcenter = xc; - - if ((yt == yb) && (xr == xl) && (yt == xr)) - { - /*Zero*/ - - ytma = ytmi = xrma = xrmi = ybma = ybmi = xlma = xlmi = yt; - ycma = ycmi = yc; - xcma = xcmi = xc; - - air_blob->main_line.size = yt; - air_blob->minor_line.size = yt; - - air_blob->maincross_line.size = yt * 2; - air_blob->maincross_line.dist = 0.0; - - air_blob->minorcross_line.size = yt * 2; - air_blob->minorcross_line.dist = 0.0; - - air_blob->direction = G_PI_2; - - } - else if (xr == xl) - { - if (yt > yb) - { - /*South*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = xl; - mapoint_i = (((yt * yt) / yb) - yt); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc; - ycma = yc + mapoint; - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = xl/2; - xcmi = xc; - ycmi = yc - mapoint/2; - - air_blob->main_line.size = mapoint + xl; - air_blob->minor_line.size = mapoint/2 + xl/2; - - air_blob->maincross_line.size = xl * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xl/2; - air_blob->minorcross_line.dist = mapoint/2; - - - - } - else - { - /*North*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = xl; - mapoint_i = (((yb * yb) / yt) - yb); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc; - ycma = yc - mapoint; - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = xl/2; - xcmi = xc; - ycmi = yc + mapoint/2; - - - air_blob->main_line.size = mapoint + xl; - air_blob->minor_line.size = mapoint/2 + xl/2; - - air_blob->maincross_line.size = xl * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xl/2; - air_blob->minorcross_line.dist = mapoint/2; - - - } - } - else if (yt == yb) - { - if (xr > xl) - { - /*East*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = yt; - mapoint_i = (((xr * xr) /xl) -xr); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = mapoint + xc; - ycma = yc; - - /*The Min Circle*/ - ytmi = ybmi = xrmi = xlmi = yt/2; - xcmi = xc - mapoint/2; - ycmi = yc; - - air_blob->main_line.size = mapoint + yt; - air_blob->minor_line.size = mapoint/2 + yt/2; - - air_blob->maincross_line.size = xl * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xl/2; - air_blob->minorcross_line.dist = mapoint/2; - - - } - else - { - /*West*/ - - /*The Max circle*/ - ytma = ybma = xrma = xlma = yt; - mapoint_i = (((xl * xl) /xr) - xl); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc - mapoint; - ycma = yc; - - - /*The Min Circle*/ - ytmi = ybmi = xrmi = xlmi = yt/2; - xcmi = xc + mapoint/2; - ycmi = yc; - - air_blob->main_line.size = mapoint + yt; - air_blob->minor_line.size = mapoint/2 + yt/2; - - air_blob->maincross_line.size = xl * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xl/2; - air_blob->minorcross_line.dist = mapoint/2; - - - } - } - else if ((yt > yb) && (xr > xl)) - { - /*SouthEast*/ - - /*The Max circle*/ - ma_ang1 = atan(yt/xr); - x1 = cos(ma_ang1) * xl; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xr; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yt * yt + xr * xr) / hypot(yb, xl)) - hypot(yt, xr)); - mapoint = mapoint_i * pow(POWFAC , mapoint_i); - xcma = xc + (cos(ma_ang1) * mapoint); - ycma = yc + (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yb, xl)/2; - xcmi = xc - (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc - (sin(ma_ang1) * mapoint * 0.5); - - - air_blob->main_line.size = mapoint + xlma; - air_blob->minor_line.size = mapoint/2 + xlmi; - - - air_blob->maincross_line.size = xlma * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xlmi; - air_blob->minorcross_line.dist = mapoint/2; - - - - - } - else if ((yt > yb) && (xl > xr)) - { - /*SouthWest*/ - - /*The Max circle*/ - ma_ang1 = atan(yt/xl); - x1 = cos(ma_ang1) * xr; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xl; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yt * yt + xl * xl) / hypot(yb, xr)) - hypot(yt, xl)); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc - (cos(ma_ang1) * mapoint); - ycma = yc + (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yb, xr)/2; - xcmi = xc + (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc - (sin(ma_ang1) * mapoint * 0.5); - - air_blob->main_line.size = mapoint + xlma; - air_blob->minor_line.size = mapoint/2 + xlmi; - - air_blob->maincross_line.size = xlma * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xlmi; - air_blob->minorcross_line.dist = mapoint/2; - - } - else if ((yb > yt) && (xl > xr)) - { - /*NorthWest*/ - - /*The Max circle*/ - ma_ang1 = atan(yb/xl); - x1 = cos(ma_ang1) * xl; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xr; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yb * yb + xl * xl) / hypot(yt, xr)) - hypot(yb, xl)); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc - (cos(ma_ang1) * mapoint); - ycma = yc - (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yt, xr)/2; - xcmi = xc + (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc + (sin(ma_ang1) * mapoint * 0.5); - - air_blob->main_line.size = mapoint + xlma; - air_blob->minor_line.size = mapoint/2 + xlmi; - - air_blob->maincross_line.size = xlma * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xlmi; - air_blob->minorcross_line.dist = mapoint/2; - - - - - } - else -/*if ((yb > yt) && (xr > xl))*/ - { - /*NorthEast*/ - - /*The Max circle*/ - ma_ang1 = atan(yb/xr); - x1 = cos(ma_ang1) * xr; - y1 = sin(ma_ang1) * yt; - ma_ang2 = G_PI_2 - ma_ang1; - x2 = cos(ma_ang2) * xl; - y2 = sin(ma_ang2) * yb; - xtotma = x1 + x2; - ytotma = y1 + y2; - ytma = ybma = xrma = xlma = hypot(ytotma, xtotma)/2; - mapoint_i = (((yb * yb + xr * xr) / hypot(yt, xl)) - hypot(yb, xr)); - mapoint = mapoint_i * pow(POWFAC, mapoint_i); - xcma = xc + (cos(ma_ang1) * mapoint); - ycma = yc - (sin(ma_ang1) * mapoint); - - /*The Min Circle*/ - ytmi = xrmi = ybmi = xlmi = hypot(yt, xl)/2; - xcmi = xc - (cos(ma_ang1) * mapoint * 0.5); - ycmi = yc + (sin(ma_ang1) * mapoint * 0.5); - - air_blob->main_line.size = mapoint + xlma; - air_blob->minor_line.size = mapoint/2 + xlmi; - - - air_blob->maincross_line.size = xlma * 2; - air_blob->maincross_line.dist = mapoint; - - air_blob->minorcross_line.size = xlmi; - air_blob->minorcross_line.dist = mapoint/2; - - - } - - return air_blob; -} - -AirLine * -create_air_line(AirBlob *airblob) -{ - - int i; - double xcenter, ycenter; - - double direction; - - double masupport, misupport; - double ma_angsupport, mi_angsupport, iang; - - int min_x, max_x; - int min_y, max_y; - - AirLine *airline; - - /* - Yes I know I can do a cal of number of lines, but it is for - the moment much easier to just set a side mem for 16 lines - */ - - airline = airline_new(1); - - xcenter = airblob->xcenter; - ycenter = airblob->ycenter; - - airline->xcenter = xcenter/SUBSAMPLE; - airline->ycenter = ycenter/SUBSAMPLE; - - direction = airblob->direction_abs; - - /* - printf("Direction: %f\n", direction); - printf("Xcenter: %f\n",xcenter/SUBSAMPLE); - printf("Ycenter: %f\n",ycenter/SUBSAMPLE); - printf("MaCr.dist: %f\n",airblob->maincross_line.dist); - printf("MaCr.size: %f\n",airblob->maincross_line.size); - printf("MiCr.dist: %f\n",airblob->minorcross_line.dist); - printf("MiCr.size: %f\n",airblob->minorcross_line.size); - printf("Ma.size: %f\n",airblob->main_line.size); - printf("Mi.size: %f\n",airblob->minor_line.size); - */ - - if (direction == G_PI_2 || direction == G_PI) - { - direction = direction - 0.001; - } - - if (direction == -G_PI_2 || direction == -G_PI) - { - direction = direction + 0.001; - } - - if(direction == 0.0) - - { - - airline->line[0].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[0].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[1].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[1].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->line[2].x = (xcenter + airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter)/SUBSAMPLE; - airline->line[3].x = (xcenter - airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter)/SUBSAMPLE; - - airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[4].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[5].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->nlines = 6; - - - } - - else if(direction == G_PI_2) - - { - - airline->line[0].x = (xcenter - airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[0].y = (ycenter - airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[1].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->line[2].x = (xcenter)/SUBSAMPLE; - airline->line[2].y = (ycenter - airblob->main_line.size)/SUBSAMPLE; - airline->line[3].x = (xcenter)/SUBSAMPLE; - airline->line[3].y = (ycenter + airblob->minor_line.size)/SUBSAMPLE; - - airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->nlines = 6; - printf("Hmm bummer G_PI_2\n"); - - } - - - else if(direction == G_PI) - - { - airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->line[2].x = (xcenter - airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter)/SUBSAMPLE; - airline->line[3].x = (xcenter + airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter)/SUBSAMPLE; - - airline->line[4].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[5].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->nlines = 6; - - printf("Hmm bummer G_PI\n"); - - - } - - else if(direction == -G_PI_2) - - { - airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->line[2].x = (xcenter)/SUBSAMPLE; - airline->line[2].y = (ycenter + airblob->main_line.size)/SUBSAMPLE; - airline->line[3].x = (xcenter)/SUBSAMPLE; - airline->line[3].y = (ycenter - airblob->minor_line.size)/SUBSAMPLE; - - airline->line[4].x = (xcenter + airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[4].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[5].x = (xcenter - airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[5].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->nlines = 6; - - printf("Hmm bummer -G_PI_2\n"); - - - - } - - - else if(direction == -G_PI) - - { - airline->line[0].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[0].y = (ycenter + airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[1].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[1].y = (ycenter - airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->line[2].x = (xcenter - airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter)/SUBSAMPLE; - airline->line[3].x = (xcenter + airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter)/SUBSAMPLE; - - airline->line[4].x = (xcenter - airblob->maincross_line.dist)/SUBSAMPLE; - airline->line[4].y = (ycenter - airblob->maincross_line.size/2)/SUBSAMPLE; - airline->line[5].x = (xcenter + airblob->minorcross_line.dist)/SUBSAMPLE; - airline->line[5].y = (ycenter + airblob->minorcross_line.size/2)/SUBSAMPLE; - - airline->nlines = 6; - - printf("Hmm bummer -G_PI\n"); - - - } - - - else if ((direction < G_PI) && (direction > G_PI_2)) - - { - - - masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2); - misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2); - - ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist); - mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist); - - iang = airblob->direction_abs - G_PI_2; - - airline->line[0].x = (xcenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[0].y = (ycenter - cos(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[1].x = (xcenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[1].y = (ycenter + cos(iang + mi_angsupport) * misupport)/SUBSAMPLE; - - airline->line[2].x = (xcenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter - cos(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[3].x = (xcenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter + cos(iang) * airblob->minor_line.size)/SUBSAMPLE; - - airline->line[4].x = (xcenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[4].y = (ycenter - cos(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[5].x = (xcenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[5].y = (ycenter + cos(iang - mi_angsupport) * misupport)/SUBSAMPLE; - - /*airline->line[6].x = (xcenter - sin(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[6].y = (ycenter - cos(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[7].x = (xcenter - sin(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[7].y = (ycenter - cos(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - - airline->line[8].x = (xcenter - sin(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[8].y = (ycenter - cos(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[9].x = (xcenter - sin(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[9].y = (ycenter - cos(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - - airline->line[10].x = (xcenter - sin(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[10].y = (ycenter - cos(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[11].x = (xcenter - sin(iang - ma_angsupport/2. - ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[11].y = (ycenter - cos(iang - ma_angsupport/2. - ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE;*/ - - - airline->nlines = 6; - - } - - else if ((direction < G_PI_2) && (direction > 0.0)) - - { - - - masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2); - misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2); - - ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist); - mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist); - - iang = airblob->direction_abs; - - airline->line[0].x = (xcenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[0].y = (ycenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[1].x = (xcenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[1].y = (ycenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE; - - airline->line[2].x = (xcenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[3].x = (xcenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE; - - airline->line[4].x = (xcenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[4].y = (ycenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[5].x = (xcenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[5].y = (ycenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE; - - - /*airline->line[6].x = (xcenter + cos(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[6].y = (ycenter - sin(iang + ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[7].x = (xcenter + cos(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[7].y = (ycenter - sin(iang - ma_angsupport/2.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - - airline->line[8].x = (xcenter + cos(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[8].y = (ycenter - sin(iang + ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[9].x = (xcenter + cos(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[9].y = (ycenter - sin(iang - ma_angsupport/4.) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - - airline->line[10].x = (xcenter + cos(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[10].y = (ycenter - sin(iang + ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[11].x = (xcenter + cos(iang - ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - airline->line[11].y = (ycenter - sin(iang - ma_angsupport/2. + ma_angsupport) * (masupport + (airblob->main_line.size - masupport)/2.0))/SUBSAMPLE; - - airline->line[12].x = airline->line[2].x + (airline->line[4].x - airline->line[2].x)/4; - airline->line[12].y = airline->line[2].y + (airline->line[4].y - airline->line[2].y)/4; - airline->line[13].x = airline->line[2].x + 3 * (airline->line[4].x - airline->line[2].x)/4; - airline->line[13].y = airline->line[2].y + 3 * (airline->line[4].y - airline->line[2].y)/4; - */ - - - - airline->nlines = 6; - - - } - - - else if ((direction < 0.0) && (direction > -G_PI_2)) - - { - - - masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2); - misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2); - - ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist); - mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist); - - iang = fabs(airblob->direction_abs); - - airline->line[0].x = (xcenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[0].y = (ycenter + sin(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[1].x = (xcenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[1].y = (ycenter - sin(iang + mi_angsupport) * misupport)/SUBSAMPLE; - - airline->line[2].x = (xcenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter + sin(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[3].x = (xcenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter - sin(iang) * airblob->minor_line.size)/SUBSAMPLE; - - airline->line[4].x = (xcenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[4].y = (ycenter + sin(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[5].x = (xcenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[5].y = (ycenter - sin(iang - mi_angsupport) * misupport)/SUBSAMPLE; - - airline->nlines = 6; - - } - - - else if ((direction < -G_PI_2) && (direction > -G_PI)) - - { - - - masupport = hypot(airblob->maincross_line.dist, airblob->maincross_line.size/2); - misupport = hypot(airblob->minorcross_line.dist,airblob->minorcross_line.size/2); - - ma_angsupport = atan(airblob->maincross_line.size/2/airblob->maincross_line.dist); - mi_angsupport = atan(airblob->minorcross_line.size/2/airblob->minorcross_line.dist); - - iang = fabs(airblob->direction_abs) - G_PI_2; - - airline->line[0].x = (xcenter - sin(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[0].y = (ycenter + cos(iang + ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[1].x = (xcenter + sin(iang + mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[1].y = (ycenter - cos(iang + mi_angsupport) * misupport)/SUBSAMPLE; - - airline->line[2].x = (xcenter - sin(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[2].y = (ycenter + cos(iang) * airblob->main_line.size)/SUBSAMPLE; - airline->line[3].x = (xcenter + sin(iang) * airblob->minor_line.size)/SUBSAMPLE; - airline->line[3].y = (ycenter - cos(iang) * airblob->minor_line.size)/SUBSAMPLE; - - airline->line[4].x = (xcenter - sin(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[4].y = (ycenter + cos(iang - ma_angsupport) * masupport)/SUBSAMPLE; - airline->line[5].x = (xcenter + sin(iang - mi_angsupport) * misupport)/SUBSAMPLE; - airline->line[5].y = (ycenter - cos(iang - mi_angsupport) * misupport)/SUBSAMPLE; - - airline->nlines = 6; - - } - else - { - printf("Hmm a bug in the create_air_line"); - } - - - - - - min_x = max_x = airline->xcenter; - min_y = max_y = airline->ycenter; - - /* - - for (i=0; i < airline->nlines ; i++) - { - printf("x%d, value %d\n", i, airline->line[i].x); - printf("y%d, value %d\n", i, airline->line[i].y); - } - - printf("The xcenter %d\n",airline->xcenter); - printf("The ycenter %d\n",airline->ycenter); - - */ - - for (i=0; i < airline->nlines ; i++) - { - min_x = MIN(airline->line[i].x, min_x); - max_x = MAX(airline->line[i].x, max_x); - min_y = MIN(airline->line[i].y, min_y); - max_y = MAX(airline->line[i].y, max_y); - } - - airline->width = max_x - min_x + 1; - airline->height = max_y - min_y + 1; - - airline->min_x = min_x; - airline->min_y = min_y; - airline->max_x = max_x; - airline->max_y = max_y; - - return airline; - -} - -AirBlob * -trans_air_blob(AirBlob *airblob_last, AirBlob *airblob_present, double dist, int xcen, int ycen) -{ - - AirBlob *trans_airblob; - - double direction_last_abs, direction_present_abs; - double idirection_abs; - - double direction_last, direction_present; - double idirection; - - double main_line_present, main_line_last; - - - double minor_line_present, minor_line_last; - - - double maincross_line_dist_present, maincross_line_dist_last; - - double minorcross_line_dist_present, minorcross_line_dist_last; - - - double maincross_line_size_present, maincross_line_size_last; - - double minorcross_line_size_present, minorcross_line_size_last; - - - - trans_airblob = airblob_new(1); - - direction_last_abs = airblob_last->direction_abs + G_PI; - direction_present_abs = airblob_present->direction_abs + G_PI; - - idirection_abs = direction_present_abs - direction_last_abs; - - direction_last = airblob_last->direction + G_PI_2; - direction_present = airblob_present->direction + G_PI_2; - - idirection = direction_present - direction_last; - - main_line_present = airblob_present->main_line.size; - main_line_last = airblob_last->main_line.size; - - minor_line_present = airblob_present->minor_line.size; - minor_line_last = airblob_last->minor_line.size; - - maincross_line_dist_present = airblob_present->maincross_line.dist; - maincross_line_size_present = airblob_present->maincross_line.size; - minorcross_line_dist_present = airblob_present->minorcross_line.dist; - minorcross_line_size_present = airblob_present->minorcross_line.size; - - maincross_line_dist_last = airblob_last->maincross_line.dist; - maincross_line_size_last = airblob_last->maincross_line.size; - minorcross_line_dist_last = airblob_last->minorcross_line.dist; - minorcross_line_size_last = airblob_last->minorcross_line.size; - - - - - /* - Now we have to guess a little :-). Why? - Well we can't know if the users is painting - up/down or if she is painting a circle at high speed. - As you may notice it be so that the last airblob has - a direction more or less G_PI rad differernt from the - present airblob. But we can't know if she tured the - airbrush quickly (so that there was no mouse capture - during the turn) or if she paints just up and down the - same direction. - - There for we guess that we want to pait up and down - when the diff in direction is bigger than 171 deg and - smaller than 189 deg. - - */ - - if ((fabs(idirection_abs) > (G_PI - 0.1571)) && (fabs(idirection_abs) < (G_PI + 0.1571))) - { - /* We asume that the artist meant to paint in a "strait line" by just tilting the airbrush*/ - - idirection_abs = idirection_abs - G_PI; - - if ((idirection_abs * dist) > (idirection_abs/2)) - { - if ((direction_present_abs - idirection_abs * dist) > 2 * G_PI) - { - trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist - 2 * G_PI - G_PI; - } - else if ((direction_present_abs - idirection_abs * dist) < 0.0) - { - trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist + 2 * G_PI - G_PI; - } - else - { - trans_airblob->direction_abs = direction_present_abs - idirection_abs * dist - G_PI; - } - } - else - { - if ((direction_present_abs + idirection_abs * dist) > 2 * G_PI) - { - trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist - 2 * G_PI - G_PI; - } - else if ((direction_present_abs + idirection_abs * dist) < 0.0) - { - trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist + 2 * G_PI - G_PI; - } - else - { - trans_airblob->direction_abs = direction_present_abs + idirection_abs * dist - G_PI; - } - } - - trans_airblob->main_line.size = main_line_last + ((minor_line_present - main_line_last) * dist); - trans_airblob->minor_line.size = minor_line_last + ((main_line_present - minor_line_last) * dist); - - trans_airblob->maincross_line.dist = maincross_line_dist_last + ((minorcross_line_dist_present - maincross_line_dist_last) * dist); - trans_airblob->maincross_line.size = maincross_line_size_last + ((minorcross_line_size_present - maincross_line_size_last) * dist); - - trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((maincross_line_dist_present - minorcross_line_dist_last) * dist); - trans_airblob->minorcross_line.size = minorcross_line_size_last + ((maincross_line_size_present - minorcross_line_size_last) * dist); - - } - - else if (fabs(idirection_abs) < (G_PI - 0.1571)) - { - if ((direction_last_abs + idirection_abs * dist) > 2*G_PI) - { - trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - 2 * G_PI - G_PI; - } - else if((direction_last_abs + idirection_abs * dist) < 0.0) - { - trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist + 2 * G_PI - G_PI; - } - else - { - trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - G_PI; - } - - trans_airblob->main_line.size = main_line_last + ((main_line_present - main_line_last) * dist); - trans_airblob->minor_line.size = minor_line_last + ((minor_line_present - minor_line_last) * dist); - - trans_airblob->maincross_line.dist = maincross_line_dist_last + ((maincross_line_dist_present - maincross_line_dist_last) * dist); - trans_airblob->maincross_line.size = maincross_line_size_last + ((maincross_line_size_present - maincross_line_size_last) * dist); - - trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((minorcross_line_dist_present - minorcross_line_dist_last) * dist); - trans_airblob->minorcross_line.size = minorcross_line_size_last + ((minorcross_line_size_present - minorcross_line_size_last) * dist); - } - else - { - - /* We asume that the artist always travels the shortest way around the "clock" */ - - idirection_abs = idirection_abs - G_PI; - - if ((direction_last_abs + idirection_abs * dist) > 2*G_PI) - { - trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - 2 * G_PI - G_PI; - } - else if((direction_last_abs + idirection_abs * dist) < 0.0) - { - trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist + 2 * G_PI - G_PI; - } - else - { - trans_airblob->direction_abs = direction_last_abs + idirection_abs * dist - G_PI; - } - - trans_airblob->main_line.size = main_line_last + ((main_line_present - main_line_last) * dist); - trans_airblob->minor_line.size = minor_line_last + ((minor_line_present - minor_line_last) * dist); - - trans_airblob->maincross_line.dist = maincross_line_dist_last + ((maincross_line_dist_present - maincross_line_dist_last) * dist); - trans_airblob->maincross_line.size = maincross_line_size_last + ((maincross_line_size_present - maincross_line_size_last) * dist); - - trans_airblob->minorcross_line.dist = minorcross_line_dist_last + ((minorcross_line_dist_present - minorcross_line_dist_last) * dist); - trans_airblob->minorcross_line.size = minorcross_line_size_last + ((minorcross_line_size_present - minorcross_line_size_last) * dist); - - } - - - trans_airblob->xcenter = xcen * SUBSAMPLE; - trans_airblob->ycenter = ycen * SUBSAMPLE; - - return trans_airblob; - -} - - - - - - - - - - - - - - - - diff --git a/app/airbrush_blob.h b/app/airbrush_blob.h deleted file mode 100644 index d11a566537..0000000000 --- a/app/airbrush_blob.h +++ /dev/null @@ -1,153 +0,0 @@ -/* airbrush_blob.h: routines for manipulating scan converted convex - * polygons. - * - * Copyright 1998, Owen Taylor - * - * > Please contact the above author before modifying the copy < - * > of this file in the GIMP distribution. Thanks. < - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * -*/ - -#ifndef __AIRBRUSHBLOB_H__ -#define __AIRBRUSHBLOB_H__ - -typedef enum { - CROSS = 0, - CROSS_LEFT = 1, - CROSS_RIGHT = 2, - CROSS_WHOLE_LINE = 3, - CROSS_NORMAL = 4 -} CrossType; - -typedef enum { - RIGHT_LEFT = 0, - LEFT_RIGHT = 1, - TOP_BOT = 2, - BOT_TOP = 3, - NONE = 4 -} MoveType; - -/* The AirBlob, which is a abstract of a real AirBrushBlob */ - -typedef struct _AirBlob AirBlob; -typedef struct _AirPoint AirPoint; -typedef struct _SupportLine SupportLine; - - -struct _AirPoint { - int x; - int y; -}; - -struct _SupportLine { - double size; - double dist; -}; - -struct _AirBlob { - double direction_abs; - double direction; - double ycenter; - double xcenter; - SupportLine main_line; - SupportLine minor_line; - SupportLine maincross_line; - SupportLine minorcross_line; -}; - - -/* The AirLine is a reslut of a AirBlob */ -typedef struct _AirLine AirLine; - -struct _AirLine { - int xcenter; - int ycenter; - AirPoint line[16]; - int min_x, min_y; - int max_x, max_y; - int width, height; - int nlines; -}; - - -typedef struct _AirBrushBlobPoint AirBrushBlobPoint; -typedef struct _AirBrushBlobSpan AirBrushBlobSpan; -typedef struct _AirBrushBlob AirBrushBlob; - -struct _AirBrushBlobPoint { - int x; - int y; -}; - -struct _AirBrushBlobSpan { - int left; - double angle_left; - double angle_left_abs; - double dist_left; - int right; - double angle_right; - double angle_right_abs; - double dist_right; - - CrossType cross_type; - int x_cross; - - int center; - double dist; - -}; - -struct _AirBrushBlob { - int y; - int height; - int width; - int min_x; - int max_x; - MoveType move; - double direction_abs; - double direction; - CrossType cross; - AirBrushBlobSpan data[1]; -}; - - -typedef struct _AirBrush AirBrush; - -struct _AirBrush { - AirBrushBlob airbrush_blob; - AirBlob airblob; -}; - - - - -AirBlob *create_air_blob (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl, double direction_abs, double direction); -AirBlob *trans_air_blob(AirBlob *airblob_last, AirBlob *airblob_present, double dist, int xc, int yc); -AirLine *create_air_line(AirBlob *airblob); - - - - - -AirBrushBlob *airbrush_blob_convex_union (AirBrushBlob *b1, AirBrushBlob *b2); -AirBrushBlob *airbrush_blob_ellipse (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl); -void airbrush_blob_bounds (AirBrushBlob *b, int *x, int *y, int *width, int *height); - - - - -#endif /* __AIRBRUSHBLOB_H__ */ diff --git a/app/app_procs.c b/app/app_procs.c index ee9474abf7..04e64c887e 100644 --- a/app/app_procs.c +++ b/app/app_procs.c @@ -46,7 +46,6 @@ #include "batch.h" #include "brush_select.h" #include "color_transfer.h" -#include "curves.h" #include "colormaps.h" #include "context_manager.h" #include "devices.h" @@ -65,11 +64,9 @@ #include "gradient_select.h" #include "gradient.h" #include "gximage.h" -#include "hue_saturation.h" #include "image_render.h" #include "interface.h" #include "lc_dialog.h" -#include "levels.h" #include "menus.h" #include "paint_funcs.h" #include "palette.h" @@ -81,7 +78,6 @@ #include "temp_buf.h" #include "tile_swap.h" #include "tips_dialog.h" -#include "tools.h" #include "undo.h" #include "unitrc.h" #include "xcf.h" @@ -97,6 +93,11 @@ #include "color_select.h" #include "gimpparasite.h" +#include "tools/curves.h" +#include "tools/hue_saturation.h" +#include "tools/levels.h" +#include "tools/tools.h" + #include "pdb/internal_procs.h" #include "libgimp/gimplimits.h" diff --git a/app/bezier_select.c b/app/bezier_select.c deleted file mode 100644 index f6243bc703..0000000000 --- a/app/bezier_select.c +++ /dev/null @@ -1,3676 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" - -#include "channel.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "drawable.h" -#include "edit_selection.h" -#include "errors.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimage_mask.h" -#include "gimpcontext.h" -#include "rect_select.h" -#include "bezier_select.h" -#include "bezier_selectP.h" -#include "paths_dialogP.h" -#include "pixel_region.h" -#include "selection_options.h" -#include "tools.h" -#include "tool_options.h" -#include "undo.h" - -#include "pdb/procedural_db.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* Bezier extensions made by Raphael FRANCOIS (fraph@ibm.net) - - BEZIER_EXTENDS VER 1.0 - - - work as the cut/copy/paste named functions. - - allow to add/remove/replace bezier curves - - allow to modify the control/anchor points even if the selection is made - - allow to add/remove control/anchor points on a curve - - allow to update a previous saved curve - - - cannot operate on open or multiple curves simultaneously -*/ - -#define BEZIER_DRAW_CURVE 1 -#define BEZIER_DRAW_CURRENT 2 -#define BEZIER_DRAW_HANDLES 4 -#define BEZIER_DRAW_ALL (BEZIER_DRAW_CURVE | BEZIER_DRAW_HANDLES) - -#define BEZIER_WIDTH 8 -#define BEZIER_HALFWIDTH 4 - - -#define SUPERSAMPLE 3 -#define SUPERSAMPLE2 9 - - -/* the bezier select structures */ - -typedef gdouble BezierMatrix[4][4]; - -typedef struct -{ - CountCurves curve_count; /* Must be the first element */ - gdouble *stroke_points; - gint num_stroke_points; /* num of valid points */ - gint len_stroke_points; /* allocated length */ - gpointer next_curve; /* Next curve in list -- we draw all curves - * separately. - */ -} BezierRenderPnts; - -typedef struct -{ - CountCurves curve_count; /* Must be the first element */ - gboolean firstpnt; - gdouble curdist; - gdouble dist; - gdouble *gradient; - gint *x; - gint *y; - gdouble lastx; - gdouble lasty; - gboolean found; -} BezierDistance; - -typedef struct -{ - CountCurves curve_count; /* Must be the first element */ - gint x; - gint y; - gint halfwidth; - gint found; -} BezierCheckPnts; - - -/* local function prototypes */ - -static void bezier_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void bezier_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void bezier_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void bezier_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); -static void bezier_select_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void bezier_select_draw (Tool *tool); - -static void bezier_offset_point (BezierPoint *pt, - gint x, - gint y); -static gint bezier_check_point (BezierPoint *pt, - gint x, - gint y, - gint halfwidth); -static void bezier_draw_handles (BezierSelect *bezier_sel, - gboolean do_all); -static void bezier_draw_current (BezierSelect *bezier_sel); -static void bezier_draw_point (BezierSelect *bezier_sel, - BezierPoint *pt, - gboolean fill); -static void bezier_draw_line (BezierSelect *bezier_sel, - BezierPoint *pt1, - BezierPoint *pt2); -static void bezier_draw_segment (BezierSelect *bezier_sel, - BezierPoint *points, - gint subdivisions, - gint space, - BezierPointsFunc points_func, - gpointer data); -static void bezier_draw_segment_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data); -static void bezier_compose (BezierMatrix a, - BezierMatrix b, - BezierMatrix ab); - -static void bezier_convert (BezierSelect *bezier_sel, - GDisplay *gdisp, - gint subdivisions, - gboolean antialias); -static void bezier_convert_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data); -static void bezier_convert_line (GSList **scanlines, - gint x1, - gint y1, - gint x2, - gint y2); -static GSList * bezier_insert_in_list (GSList *list, - gint x); - -static gboolean test_add_point_on_segment (BezierSelect *bezier_sel, - BezierPoint *pt, - gint subdivisions, - gint space, - gint xpos, - gint ypos, - gint halfwidth); -static void bezier_to_sel_internal (BezierSelect *bezier_sel, - Tool *tool, - GDisplay *gdisp, - gint op, - gboolean replace); -static void bezier_stack_points_aux (GdkPoint *points, - gint start, - gint end, - gdouble error, - BezierRenderPnts *rpnts); -static void bezier_stack_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data); -static gboolean stroke_interpolatable (gint offx, - gint offy, - gint l_offx, - gint l_offy, - gdouble error); -static gint count_points_on_curve (BezierPoint *points); - - -/* private variables */ - -/* the bezier selection tool options */ -static SelectionOptions *bezier_options = NULL; - -/* local variables */ -static BezierMatrix basis = -{ - { -1, 3, -3, 1 }, - { 3, -6, 3, 0 }, - { -3, 3, 0, 0 }, - { 1, 0, 0, 0 }, -}; - -/* -static BezierMatrix basis = -{ - { -1/6.0, 3/6.0, -3/6.0, 1/6.0 }, - { 3/6.0, -6/6.0, 3/6.0, 0 }, - { -3/6.0, 0, 3/6.0, 0 }, - { 1/6.0, 4/6.0, 1, 0 }, -}; -*/ - -/* Global Static Variable to maintain informations about the "contexte" */ -static BezierSelect *curSel = NULL; -static Tool *curTool = NULL; -static GDisplay *curGdisp = NULL; -static DrawCore *curCore = NULL; -static gint ModeEdit = EXTEND_NEW; - - -/* functions */ - -static void -bezier_select_options_reset (void) -{ - selection_options_reset (bezier_options); -} - -Tool * -tools_new_bezier_select (void) -{ - Tool *tool; - BezierSelect *private; - - /* The tool options */ - if (! bezier_options) - { - bezier_options = - selection_options_new (BEZIER_SELECT, bezier_select_options_reset); - tools_register (BEZIER_SELECT, (ToolOptions *) bezier_options); - } - - tool = tools_new_tool (BEZIER_SELECT); - private = g_new0 (BezierSelect, 1); - - private->num_points = 0; - private->mask = NULL; - private->core = draw_core_new (bezier_select_draw); - bezier_select_reset (private); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->button_press_func = bezier_select_button_press; - tool->button_release_func = bezier_select_button_release; - tool->motion_func = bezier_select_motion; - tool->cursor_update_func = bezier_select_cursor_update; - tool->control_func = bezier_select_control; - - curCore = private->core; - curSel = private; - curTool = tool; - - paths_new_bezier_select_tool (); - - return tool; -} - -void -tools_free_bezier_select (Tool *tool) -{ - BezierSelect *bezier_sel; - - bezier_sel = tool->private; - - if (tool->state == ACTIVE) - draw_core_stop (bezier_sel->core, tool); - draw_core_free (bezier_sel->core); - - bezier_select_reset (bezier_sel); - - g_free (bezier_sel); -} - -gint -bezier_select_load (GDisplay *gdisp, - BezierPoint *pts, - gint num_pts, - gint closed) -{ - Tool *tool; - BezierSelect *bezier_sel; - - /* select the bezier tool */ - gimp_context_set_tool (gimp_context_get_user (), BEZIER_SELECT); - tool = active_tool; - tool->state = ACTIVE; - tool->gdisp = gdisp; - bezier_sel = (BezierSelect *) tool->private; - - bezier_sel->points = pts; - bezier_sel->last_point = pts->prev; - bezier_sel->num_points = num_pts; - bezier_sel->closed = closed; - bezier_sel->state = BEZIER_EDIT; - bezier_sel->draw = BEZIER_DRAW_ALL; - - bezier_convert (bezier_sel, tool->gdisp, SUBDIVIDE, FALSE); - - draw_core_start (bezier_sel->core, gdisp->canvas->window, tool); - - return 1; -} - -static BezierPoint * -valid_curve_segment (BezierPoint *points) -{ - /* Valid curve segment is made up of four points */ - if (points && - points->next && - points->next->next && - points->next->next->next) - { - return points; - } - - return NULL; -} - -static BezierPoint * -next_anchor (BezierPoint *points, - BezierPoint **next_curve) -{ - gint loop; - - *next_curve = NULL; - - if (!points) - return NULL; - - for (loop = 0; loop < 3; loop++) - { - points = points->next; - - if (!points) - return NULL; - - if (points->next_curve) - { - *next_curve = points->next_curve; - } - } - - return valid_curve_segment (points); -} - -void -bezier_draw_curve (BezierSelect *bezier_sel, - BezierPointsFunc func, - gint coord, - gpointer data) -{ - BezierPoint *points; - BezierPoint *start_pt; - BezierPoint *next_curve; - CountCurves *cnt = (CountCurves *) data; - gint point_counts = 0; - -/* printSel(bezier_sel); */ - - if (cnt) - cnt->count = 0; - - points = bezier_sel->points; - start_pt = bezier_sel->points; - - if (bezier_sel->num_points >= 4) - { - do - { - point_counts = count_points_on_curve (points); - - if (point_counts >= 4) - { - do - { - bezier_draw_segment (bezier_sel, points, - SUBDIVIDE, coord, - func, - data); - - points = next_anchor (points,&next_curve); - /* g_print ("next_anchor = %p\n",points); */ - } - while (points != start_pt && points); - - if (cnt) - cnt->count++; - - start_pt = next_curve; - points = next_curve; - } - else - { - break; /* must be last curve since only this one is allowed < 4 - * points. - */ - } - } - while (next_curve); - } -} - -void -bezier_select_reset (BezierSelect *bezier_sel) -{ - BezierPoint *points; - BezierPoint *start_pt; - BezierPoint *temp_pt; - BezierPoint *next_curve; - - if (bezier_sel->num_points > 0) - { - points = bezier_sel->points; - start_pt = bezier_sel->points; - - do - { - do - { - temp_pt = points; - next_curve = points->next_curve; - points = points->next; - - if (points != start_pt && next_curve) - { - g_warning ("Curve points out of sync"); - } - g_free (temp_pt); - } - while (points != start_pt && points); - - points = next_curve; - start_pt = next_curve; - } - while (next_curve); - } - - if (bezier_sel->mask) - gtk_object_unref (GTK_OBJECT (bezier_sel->mask)); - - bezier_sel->state = BEZIER_START; /* we are starting the curve */ - bezier_sel->draw = BEZIER_DRAW_ALL; /* draw everything by default */ - bezier_sel->closed = 0; /* the curve is initally open */ - bezier_sel->points = NULL; /* initially there are no points */ - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - bezier_sel->last_point = NULL; - bezier_sel->num_points = 0; /* intially there are no points */ - bezier_sel->mask = NULL; /* empty mask */ - bezier_sel->scanlines = NULL; -} - -void -bezier_select_free (BezierSelect *bezier_sel) -{ - bezier_select_reset (bezier_sel); - g_free (bezier_sel); -} - -/* Find the curve that points to this curve. This makes to_check point - * the start of a curve. - */ -static BezierPoint * -check_for_next_curve (BezierSelect *bezier_sel, - BezierPoint *to_check) -{ - BezierPoint *points = bezier_sel->points; - gint num_points = bezier_sel->num_points; - - while (points && num_points) - { - if (points->next_curve == to_check) - return points; - - if (points->next_curve) - points = points->next_curve; - else - points = points->next; - - num_points--; - } - - return NULL; -} - -static gint -count_points_on_curve (BezierPoint *points) -{ - BezierPoint *start = points; - gint count = 0; - - while (points && points->next != start) - { - points = points->next; - count++; - } - - return count; -} - -/* Find the start of the last open curve, if curve already closed - * this is an error.. - */ - -static BezierPoint * -find_start_open_curve (BezierSelect *bsel) -{ - BezierPoint *start_pnt = NULL; - BezierPoint *this_pnt = bsel->last_point; - - /* Could be one of the first points */ - if (! bsel->last_point) - return NULL; - - if (bsel->closed) - { - g_message (_("Bezier path already closed.")); - return NULL; - } - - /* Step backwards until the prev point is null. - * in this case this is the start of the open curve. - * The start_pnt stuff is to stop us going around forever. - * If we even have a closed curve then we are in seroius - * trouble. - */ - - while (this_pnt->prev && start_pnt != this_pnt) - { - if (!start_pnt) - start_pnt = this_pnt; - - this_pnt = this_pnt->prev; - } - - /* Must be an anchor to be the start */ - if (start_pnt == this_pnt || this_pnt->type != BEZIER_ANCHOR) - { - g_message (_("Corrupt curve")); - return NULL; - } - -/* g_print ("Returned start pnt of curve %p is %p\n",bsel->last_point,this_pnt); */ - return this_pnt; -} - -/* Delete a whole curve. Watch out for special cases. - * start_pnt must always be the start point if the curve to delete. - */ - -static void -delete_whole_curve (BezierSelect *bezier_sel, - BezierPoint *start_pnt) -{ - BezierPoint *tmppnt; - BezierPoint *next_curve = NULL; /* Next curve this one - * points at (if any) - */ - BezierPoint *prev_curve; /* Does a curve point to this one? */ - gint cnt_pnts = 0; /* Count how many pnts deleted */ - gint reset_last = FALSE; - - /* shift and del means delete whole curve */ - /* Three cases, this is first curve, middle curve - * or end curve. - */ - - /* Does this curve have another chained on the end? - * or is this curve pointed to another one? - */ - -/* g_print ("delete_whole_curve::\n"); */ - - tmppnt = start_pnt; - do - { - if (tmppnt->next_curve) - { - next_curve = tmppnt->next_curve; - break; - } - tmppnt = tmppnt->next; - } - while (tmppnt != start_pnt && tmppnt); - - prev_curve = check_for_next_curve (bezier_sel, start_pnt); - - /* First curve ?*/ - if (bezier_sel->points == start_pnt) - { - bezier_sel->points = next_curve; - } - else - { - /* better have a previous curve else how did we get here? */ - prev_curve->next_curve = next_curve; - } - - /* start_pnt points to the curve we should free .. ignoring the next_curve */ - - tmppnt = start_pnt; - do - { - BezierPoint *fpnt; - - fpnt = tmppnt; - tmppnt = tmppnt->next; - - if (fpnt == bezier_sel->last_point) - reset_last = TRUE; - - g_free (fpnt); - cnt_pnts++; - } - while (tmppnt != start_pnt && tmppnt); - - bezier_sel->num_points -= cnt_pnts; - - /* if deleted curve was unclosed then must have been the last curve - * and thus this curve becomes closed. - */ - if (!tmppnt && bezier_sel->num_points > 0) - { - bezier_sel->closed = 1; - bezier_sel->state = BEZIER_EDIT; - } - - if (bezier_sel->num_points <= 0) - { - bezier_select_reset(bezier_sel); - } - - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - - /* The last point could have been on this curve as well... */ - if (reset_last) - { - BezierPoint *points = bezier_sel->points; - BezierPoint *l_pnt = NULL; - gint num_points = bezier_sel->num_points; - - while (points && num_points) - { - l_pnt = points; - - if(points->next_curve) - points = points->next_curve; - else - points = points->next; - - num_points--; - } - - bezier_sel->last_point = l_pnt; - } -} - -static gboolean -bezier_edit_point_on_curve (gint x, - gint y, - gint halfwidth, - GDisplay *gdisp, - BezierSelect *bezier_sel, - Tool *tool, - GdkEventButton *bevent) -{ - gboolean grab_pointer = FALSE; - BezierPoint *next_curve; - BezierPoint *points = bezier_sel->points; - BezierPoint *start_pt = bezier_sel->points; - BezierPoint *last_curve = NULL; - gint point_counts = 0; - - /* find if the button press occurred on a point */ - do - { - point_counts = count_points_on_curve (points); - - do - { - if (bezier_check_point (points, x, y, halfwidth)) - { - BezierPoint *finded=points; - BezierPoint *start_op; - BezierPoint *end_op; - - if (ModeEdit== EXTEND_REMOVE) - { - if ((bevent->state & GDK_SHIFT_MASK) || (point_counts <= 7)) - { - /* Case 1: GDK_SHIFT_MASK - The user explicitly wishes - the present curve to go away. - - Case 2: The current implementation cannot cope with - less than 7 points ie: 2 anchors points and - 4 controls: the minimal closed curve. - Since the user wishes less than this implementation - minimum, we take this for an implicit wish that - the entire curve go away. G'bye dear curve. - */ - - delete_whole_curve (bezier_sel,start_pt); - - return TRUE; - } - else if (!finded->prev || !finded->prev->prev) - { - /* This is the first point on the curve */ - /* Clear current anchor and control */ - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - /* Where are we? reset to first point... */ - /*if(last_curve == NULL)*/ - if (start_pt == bezier_sel->points) - { - finded = bezier_sel->points; - bezier_sel->points = finded->next->next->next; - bezier_sel->points->prev = NULL; - } - else - { - finded = last_curve->next_curve; - last_curve->next_curve = finded->next->next->next; - last_curve->next_curve->prev = NULL; - } - - bezier_sel->num_points -= 3; - - g_free (finded->next->next); - g_free (finded->next); - g_free (finded); - } - else if (!bezier_sel->closed && - (finded == bezier_sel->last_point || - finded == bezier_sel->last_point->prev || - finded == bezier_sel->last_point->prev->prev)) - { - /* This is the last point on the curve */ - /* Clear current anchor and control */ - /* Where are we? reset to last point... */ - finded = bezier_sel->last_point->prev; - bezier_sel->last_point = finded->prev->prev; - bezier_sel->last_point->next = NULL; - - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - - bezier_sel->num_points -= 3; - - g_free (finded->prev); - g_free (finded->next); - g_free (finded); - } - else - { - if (finded->type == BEZIER_CONTROL) - { - if (finded->next->type == BEZIER_CONTROL) - finded = finded->prev; - else - finded = finded->next; - } - - start_op = finded->prev->prev; - end_op = finded->next->next; - - /* we can use next_curve here since we are going to - * drop out the bottom anyways. - */ - next_curve = check_for_next_curve (bezier_sel,finded); - - if (next_curve) - { - /* Deleteing first point of next curve*/ - next_curve->next_curve = finded->prev->prev->prev; - } - else /* Can't be both first and a next curve!*/ - { - if (bezier_sel->points == finded) - { - /* g_print ("Deleting first point %p\n",finded); */ - bezier_sel->points = finded->prev->prev->prev; - } - } - - /* Make sure the chain of curves is preserved */ - if (finded->prev->next_curve) - { - /* g_print ("Moving curve on next_curve %p\n",finded->prev->next_curve); */ - /* last point on closed multi-path */ - finded->prev->prev->prev->prev->next_curve = finded->prev->next_curve; - } - - if (bezier_sel->last_point == finded->prev) - { - /* g_print ("Deleting last point %p\n",finded->prev); */ - bezier_sel->last_point = bezier_sel->last_point->prev->prev->prev; - } - - start_op->next = end_op; - end_op->prev = start_op; - -/* if ( (bezier_sel->last_point == finded) || */ -/* (bezier_sel->last_point == finded->next) || */ -/* (bezier_sel->last_point == finded->prev)) */ -/* { */ -/* bezier_sel->last_point = start_op->prev->prev; */ -/* bezier_sel->points = start_op->prev; */ -/* } */ - - bezier_sel->num_points -= 3; - - g_free (finded->prev); - g_free (finded->next); - g_free (finded); - - /* Clear current anchor and control */ - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - } - } - else - { - /* set the current anchor and control points */ - switch (points->type) - { - case BEZIER_ANCHOR: - bezier_sel->cur_anchor = points; - bezier_sel->cur_control = bezier_sel->cur_anchor->next; - break; - case BEZIER_CONTROL: - bezier_sel->cur_control = points; - if (bezier_sel->cur_control->next && - bezier_sel->cur_control->next->type == BEZIER_ANCHOR) - bezier_sel->cur_anchor = bezier_sel->cur_control->next; - else - bezier_sel->cur_anchor = bezier_sel->cur_control->prev; - break; - } - } - - return TRUE; - } - - next_curve = points->next_curve; - if (next_curve) - last_curve = points; - points = points->next; - } - while (points != start_pt && points); - - start_pt = next_curve; - points = next_curve; - } - while (next_curve); - - return grab_pointer; -} - -static gboolean -bezier_add_point_on_segment (gint x, - gint y, - gint halfwidth, - GDisplay *gdisp, - BezierSelect *bezier_sel, - Tool *tool) -{ - BezierPoint *points = bezier_sel->points; - BezierPoint *start_pt = bezier_sel->points; - BezierPoint *next_curve; - - do - { - do - { - if (test_add_point_on_segment (bezier_sel, - points, - SUBDIVIDE, - IMAGE_COORDS, - x, y, - halfwidth)) - { - return TRUE; - } - - points = points->next; - - if (!points) - return FALSE; - - points = points->next; - - if (!points) - return FALSE; - - next_curve = points->next_curve; - points = points->next; - } - while (points != start_pt && points); - - start_pt = next_curve; - points = next_curve; - } - while (next_curve); - - return FALSE; -} - - -static void -bezier_start_new_segment (BezierSelect *bezier_sel, - gint x, - gint y) -{ - /* Must be closed to do this! */ - if (!bezier_sel->closed) - return; - - bezier_sel->closed = 0; /* End is no longer closed !*/ - bezier_sel->state = BEZIER_ADD; - - bezier_add_point (bezier_sel, BEZIER_MOVE, (gdouble) x, (gdouble) y); - bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble) x, (gdouble) y); -} - -static void -bezier_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - BezierSelect *bezier_sel; - BezierPoint *points; - BezierPoint *start_pt; - BezierPoint *curve_start; - gboolean grab_pointer; - gint op; - gint x, y; - gint halfwidth, dummy; - - tool->drawable = gimp_image_active_drawable (gdisp->gimage); - - bezier_sel = tool->private; - grab_pointer = FALSE; - - /* If the tool was being used in another image...reset it */ - if (tool->state == ACTIVE && gdisp != tool->gdisp) - { - draw_core_stop (bezier_sel->core, tool); - bezier_select_reset (bezier_sel); - } - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0); - - /* get halfwidth in image coord */ - gdisplay_untransform_coords (gdisp, bevent->x + BEZIER_HALFWIDTH, 0, - &halfwidth, &dummy, TRUE, 0); - halfwidth -= x; - - curTool = active_tool; - curSel = curTool->private; - curGdisp = (GDisplay *) gdisp; - active_tool->gdisp = gdisp; - curCore = bezier_sel->core; - - switch (bezier_sel->state) - { - case BEZIER_START: - if (ModeEdit != EXTEND_NEW) - break; - - grab_pointer = TRUE; - tool->state = ACTIVE; - tool->gdisp = gdisp; - -/* if (bevent->state & GDK_MOD1_MASK) */ -/* { */ -/* init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE); */ -/* break; */ -/* } */ -/* else if (!(bevent->state & GDK_SHIFT_MASK) && !(bevent->state & GDK_CONTROL_MASK)) */ -/* if (! (layer_is_floating_sel (gimp_image_get_active_layer (gdisp->gimage))) && */ -/* gdisplay_mask_value (gdisp, bevent->x, bevent->y) > HALF_WAY) */ -/* { */ -/* init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE); */ -/* break; */ -/* } */ - - bezier_sel->state = BEZIER_ADD; - /*bezier_sel->draw = BEZIER_DRAW_CURVE; | BEZIER_DRAW_HANDLES;*/ - bezier_sel->draw = BEZIER_DRAW_CURRENT; - - bezier_add_point (bezier_sel, BEZIER_ANCHOR, (gdouble)x, (gdouble)y); - bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y); - - draw_core_start (bezier_sel->core, gdisp->canvas->window, tool); - break; - - case BEZIER_ADD: - grab_pointer = TRUE; - - if (ModeEdit == EXTEND_EDIT) - { - /* erase the handles */ - if(bezier_sel->closed) - bezier_sel->draw = BEZIER_DRAW_ALL; - else - bezier_sel->draw = BEZIER_DRAW_CURVE; - draw_core_pause (bezier_sel->core, tool); - /* unset the current anchor and control */ - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - - grab_pointer = bezier_edit_point_on_curve (x, y, halfwidth, - gdisp, bezier_sel, - tool, bevent); - - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_resume (bezier_sel->core, tool); - - if (grab_pointer) - { - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - } - else - { - paths_dialog_set_default_op (); - /* recursive call */ - bezier_select_button_press (tool, bevent, gdisp); - } - return; - } - - if (ModeEdit == EXTEND_REMOVE) - { -/* if(bezier_sel->num_points < 6) */ -/* return; */ - - /* erase the handles */ - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_pause (bezier_sel->core, tool); - /* unset the current anchor and control */ - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - - /*kkk*/ - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_resume (bezier_sel->core, tool); - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_pause (bezier_sel->core, tool); - /*kkk*/ - - grab_pointer = bezier_edit_point_on_curve (x, y, halfwidth, - gdisp, bezier_sel, - tool, bevent); - - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_resume (bezier_sel->core, tool); - - if (bezier_sel->num_points == 0) - { - draw_core_pause (bezier_sel->core, tool); - paths_dialog_set_default_op (); - } - - if (!grab_pointer) - { - paths_dialog_set_default_op (); - /* recursive call */ - bezier_select_button_press (tool, bevent, gdisp); - } - return; - } - - if (ModeEdit == EXTEND_ADD) - { - if (bezier_sel->num_points < 5) - return; - - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_pause (bezier_sel->core, tool); - - grab_pointer = bezier_add_point_on_segment (x, y, halfwidth, - gdisp, bezier_sel, tool); - - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_resume (bezier_sel->core, tool); - if (grab_pointer) - { - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - } - else - { - paths_dialog_set_default_op (); - /* recursive call */ - bezier_select_button_press (tool, bevent, gdisp); - } - return; - } - - if (bezier_sel->cur_anchor) - { - if (bezier_check_point (bezier_sel->cur_anchor, x, y, halfwidth)) - { - break; - } - - if (bezier_sel->cur_anchor->next && - bezier_check_point (bezier_sel->cur_anchor->next, x, y, halfwidth)) - { - bezier_sel->cur_control = bezier_sel->cur_anchor->next; - break; - } - - if (bezier_sel->cur_anchor->prev && - bezier_check_point (bezier_sel->cur_anchor->prev, x, y, halfwidth)) - { - bezier_sel->cur_control = bezier_sel->cur_anchor->prev; - break; - } - } - - curve_start = find_start_open_curve(bezier_sel); - - if (curve_start && bezier_check_point (curve_start, x, y, halfwidth)) - { - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_pause (bezier_sel->core, tool); - - bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y); - bezier_sel->last_point->next = curve_start; - curve_start->prev = bezier_sel->last_point; - bezier_sel->cur_anchor = curve_start; - bezier_sel->cur_control = curve_start->next; - - bezier_sel->closed = 1; - bezier_sel->state = BEZIER_EDIT; - bezier_sel->draw = BEZIER_DRAW_ALL; - - draw_core_resume (bezier_sel->core, tool); - } - else - { - if(bezier_sel->cur_anchor) - bezier_sel->cur_anchor->pointflags = 1; - bezier_sel->draw = BEZIER_DRAW_HANDLES; - draw_core_pause (bezier_sel->core, tool); - - bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y); - bezier_add_point (bezier_sel, BEZIER_ANCHOR, (gdouble)x, (gdouble)y); - bezier_add_point (bezier_sel, BEZIER_CONTROL, (gdouble)x, (gdouble)y); - - bezier_sel->draw = BEZIER_DRAW_CURRENT | BEZIER_DRAW_HANDLES; - - draw_core_resume (bezier_sel->core, tool); - } - break; - - case BEZIER_EDIT: - if (!bezier_sel->closed) - gimp_fatal_error ("bezier_select_button_press(): Tried to edit " - "on open bezier curve in edit selection"); - - /* erase the handles */ - bezier_sel->draw = BEZIER_DRAW_ALL; - draw_core_pause (bezier_sel->core, tool); - - /* unset the current anchor and control */ - bezier_sel->cur_anchor = NULL; - bezier_sel->cur_control = NULL; - - points = bezier_sel->points; - start_pt = bezier_sel->points; - - if (ModeEdit == EXTEND_ADD) - { - if (bezier_sel->closed) - { - grab_pointer = bezier_add_point_on_segment (x, y, halfwidth, - gdisp, bezier_sel, - tool); - } - } - else - { - grab_pointer = bezier_edit_point_on_curve (x, y, halfwidth, - gdisp, bezier_sel, - tool, bevent); - - if (grab_pointer && bezier_sel->num_points == 0) - { - draw_core_pause (bezier_sel->core, tool); - paths_dialog_set_default_op (); - } - } - - if (!grab_pointer && channel_value (bezier_sel->mask, x, y)) - { - gboolean replace = FALSE; - - if ((bevent->state & GDK_SHIFT_MASK) && - !(bevent->state & GDK_CONTROL_MASK)) - op = CHANNEL_OP_ADD; - else if ((bevent->state & GDK_CONTROL_MASK) && - !(bevent->state & GDK_SHIFT_MASK)) - op = CHANNEL_OP_SUB; - else if ((bevent->state & GDK_CONTROL_MASK) && - (bevent->state & GDK_SHIFT_MASK)) - op = CHANNEL_OP_INTERSECT; - else - { - op = CHANNEL_OP_ADD; - replace = TRUE; - } - - bezier_to_sel_internal (bezier_sel, tool, gdisp, op, replace); - draw_core_resume (bezier_sel->core, tool); - } - else - { - /* draw the handles */ - if (!grab_pointer) - { - paths_dialog_set_default_op (); - bezier_start_new_segment (bezier_sel, x, y); - } - bezier_sel->draw = BEZIER_DRAW_ALL; - - draw_core_resume (bezier_sel->core, tool); - } - break; - } - - if (grab_pointer) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - /* Don't bother doing this if we don't have any points */ - if (bezier_sel->num_points > 0) - paths_first_button_press(bezier_sel, gdisp); -} - -static void -bezier_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - BezierSelect *bezier_sel; - - gdisp = tool->gdisp; - - bezier_sel = tool->private; - bezier_sel->state &= ~(BEZIER_DRAG); - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - if (bezier_sel->closed) - bezier_convert (bezier_sel, tool->gdisp, SUBDIVIDE, FALSE); - - /* Here ?*/ - paths_newpoint_current (bezier_sel,gdisp); -} - - -/* unused -static void -bez_copy_points (BezierSelect *tobez, - BezierSelect *frombez) -{ - BezierPoint *pts; - gint i; - BezierPoint *bpnt = NULL; - gboolean need_move = FALSE; - - pts = (BezierPoint *) frombez->points; - - for (i = 0; i < frombez->num_points; i++) - { - if (need_move) - { - bezier_add_point (tobez, BEZIER_MOVE, pts->x, pts->y); - need_move = FALSE; - } - else - { - bezier_add_point (tobez, pts->type, pts->x, pts->y); - } - - if (pts == frombez->cur_anchor) - tobez->cur_anchor = tobez->last_point; - else if (pts == frombez->cur_control) - tobez->cur_control = tobez->last_point; - - if (bpnt == NULL) - bpnt = tobez->last_point; - - if (pts->next_curve) - { - tobez->last_point->next = bpnt; - bpnt->prev = tobez->last_point; - bpnt = NULL; - need_move = TRUE; - pts = pts->next_curve; - } - else - { - pts = pts->next; - } - } - - if (frombez->closed) - { - tobez->last_point->next = bpnt; - bpnt->prev = tobez->last_point; - tobez->closed = TRUE; - } -} -*/ - -static void -bezier_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - static gint lastx, lasty; - - BezierSelect *bezier_sel; - BezierPoint *anchor; - BezierPoint *opposite_control; - gint offsetx; - gint offsety; - gint x, y; - - if (tool->state != ACTIVE) - return; - - bezier_sel = tool->private; - - if (!bezier_sel->cur_anchor || !bezier_sel->cur_control) - return; - - if (mevent->state & GDK_MOD1_MASK) - { - bezier_sel->draw = BEZIER_DRAW_ALL; - } - else - { - bezier_sel->draw = BEZIER_DRAW_CURRENT | BEZIER_DRAW_HANDLES; - } - - draw_core_pause (bezier_sel->core, tool); - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - /* If this is the first point then change the state and "remember" the point. - */ - if (!(bezier_sel->state & BEZIER_DRAG)) - { - bezier_sel->state |= BEZIER_DRAG; - lastx = x; - lasty = y; - } - - /* The Alt key is down... Move all the points of the bezier curve */ - - if (mevent->state & GDK_MOD1_MASK) - { - BezierPoint *tmp = bezier_sel->points; - gint num_points = bezier_sel->num_points; - - offsetx = x - lastx; - offsety = y - lasty; - - if (mevent->state & GDK_SHIFT_MASK) - { - /* Only move this curve */ - BezierPoint *start_pt = bezier_sel->cur_anchor; - - /* g_print ("moving only one curve\n"); */ - - tmp = start_pt; - - do - { - bezier_offset_point (tmp, offsetx, offsety); - tmp = tmp->next; - } - while (tmp != start_pt && tmp); - - /* Check if need to go backwards because curve is open */ - if (!tmp && bezier_sel->cur_anchor->prev) - { - BezierPoint *start_pt = bezier_sel->cur_anchor->prev; - - tmp = start_pt; - - do - { - bezier_offset_point (tmp, offsetx, offsety); - tmp = tmp->prev; - } - while (tmp != start_pt && tmp); - } - } - else - { - while (tmp && num_points) - { - bezier_offset_point (tmp, offsetx, offsety); - - if(tmp->next_curve) - tmp = tmp->next_curve; - else - tmp = tmp->next; - - num_points--; - } - } - } - else if (mevent->state & GDK_CONTROL_MASK) - { - /* the control key is down ... move the current anchor point */ - /* we must also move the neighboring control points appropriately */ - - offsetx = x - lastx; - offsety = y - lasty; - - bezier_offset_point (bezier_sel->cur_anchor, offsetx, offsety); - bezier_offset_point (bezier_sel->cur_anchor->next, offsetx, offsety); - bezier_offset_point (bezier_sel->cur_anchor->prev, offsetx, offsety); - } - else - { - /* the control key is not down ... we move the current control point */ - - offsetx = x - bezier_sel->cur_control->x; - offsety = y - bezier_sel->cur_control->y; - - bezier_offset_point (bezier_sel->cur_control, offsetx, offsety); - - /* if the shift key is not down then we align the opposite control */ - /* point...ie the opposite control point acts like a mirror of the */ - /* current control point */ - - if (!(mevent->state & GDK_SHIFT_MASK)) - { - anchor = NULL; - opposite_control = NULL; - - if (bezier_sel->cur_control->next) - { - if (bezier_sel->cur_control->next->type == BEZIER_ANCHOR) - { - anchor = bezier_sel->cur_control->next; - opposite_control = anchor->next; - } - } - if (bezier_sel->cur_control->prev) - { - if (bezier_sel->cur_control->prev->type == BEZIER_ANCHOR) - { - anchor = bezier_sel->cur_control->prev; - opposite_control = anchor->prev; - } - } - - if (!anchor) - gimp_fatal_error ("bezier_select_motion(): Encountered orphaned " - "bezier control point"); - - if (opposite_control) - { - offsetx = bezier_sel->cur_control->x - anchor->x; - offsety = bezier_sel->cur_control->y - anchor->y; - - opposite_control->x = anchor->x - offsetx; - opposite_control->y = anchor->y - offsety; - } - } - } - - /* As we're moving all the control points of the curve, - we have to redraw all !!! - */ - - if ( mevent->state & GDK_MOD1_MASK) - bezier_sel->draw = BEZIER_DRAW_ALL; - else - bezier_sel->draw = BEZIER_DRAW_CURRENT | BEZIER_DRAW_HANDLES; - - draw_core_resume (bezier_sel->core, tool); - - lastx = x; - lasty = y; -} - -/* returns 0 if not on control point, else BEZIER_ANCHOR or BEZIER_CONTROL */ -static gint -bezier_on_control_point (GDisplay *gdisp, - BezierSelect *bezier_sel, - gint x, - gint y, - gint halfwidth) -{ - BezierPoint *points; - gint num_points; - - /* transform the points from image space to screen space */ - points = bezier_sel->points; - num_points = bezier_sel->num_points; - - while (points && num_points) - { - if (bezier_check_point (points, x, y, halfwidth)) - return points->type; - - if(points->next_curve) - points = points->next_curve; - else - points = points->next; - - num_points--; - } - - return FALSE; -} - -static void -bezier_check_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data) -{ - BezierCheckPnts *chkpnts = data; - gint halfwidth = chkpnts->halfwidth; - gint loop; - gint l, r, t, b; - - /* Quick exit if already found */ - - if (chkpnts->found) - return; - - for (loop = 0 ; loop < n_points; loop++) - { - l = points[loop].x - halfwidth; - r = points[loop].x + halfwidth; - t = points[loop].y - halfwidth; - b = points[loop].y + halfwidth; - -/* g_print ("x,y = [%d,%d] halfwidth %d l,r,t,d [%d,%d,%d,%d]\n", */ -/* points[loop].x, */ -/* points[loop].y, */ -/* halfwidth, */ -/* l,r,t,b); */ - - if ((chkpnts->x >= l) && - (chkpnts->x <= r) && - (chkpnts->y >= t) && - (chkpnts->y <= b)) - { - chkpnts->found = TRUE; - } - } -} - -static gboolean -points_in_box (BezierPoint *points, - gint x, - gint y) -{ - /* below code adapted from Wm. Randolph Franklin - */ - gint i, j; - gint c = 0; - gdouble yp[4]; - gdouble xp[4]; - - for (i = 0; i < 4; i++) - { - xp[i] = points->x; - yp[i] = points->y; - points = points->next; - } - - /* Check if straight line ..below don't work if it is! */ - if((xp[0] == xp[1] && yp[0] == yp[1]) || - (xp[2] == xp[3] && yp[0] == yp[1])) - return TRUE; - - for (i = 0, j = 3; i < 4; j = i++) - { - if ((((yp[i]<=y) && (ycount = 0; - - points = bezier_sel->points; - start_pt = bezier_sel->points; - - if (bezier_sel->num_points >= 4) - { - do - { - point_counts = count_points_on_curve(points); - if (point_counts >= 4) - { - do - { - if (points_in_box (points, x, y)) - { - bezier_draw_segment (bezier_sel, points, - SUBDIVIDE, IMAGE_COORDS, - bezier_check_points, - &chkpnts); - } - points = next_anchor (points, &next_curve); - /* g_print ("next_anchor = %p\n",points); */ - } - while (points != start_pt && points); - if (cnt) - cnt->count++; - start_pt = next_curve; - points = next_curve; - } - else - break; /* must be last curve since only this one is allowed < 4 - * points. - */ - } - while (next_curve); - } - - return chkpnts.found; -} - -static void -bezier_select_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - BezierSelect *bezier_sel; - gboolean on_curve; - gboolean on_control_pnt; - gboolean in_selection_area; - gint halfwidth, dummy; - gint x, y; - - bezier_sel = tool->private; - - if (gdisp != tool->gdisp || bezier_sel->core->draw_state == INVISIBLE) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); - return; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - /* get halfwidth in image coord */ - gdisplay_untransform_coords (gdisp, mevent->x + BEZIER_HALFWIDTH, 0, - &halfwidth, &dummy, TRUE, 0); - halfwidth -= x; - - on_control_pnt = bezier_on_control_point (gdisp, bezier_sel, x, y, halfwidth); - - on_curve = bezier_point_on_curve (gdisp, bezier_sel, x, y, halfwidth); - - if (bezier_sel->mask && bezier_sel->closed && - channel_value(bezier_sel->mask, x, y) && - !on_control_pnt && - (!on_curve || ModeEdit != EXTEND_ADD)) - { - in_selection_area = TRUE; - - if ((mevent->state & GDK_SHIFT_MASK) && - !(mevent->state & GDK_CONTROL_MASK)) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_PLUS, - FALSE); - } - else if ((mevent->state & GDK_CONTROL_MASK) && - !(mevent->state & GDK_SHIFT_MASK)) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_MINUS, - FALSE); - } - else if ((mevent->state & GDK_CONTROL_MASK) && - (mevent->state & GDK_SHIFT_MASK)) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_INTERSECT, - FALSE); - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); - } - return; - } - - if (mevent->state & GDK_MOD1_MASK) - { - /* Moving curve */ - if (mevent->state & GDK_SHIFT_MASK) - { - /* moving on 1 curve */ - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_MOVE, - FALSE); - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_MOVE, - FALSE); - } - } - else - { - switch (ModeEdit) - { - case EXTEND_NEW: - if (on_control_pnt && bezier_sel->closed) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_CONTROL, - FALSE); -/* g_print ("add to curve cursor\n"); */ - } - else if (on_curve) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); -/* g_print ("edit control point cursor\n"); */ - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); - } - break; - - case EXTEND_ADD: - if (on_curve) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_PLUS, - FALSE); -/* g_print ("add to curve cursor\n"); */ - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); -/* g_print ("default no action cursor\n"); */ - } - break; - - case EXTEND_EDIT: - if (on_control_pnt) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_CONTROL, - FALSE); -/* g_print ("edit control point cursor\n"); */ - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); -/* g_print ("default no action cursor\n"); */ - } - break; - - case EXTEND_REMOVE: - if (on_control_pnt && mevent->state & GDK_SHIFT_MASK) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_MINUS, - FALSE); -/* g_print ("delete whole curve cursor\n"); */ - } - else if (on_control_pnt) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_MINUS, - FALSE); -/* g_print ("remove point cursor\n"); */ - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); -/* g_print ("default no action cursor\n"); */ - } - break; - - default: - g_print ("In default\n"); - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BEZIER_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); - break; - } - } -} - -static void -bezier_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - BezierSelect * bezier_sel; - - bezier_sel = tool->private; - - switch (action) - { - case PAUSE : - draw_core_pause (bezier_sel->core, tool); - break; - - case RESUME : - draw_core_resume (bezier_sel->core, tool); - break; - - case HALT : - draw_core_stop (bezier_sel->core, tool); - bezier_select_reset (bezier_sel); - break; - - default: - break; - } -} - -void -bezier_draw (GDisplay *gdisp, - BezierSelect *bezier_sel) -{ - BezierPoint *points; - gint num_points; - gint draw_curve; - gint draw_handles; - gint draw_current; - - if (!bezier_sel->draw) - return; - - draw_curve = bezier_sel->draw & BEZIER_DRAW_CURVE; - draw_current = bezier_sel->draw & BEZIER_DRAW_CURRENT; - draw_handles = bezier_sel->draw & BEZIER_DRAW_HANDLES; - - /* reset to the default drawing state of drawing the curve and handles */ - bezier_sel->draw = BEZIER_DRAW_ALL; - - /* transform the points from image space to screen space */ - points = bezier_sel->points; - num_points = bezier_sel->num_points; - - while (points && num_points) - { - gdisplay_transform_coords (gdisp, points->x, points->y, - &points->sx, &points->sy, 0); - - if (points->next_curve) - points = points->next_curve; - else - points = points->next; - - num_points--; - } - - if (draw_curve) - { - bezier_draw_curve (bezier_sel, bezier_draw_segment_points, - SCREEN_COORDS, NULL); - bezier_draw_handles (bezier_sel, TRUE); - } - else if (draw_current) - { - bezier_draw_current (bezier_sel); - bezier_draw_handles (bezier_sel, FALSE); - } - else if (draw_handles) - { - bezier_draw_handles (bezier_sel, FALSE); - } - -} - -static void -bezier_select_draw (Tool *tool) -{ - GDisplay *gdisp; - BezierSelect *bezier_sel; - - gdisp = tool->gdisp; - bezier_sel = tool->private; - - bezier_draw (gdisp, bezier_sel); -} - - - -void -bezier_add_point (BezierSelect *bezier_sel, - gint type, - gdouble x, - gdouble y) -{ - BezierPoint *newpt; - - newpt = g_new0 (BezierPoint,1); - - newpt->type = type; - newpt->x = x; - newpt->y = y; - newpt->next = NULL; - newpt->prev = NULL; - newpt->next_curve = NULL; - - if (type == BEZIER_MOVE && - bezier_sel->last_point) - { -/* g_print ("Adding move point\n"); */ - newpt->type = BEZIER_ANCHOR; - bezier_sel->last_point->next_curve = newpt; - bezier_sel->last_point = newpt; - bezier_sel->cur_anchor = newpt; - } - else - { - if(type == BEZIER_MOVE) - { - newpt->type = BEZIER_ANCHOR; - /* g_print ("Adding MOVE point to null curve\n"); */ - } - - if (bezier_sel->last_point) - { - bezier_sel->last_point->next = newpt; - newpt->prev = bezier_sel->last_point; - bezier_sel->last_point = newpt; - } - else - { - bezier_sel->points = newpt; - bezier_sel->last_point = newpt; - } - - switch (type) - { - case BEZIER_ANCHOR: - bezier_sel->cur_anchor = newpt; - break; - case BEZIER_CONTROL: - bezier_sel->cur_control = newpt; - break; - } - } - - bezier_sel->num_points += 1; -} - -static void -bezier_offset_point (BezierPoint *pt, - gint x, - gint y) -{ - if (pt) - { - pt->x += x; - pt->y += y; - } -} - -static int -bezier_check_point (BezierPoint *pt, - gint x, - gint y, - gint halfwidth) -{ - gint l, r, t, b; - - if (pt) - { - l = pt->x - halfwidth; - r = pt->x + halfwidth; - t = pt->y - halfwidth; - b = pt->y + halfwidth; - - return ((x >= l) && (x <= r) && (y >= t) && (y <= b)); - } - - return 0; -} - - -static void -bezier_draw_handles (BezierSelect *bezier_sel, - gboolean do_all) -{ - BezierPoint *points; - gint num_points; - - points = bezier_sel->points; - num_points = bezier_sel->num_points; - - if (num_points <= 0) - return; - - while (num_points && num_points > 0) - { - if (points == bezier_sel->cur_anchor) - { -/* g_print ("bezier_draw_handles:: found cur_anchor %p\n",points); */ - bezier_draw_point (bezier_sel, points, FALSE); - bezier_draw_point (bezier_sel, points->next, FALSE); - bezier_draw_point (bezier_sel, points->prev, FALSE); - bezier_draw_line (bezier_sel, points, points->next); - bezier_draw_line (bezier_sel, points, points->prev); - } - else - { - /* g_print ("bezier_draw_handles:: not found cur_anchor %p\n",points); */ - if (do_all || points->pointflags == 1) - { - bezier_draw_point (bezier_sel, points, TRUE); - points->pointflags = 0; - } - } - - if (points) - { - if (points->next_curve) - points = points->next_curve; - else - points = points->next; - } - - if (points) - { - if (points->next_curve) - points = points->next_curve; - else - points = points->next; - } - - if (points) - { - if (points->next_curve) - points = points->next_curve; - else - points = points->next; - } - - num_points -= 3; - } -} - -static void -bezier_draw_current (BezierSelect *bezier_sel) -{ - BezierPoint *points; - - points = bezier_sel->cur_anchor; - - if (points) points = points->prev; - if (points) points = points->prev; - if (points) points = points->prev; - - if (points) - bezier_draw_segment (bezier_sel, points, - SUBDIVIDE, SCREEN_COORDS, - bezier_draw_segment_points, - NULL); - - if (points != bezier_sel->cur_anchor) - { - points = bezier_sel->cur_anchor; - - if (points) points = points->next; - if (points) points = points->next; - if (points) points = points->next; - - if (points) - bezier_draw_segment (bezier_sel, bezier_sel->cur_anchor, - SUBDIVIDE, SCREEN_COORDS, - bezier_draw_segment_points, - NULL); - } -} - -static void -bezier_draw_point (BezierSelect *bezier_sel, - BezierPoint *pt, - gboolean fill) -{ - if (pt) - { - switch (pt->type) - { - case BEZIER_ANCHOR: - if (fill) - { - gdk_draw_arc (bezier_sel->core->win, bezier_sel->core->gc, - TRUE, - pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH, - BEZIER_WIDTH, BEZIER_WIDTH, 0, 23040); - } - else - { - gdk_draw_arc (bezier_sel->core->win, bezier_sel->core->gc, - FALSE, - pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH, - BEZIER_WIDTH, BEZIER_WIDTH, 0, 23040); - } - break; - - case BEZIER_CONTROL: - if (fill) - { - gdk_draw_rectangle (bezier_sel->core->win, bezier_sel->core->gc, - TRUE, - pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH, - BEZIER_WIDTH, BEZIER_WIDTH); - } - else - { - gdk_draw_rectangle (bezier_sel->core->win, bezier_sel->core->gc, - FALSE, - pt->sx - BEZIER_HALFWIDTH, pt->sy - BEZIER_HALFWIDTH, - BEZIER_WIDTH, BEZIER_WIDTH); - } - break; - } - } -} - -static void -bezier_draw_line (BezierSelect *bezier_sel, - BezierPoint *pt1, - BezierPoint *pt2) -{ - if (pt1 && pt2) - { - gdk_draw_line (bezier_sel->core->win, - bezier_sel->core->gc, - pt1->sx, pt1->sy, pt2->sx, pt2->sy); - } -} - -static void -bezier_draw_segment (BezierSelect *bezier_sel, - BezierPoint *points, - gint subdivisions, - gint space, - BezierPointsFunc points_func, - gpointer data) -{ - static GdkPoint gdk_points[256]; - static gint n_points = 256; - - BezierMatrix geometry; - BezierMatrix tmp1, tmp2; - BezierMatrix deltas; - gdouble x, dx, dx2, dx3; - gdouble y, dy, dy2, dy3; - gdouble d, d2, d3; - gint lastx, lasty; - gint newx, newy; - gint index; - gint i; - - /* construct the geometry matrix from the segment */ - /* assumes that a valid segment containing 4 points is passed in */ - - for (i = 0; i < 4; i++) - { - if (!points) - gimp_fatal_error ("bezier_draw_segment(): Bad bezier segment"); - - switch (space) - { - case IMAGE_COORDS: - geometry[i][0] = points->x; - geometry[i][1] = points->y; - break; - case AA_IMAGE_COORDS: - geometry[i][0] = (points->x * SUPERSAMPLE); - geometry[i][1] = (points->y * SUPERSAMPLE); - break; - case SCREEN_COORDS: - geometry[i][0] = points->sx; - geometry[i][1] = points->sy; - break; - default: - gimp_fatal_error ("bezier_draw_segment(): Unknown coordinate space: %d", space); - break; - } - - geometry[i][2] = 0; - geometry[i][3] = 0; - - points = points->next; - } - - /* subdivide the curve n times */ - /* n can be adjusted to give a finer or coarser curve */ - - d = 1.0 / subdivisions; - d2 = d * d; - d3 = d * d * d; - - /* construct a temporary matrix for determining the forward diffencing deltas */ - - tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; - tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; - tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; - tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; - - /* compose the basis and geometry matrices */ - bezier_compose (basis, geometry, tmp1); - - /* compose the above results to get the deltas matrix */ - bezier_compose (tmp2, tmp1, deltas); - - /* extract the x deltas */ - x = deltas[0][0]; - dx = deltas[1][0]; - dx2 = deltas[2][0]; - dx3 = deltas[3][0]; - - /* extract the y deltas */ - y = deltas[0][1]; - dy = deltas[1][1]; - dy2 = deltas[2][1]; - dy3 = deltas[3][1]; - - lastx = x; - lasty = y; - - gdk_points[0].x = (lastx); - gdk_points[0].y = (lasty); - index = 1; - - /* loop over the curve */ - for (i = 0; i < subdivisions; i++) - { - /* increment the x values */ - x += dx; - dx += dx2; - dx2 += dx3; - - /* increment the y values */ - y += dy; - dy += dy2; - dy2 += dy3; - - newx = ROUND (x); - newy = ROUND (y); - - /* if this point is different than the last one...then draw it */ - if ((lastx != newx) || (lasty != newy)) - { - /* add the point to the point buffer */ - gdk_points[index].x = (newx); - gdk_points[index].y = (newy); - index++; - - /* if the point buffer is full put it to the screen and zero it out */ - if (index >= n_points) - { - (* points_func) (bezier_sel, gdk_points, index, data); - index = 0; - } - } - - lastx = newx; - lasty = newy; - } - - /* if there are points in the buffer, then put them on the screen */ - if (index) - (* points_func) (bezier_sel, gdk_points, index, data); -} - -static void -bezier_draw_segment_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data) -{ - gdk_draw_points (bezier_sel->core->win, - bezier_sel->core->gc, points, n_points); -} - -static void -bezier_compose (BezierMatrix a, - BezierMatrix b, - BezierMatrix ab) -{ - int i, j; - - for (i = 0; i < 4; i++) - { - for (j = 0; j < 4; j++) - { - ab[i][j] = (a[i][0] * b[0][j] + - a[i][1] * b[1][j] + - a[i][2] * b[2][j] + - a[i][3] * b[3][j]); - } - } -} - -static int start_convert; -static int width, height; -static int lastx; -static int lasty; - -static void -bezier_convert (BezierSelect *bezier_sel, - GDisplay *gdisp, - gint subdivisions, - gboolean antialias) -{ - PixelRegion maskPR; - BezierPoint *points; - BezierPoint *start_pt; - BezierPoint *next_curve; - GSList *list; - guchar *buf, *b; - gint draw_type; - gint *vals, val; - gint start, end; - gint x, x2, w; - gint i, j; - - if (!bezier_sel->closed) - gimp_fatal_error ("bezier_convert(): tried to convert an open bezier curve"); - - /* destroy previous mask */ - if (bezier_sel->mask) - { - channel_delete (bezier_sel->mask); - bezier_sel->mask = NULL; - } - - /* get the new mask's maximum extents */ - if (antialias) - { - buf = (unsigned char *) g_malloc (width); - width = gdisp->gimage->width * SUPERSAMPLE; - height = gdisp->gimage->height * SUPERSAMPLE; - draw_type = AA_IMAGE_COORDS; - /* allocate value array */ - vals = (int *) g_malloc (sizeof (int) * width); - } - else - { - buf = NULL; - width = gdisp->gimage->width; - height = gdisp->gimage->height; - draw_type = IMAGE_COORDS; - vals = NULL; - } - - /* create a new mask */ - bezier_sel->mask = channel_new_mask (gdisp->gimage, - gdisp->gimage->width, - gdisp->gimage->height); - - gtk_object_ref (GTK_OBJECT (bezier_sel->mask)); - gtk_object_sink (GTK_OBJECT (bezier_sel->mask)); - - /* allocate room for the scanlines */ - bezier_sel->scanlines = g_malloc (sizeof (GSList *) * height); - - /* zero out the scanlines */ - for (i = 0; i < height; i++) - bezier_sel->scanlines[i] = NULL; - - /* scan convert the curve */ - points = bezier_sel->points; - start_pt = bezier_sel->points; - - do { - start_convert = 1; - do { - bezier_draw_segment (bezier_sel, points, - subdivisions, draw_type, - bezier_convert_points, - NULL); - - /* advance to the next segment */ - points = next_anchor(points,&next_curve); - } while (points != start_pt && points); - start_pt = next_curve; - points = next_curve; - } while (next_curve); - - pixel_region_init (&maskPR, - gimp_drawable_data (GIMP_DRAWABLE (bezier_sel->mask)), - 0, 0, - gimp_drawable_width (GIMP_DRAWABLE (bezier_sel->mask)), - gimp_drawable_height (GIMP_DRAWABLE (bezier_sel->mask)), - TRUE); - - for (i = 0; i < height; i++) - { - list = bezier_sel->scanlines[i]; - - /* zero the vals array */ - if (antialias && !(i % SUPERSAMPLE)) - memset (vals, 0, width * sizeof (int)); - - while (list) - { - x = (long) list->data; - list = list->next; -/* - if (!list) - g_message ("cannot properly scanline convert bezier curve: %d", i); - else -*/ - { - /* bounds checking */ - x = CLAMP (x, 0, width); - x2 = CLAMP ((long) list->data, 0, width); - - w = x2 - x; - - if (!antialias) - channel_add_segment (bezier_sel->mask, x, i, w, 255); - else - for (j = 0; j < w; j++) - vals[j + x] += 255; - - list = g_slist_next (list); - } - } - - if (antialias && !((i+1) % SUPERSAMPLE)) - { - b = buf; - start = 0; - end = width; - for (j = start; j < end; j += SUPERSAMPLE) - { - val = 0; - for (x = 0; x < SUPERSAMPLE; x++) - val += vals[j + x]; - - *b++ = (unsigned char) (val / SUPERSAMPLE2); - } - - pixel_region_set_row (&maskPR, 0, (i / SUPERSAMPLE), - gimp_drawable_width (GIMP_DRAWABLE (bezier_sel->mask)), buf); - } - - g_slist_free (bezier_sel->scanlines[i]); - } - - if (antialias) - { - g_free (vals); - g_free (buf); - } - - g_free (bezier_sel->scanlines); - bezier_sel->scanlines = NULL; - - channel_invalidate_bounds (bezier_sel->mask); -} - -static void -bezier_convert_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data) -{ - gint i; - - if (start_convert) - start_convert = 0; - else - bezier_convert_line (bezier_sel->scanlines, - lastx, lasty, points[0].x, points[0].y); - - for (i = 0; i < (n_points - 1); i++) - { - bezier_convert_line (bezier_sel->scanlines, - points[i].x, points[i].y, - points[i+1].x, points[i+1].y); - } - - lastx = points[n_points - 1].x; - lasty = points[n_points - 1].y; -} - -static void -bezier_convert_line (GSList **scanlines, - gint x1, - gint y1, - gint x2, - gint y2) -{ - gint dx, dy; - gint error, inc; - gint tmp; - gdouble slope; - - if (y1 == y2) - return; - - if (y1 > y2) - { - tmp = y2; y2 = y1; y1 = tmp; - tmp = x2; x2 = x1; x1 = tmp; - } - - if (y1 < 0) - { - if (y2 < 0) - return; - - if (x2 == x1) - { - y1 = 0; - } - else - { - slope = (double) (y2 - y1) / (double) (x2 - x1); - x1 = x2 + (int)(0.5 + (double)(0 - y2) / slope); - y1 = 0; - } - } - - if (y2 >= height) - { - if (y1 >= height) - return; - - if (x2 == x1) - { - y2 = height; - } - else - { - slope = (double) (y2 - y1) / (double) (x2 - x1); - x2 = x1 + (int)(0.5 + (double)(height - y1) / slope); - y2 = height; - } - } - - if (y1 == y2) - return; - - dx = x2 - x1; - dy = y2 - y1; - - scanlines = &scanlines[y1]; - - if (((dx < 0) ? -dx : dx) > ((dy < 0) ? -dy : dy)) - { - if (dx < 0) - { - inc = -1; - dx = -dx; - } - else - { - inc = 1; - } - - error = -dx /2; - while (x1 != x2) - { - error += dy; - if (error > 0) - { - error -= dx; - *scanlines = bezier_insert_in_list (*scanlines, x1); - scanlines++; - } - - x1 += inc; - } - } - else - { - error = -dy /2; - if (dx < 0) - { - dx = -dx; - inc = -1; - } - else - { - inc = 1; - } - - while (y1++ < y2) - { - *scanlines = bezier_insert_in_list (*scanlines, x1); - scanlines++; - - error += dx; - if (error > 0) - { - error -= dy; - x1 += inc; - } - } - } -} - -static GSList * -bezier_insert_in_list (GSList *list, - gint x) -{ - GSList *orig = list; - GSList *rest; - - if (!list) - return g_slist_prepend (list, (void *) ((long) x)); - - while (list) - { - rest = g_slist_next (list); - if (x < (long) list->data) - { - rest = g_slist_prepend (rest, list->data); - list->next = rest; - list->data = (void *) ((long) x); - return orig; - } - else if (!rest) - { - g_slist_append (list, (void *) ((long) x)); - return orig; - } - list = g_slist_next (list); - } - - return orig; -} - -gboolean -bezier_tool_selected (void) -{ - return (active_tool && - active_tool->type == BEZIER_SELECT && - active_tool->state == ACTIVE); -} - -void -bezier_paste_bezierselect_to_current (GDisplay *gdisp, - BezierSelect *bsel) -{ - BezierPoint *pts; - gint i; - Tool *tool; - BezierPoint *bpnt = NULL; - gint need_move = 0; - -/* g_print ("bezier_paste_bezierselect_to_current::\n"); */ -/* printSel(bsel); */ - - /* If the tool was being used before clear it */ - if (active_tool && - active_tool->type == BEZIER_SELECT && - active_tool->state == ACTIVE) - { - BezierSelect *bezier_sel = (BezierSelect *) active_tool->private; - if(bezier_sel) - { - draw_core_stop (curSel->core, active_tool); - bezier_select_reset (bezier_sel); - } - } - - gimp_context_set_tool (gimp_context_get_user (), BEZIER_SELECT); - active_tool->paused_count = 0; - active_tool->gdisp = gdisp; - active_tool->drawable = gimp_image_active_drawable (gdisp->gimage); - - tool = active_tool; - - bezier_select_reset (curSel); - - draw_core_start (curSel->core, gdisp->canvas->window, tool); - - tool->state = ACTIVE; - - pts = (BezierPoint *) bsel->points; - - for (i = 0; i < bsel->num_points; i++) - { - if (need_move) - { - bezier_add_point (curSel, BEZIER_MOVE, pts->x, pts->y); - need_move = 0; - } - else - { - bezier_add_point (curSel, pts->type, pts->x, pts->y); - } - - if (bpnt == NULL) - bpnt = curSel->last_point; - - if (pts->next_curve) - { -/* g_print ("bezier_paste_bezierselect_to_current:: Close last curve off \n"); */ - curSel->last_point->next = bpnt; - bpnt->prev = curSel->last_point; - curSel->cur_anchor = NULL; - curSel->cur_control = NULL; - bpnt = NULL; - need_move = 1; - pts = pts->next_curve; - } - else - { - pts = pts->next; - } - } - - if (bsel->closed) - { - curSel->last_point->next = bpnt; - bpnt->prev = curSel->last_point; - curSel->cur_anchor = curSel->points; - curSel->cur_control = curSel->points->next; - curSel->closed = 1; - if (curTool->gdisp) - bezier_convert (curSel, curTool->gdisp, SUBDIVIDE, FALSE); - } - -/* g_print ("After pasting...\n"); */ -/* printSel(curSel); */ - - if (bsel->num_points == 0) - { - curSel->state = BEZIER_START; - curSel->draw = 0; - draw_core_stop( curSel->core, curTool); - } - else - { - curSel->state = bsel->state; - curSel->draw = BEZIER_DRAW_ALL; - draw_core_resume( curSel->core, curTool); - } -} - -static void -bezier_to_sel_internal (BezierSelect *bezier_sel, - Tool *tool, - GDisplay *gdisp, - gint op, - gint replace) -{ - /* If we're antialiased, then recompute the mask... - */ - if (bezier_options->antialias) - bezier_convert (bezier_sel, tool->gdisp, SUBDIVIDE, TRUE); - - if (replace) - gimage_mask_clear (gdisp->gimage); - else - gimage_mask_undo (gdisp->gimage); - - if (bezier_options->feather) - channel_feather (bezier_sel->mask, - gimp_image_get_mask (gdisp->gimage), - bezier_options->feather_radius, - bezier_options->feather_radius, - op, 0, 0); - else - channel_combine_mask (gimp_image_get_mask (gdisp->gimage), - bezier_sel->mask, op, 0, 0); - - /* show selection on all views */ - gdisplays_flush (); -} - -static gboolean -test_add_point_on_segment (BezierSelect *bezier_sel, - BezierPoint *pt, - gint subdivisions, - gint space, - gint xpos, - gint ypos, - gint halfwidth) - -{ - BezierPoint *points; - BezierMatrix geometry; - BezierMatrix tmp1, tmp2; - BezierMatrix deltas; - gdouble x, dx, dx2, dx3; - gdouble y, dy, dy2, dy3; - gdouble d, d2, d3; - gint lastx, lasty; - gint newx, newy; - gint i; - gdouble ratio; - - /* construct the geometry matrix from the segment assumes that a - * valid segment containing 4 points is passed in ALT ignore invalid - * segments since we might be working on an open curve - */ - - points = pt; - - ratio = -1.0; - - for (i = 0; i < 4; i++) - { - if (!points) - return FALSE; - - switch (space) - { - case IMAGE_COORDS: - geometry[i][0] = points->x; - geometry[i][1] = points->y; - break; - case AA_IMAGE_COORDS: - geometry[i][0] = RINT(points->x * SUPERSAMPLE); - geometry[i][1] = RINT(points->y * SUPERSAMPLE); - break; - case SCREEN_COORDS: - geometry[i][0] = points->sx; - geometry[i][1] = points->sy; - break; - default: - gimp_fatal_error ("test_add_point_on_segment(): Unknown coordinate space: %d", space); - break; - } - - geometry[i][2] = 0; - geometry[i][3] = 0; - - points = points->next; - } - - /* subdivide the curve n times n can be adjusted to give a finer or - * coarser curve - */ - - d = 1.0 / subdivisions; - d2 = d * d; - d3 = d * d * d; - - /* construct a temporary matrix for determining the forward - * diffencing deltas - */ - - tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; - tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; - tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; - tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; - - /* compose the basis and geometry matrices */ - bezier_compose (basis, geometry, tmp1); - - /* compose the above results to get the deltas matrix */ - bezier_compose (tmp2, tmp1, deltas); - - /* extract the x deltas */ - x = deltas[0][0]; - dx = deltas[1][0]; - dx2 = deltas[2][0]; - dx3 = deltas[3][0]; - - /* extract the y deltas */ - y = deltas[0][1]; - dy = deltas[1][1]; - dy2 = deltas[2][1]; - dy3 = deltas[3][1]; - - lastx = x; - lasty = y; - - /* loop over the curve */ - for (i = 0; i < subdivisions; i++) - { - /* increment the x values */ - x += dx; - dx += dx2; - dx2 += dx3; - - /* increment the y values */ - y += dy; - dy += dy2; - dy2 += dy3; - - newx = ROUND (x); - newy = ROUND (y); - - /* if this point is different than the last one...then test it */ - if ((lastx != newx) || (lasty != newy)) - { - int l, r, b, t; - - l = newx - halfwidth; - r = newx + halfwidth; - t = newy - halfwidth; - b = newy + halfwidth; - - if ((xpos >= l) && (xpos <= r) && (ypos >= t) && (ypos <= b)) - { - /* so we found one point in the square hit */ - - ratio = (double)i/(double)subdivisions; - - /* We found the exact point on the curve, so take it ...*/ - - if ((xpos==newx) && (ypos==newy)) break; - - /* To Implement: keep each time the nearest point of the - * curve from where we've clicked in the case where we - * haven't click exactely on the curve. - */ - } - } - lastx = newx; - lasty = newy; - } - - /* we found a point on the curve */ - - if (ratio >= 0.0) - { - BezierPoint *pts, *pt1, *pt2, *pt3; - BezierPoint *P00, *P01, *P02, *P03; - BezierPoint P10, P11, P12; - BezierPoint P20, P21; - BezierPoint P30; - - pts = pt; - - P00 = pts; - pts = pts->next; - P01 = pts; - pts = pts->next; - P02 = pts; - pts = pts->next; - P03 = pts; - - /* De Casteljau algorithme - [Advanced Animation & Randering Technics / Alan & Mark WATT] - [ADDISON WESLEY ref 54412] - Iteratif way of drawing a Bezier curve by geometrical approch - - P0x represent the four controls points ( anchor / control /control /anchor ) - P30 represent the new anchor point to add on the curve - P2x represent the new control points of P30 - P1x represent the new values of the control points P01 and P02 - - so if we moves ratio from 0 to 1 we draw the all curve between P00 and P03 - */ - - P10.x = (int)((1-ratio)*P00->x + ratio * P01->x); - P10.y = (int)((1-ratio)*P00->y + ratio * P01->y); - - P11.x = (1-ratio)*P01->x + ratio * P02->x; - P11.y = (1-ratio)*P01->y + ratio * P02->y; - - P12.x = (1-ratio)*P02->x + ratio * P03->x; - P12.y = (1-ratio)*P02->y + ratio * P03->y; - - P20.x = (1-ratio)*P10.x + ratio * P11.x; - P20.y = (1-ratio)*P10.y + ratio * P11.y; - - P21.x = (1-ratio)*P11.x + ratio * P12.x; - P21.y = (1-ratio)*P11.y + ratio * P12.y; - - P30.x = (1-ratio)*P20.x + ratio * P21.x; - P30.y = (1-ratio)*P20.y + ratio * P21.y; - - P01->x = P10.x; - P01->y = P10.y; - - P02->x = P12.x; - P02->y = P12.y; - - /* All the computes are done, let's insert the new point on the curve */ - - pt1 = g_new0(BezierPoint,1); - pt2 = g_new0(BezierPoint,1); - pt3 = g_new0(BezierPoint,1); - - pt1->type = BEZIER_CONTROL; - pt2->type = BEZIER_ANCHOR; - pt3->type = BEZIER_CONTROL; - - pt1->x = P20.x; pt1->y = P20.y; - pt2->x = P30.x; pt2->y = P30.y; - pt3->x = P21.x; pt3->y = P21.y; - - pt3->next_curve = P01->next_curve; - P01->next = pt1; - - pt1->prev = P01; - pt1->next = pt2; - - pt2->prev = pt1; - pt2->next = pt3; - - pt3->prev = pt2; - pt3->next = P02; - - P02->prev = pt3; - - bezier_sel->num_points += 3; - - bezier_sel->cur_anchor = pt2; - bezier_sel->cur_control = pt1; - - return TRUE; - } - - return FALSE; -} - -void -bezier_select_mode (gint mode) -{ - ModeEdit = mode; -} - -/* The curve has to be closed to do a selection. */ - -void -bezier_to_selection (BezierSelect *bezier_sel, - GDisplay *gdisp) -{ - /* Call the internal function */ - if (!bezier_sel->closed) - { - g_message (_("Curve not closed!")); - return; - } - - /* force the passed selection to be the current selection... - * This loads it into curSel for this image - */ - bezier_paste_bezierselect_to_current (gdisp, bezier_sel); - bezier_to_sel_internal (curSel, curTool, gdisp, CHANNEL_OP_ADD, TRUE); -} - -/* unused -static void -printSel (BezierSelect *sel) -{ - BezierPoint *pt; - BezierPoint *start_pt; - gint i; - - pt = sel->points; - start_pt = pt; - - g_print ("\n"); - - for (i = 0; i < sel->num_points; i++) - { - g_print ("%d(%p) x,y=%f,%f type=%d next=%p prev=%p next_curve=%p\n", - i,pt, pt->x, pt->y,pt->type,pt->next,pt->prev,pt->next_curve); - - if (pt->next != start_pt && pt->next_curve) - g_print ("Curve out a sync!!\n"); - - if(pt->next_curve) - { - pt = pt->next_curve; - start_pt = pt; - } - else - { - pt = pt->next; - } - } - - g_print ("core : %p\n", sel->core); - g_print ("closed : %d\n", sel->closed); - g_print ("draw : %d\n", sel->draw); - g_print ("state: %d\n", sel->state); -} -*/ - -/* check whether vectors (offx, offy), (l_offx, l_offy) have the same angle. */ -static gboolean -stroke_interpolatable (gint offx, - gint offy, - gint l_offx, - gint l_offy, - gdouble error) -{ - if ((offx == l_offx) & (offy == l_offy)) - { - return TRUE; - } - else if ((offx == 0) | (l_offx == 0)) - { - if (offx == l_offx) - return ((0 <= offy) & (0 <= offy)) | ((offy < 0) & (l_offy < 0)); - else - return FALSE; - } - else if ((offy == 0) | (l_offy == 0)) - { - if (offy == l_offy) - return ((0 < offx) & (0 < l_offx)) | ((offx < 0) & (l_offx < 0)); - else - return FALSE; - } - /* At this point, we can assert: offx, offy, l_offx, l_offy != 0 */ - else if (((0 < offx) & (0 < l_offx)) | ((offx < 0) & (l_offx < 0))) - { - gdouble grad1, grad2; - - if (ABS (offy) < ABS (offx)) - { - grad1 = (gdouble) offy / (gdouble) offx; - grad2 = (gdouble) l_offy / (gdouble) l_offx; - } - else - { - grad1 = (gdouble) offx / (gdouble) offy; - grad2 = (gdouble) l_offx / (gdouble) l_offy; - } - - /* printf ("error: %f / %f\n", ABS (grad1 - grad2), error); */ - return ABS (grad1 - grad2) <= error; - } - - return FALSE; -} - -static void -bezier_stack_points_aux (GdkPoint *points, - gint start, - gint end, - gdouble error, - BezierRenderPnts *rpnts) -{ - const gint expand_size = 32; - gint med; - gint offx, offy, l_offx, l_offy; - - if (rpnts->stroke_points == NULL) - return; - - /* BASE CASE: stack the end point */ - if (end - start <= 1) - { - if ((rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] == points[end].x) - && (rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] == points[end].y)) - return; - - rpnts->num_stroke_points++; - if (rpnts->len_stroke_points <= rpnts->num_stroke_points) - { - rpnts->len_stroke_points += expand_size; - rpnts->stroke_points = g_renew (double, rpnts->stroke_points, 2 * rpnts->len_stroke_points); - if (rpnts->stroke_points == NULL) - { - rpnts->len_stroke_points = rpnts->num_stroke_points = 0; - return; - } - } - rpnts->stroke_points[rpnts->num_stroke_points * 2 - 2] = points[end].x; - rpnts->stroke_points[rpnts->num_stroke_points * 2 - 1] = points[end].y; - return; - } - - if (end - start <= 32) - { - gint i; - - for (i = start+ 1; i <= end; i++) - bezier_stack_points_aux (points, i, i, 0,rpnts); - return; - } - /* Otherwise, check whether to divide the segment recursively */ - offx = points[end].x - points[start].x; - offy = points[end].y - points[start].y; - med = (end + start) / 2; - - l_offx = points[med].x - points[start].x; - l_offy = points[med].y - points[start].y; - - if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error)) - { - bezier_stack_points_aux (points, start, med, error, rpnts); - bezier_stack_points_aux (points, med, end, error, rpnts); - return; - } - - l_offx = points[end].x - points[med].x; - l_offy = points[end].y - points[med].y; - - if (! stroke_interpolatable (offx, offy, l_offx, l_offy, error)) - { - bezier_stack_points_aux (points, start, med, error, rpnts); - bezier_stack_points_aux (points, med, end, error, rpnts); - return; - } - /* Now, the curve can be represented by a points pair: (start, end). - So, add the last point to stroke_points. */ - bezier_stack_points_aux (points, end, end, 0, rpnts); -} - -static void -bezier_stack_points (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data) -{ - BezierRenderPnts *rpnts = data; - gint i; - gint expand_size = 32; - gint minx, maxx, miny, maxy; - gdouble error; - - if (n_points < 2) /* Does this happen? */ - return; - - if (rpnts->stroke_points == NULL) /* initialize it here */ - { - rpnts->num_stroke_points = 0; - rpnts->len_stroke_points = expand_size; - rpnts->stroke_points = g_new (gdouble, 2 * rpnts->len_stroke_points); - } - - maxx = minx = points[0].x; - maxy = miny = points[0].y; - for (i = 1; i < n_points; i++) - { - if (points[i].x < minx) - minx = points[i].x; - else if (maxx < points[i].x) - maxx = points[i].x; - if (points[i].y < miny) - miny = points[i].x; - else if (maxy < points[i].y) - maxy = points[i].y; - } - /* allow one pixel fluctuation */ - error = 2.0 / MAX (maxx - minx, maxy - miny); - error = 0.0; /* ALT */ - - /* add the start point */ - bezier_stack_points_aux (points, 0, 0, 0, rpnts); - - /* divide segments recursively */ - bezier_stack_points_aux (points, 0, n_points - 1, error, rpnts); - - /* printf ("n_points: %d\n", n_points); */ -} - -static gint -bezier_gen_points (BezierSelect *bezier_sel, - gint open_path, - BezierRenderPnts *rpnts) -{ - BezierPoint *points; - BezierPoint *start_pt; - BezierPoint *next_curve; - BezierRenderPnts *next_rpnts = rpnts; - gint point_counts = 0; - - /* stack points */ - points = bezier_sel->points; - start_pt = bezier_sel->points; - - if (bezier_sel->num_points >= 4) - { - do - { - point_counts = count_points_on_curve (points); - - if (point_counts < 4) - return TRUE; - - do - { - bezier_draw_segment (bezier_sel, points, - SUBDIVIDE, AA_IMAGE_COORDS, - bezier_stack_points, - (gpointer) next_rpnts); - - points = next_anchor (points, &next_curve); - } - while (points != start_pt && points); - - start_pt = next_curve; - points = next_curve; - - if (next_curve) - { - next_rpnts->next_curve = g_new0 (BezierRenderPnts, 1); - next_rpnts = next_rpnts->next_curve; - } - } - while (next_curve); - } - - return TRUE; -} - -void -bezier_stroke (BezierSelect *bezier_sel, - GDisplay *gdisp, - gint subdivisions, - gint open_path) -{ - Argument *return_vals; - gint nreturn_vals; - BezierRenderPnts *next_rpnts; - BezierRenderPnts *rpnts; - - rpnts = g_new0 (BezierRenderPnts, 1); - - /* Start an undo group */ - undo_push_group_start (gdisp->gimage, PAINT_CORE_UNDO); - - bezier_gen_points (bezier_sel,open_path,rpnts); - - do - { - if (rpnts->stroke_points) - { - GimpDrawable *drawable; - gint offset_x, offset_y; - gdouble *ptr; - - drawable = gimp_image_active_drawable (gdisp->gimage); - gimp_drawable_offsets (drawable, &offset_x, &offset_y); - - ptr = rpnts->stroke_points; - while (ptr < rpnts->stroke_points + (rpnts->num_stroke_points * 2)) - { - *ptr /= SUPERSAMPLE; - *ptr++ -= offset_x; - *ptr /= SUPERSAMPLE; - *ptr++ -= offset_y; - } - - /* Stroke with the correct tool */ - return_vals = - procedural_db_run_proc (tool_active_PDB_string (), - &nreturn_vals, - PDB_DRAWABLE, gimp_drawable_get_ID (drawable), - PDB_INT32, (gint32) rpnts->num_stroke_points * 2, - PDB_FLOATARRAY, rpnts->stroke_points, - PDB_END); - - if (return_vals && return_vals[0].value.pdb_int != PDB_SUCCESS) - g_message (_("Paintbrush operation failed.")); - - procedural_db_destroy_args (return_vals, nreturn_vals); - - g_free (rpnts->stroke_points); - } - - next_rpnts = rpnts->next_curve; - rpnts->stroke_points = NULL; - rpnts->len_stroke_points = rpnts->num_stroke_points = 0; - g_free(rpnts); - rpnts = next_rpnts; - } - while (rpnts); - - /* End an undo group */ - undo_push_group_end (gdisp->gimage); - gdisplays_flush (); -} - -static void -bezier_draw_segment_for_distance (BezierSelect *bezier_sel, - BezierPoint *points, - gint subdivisions, - BezierDistance *bdist) -{ - BezierMatrix geometry; - BezierMatrix tmp1, tmp2; - BezierMatrix deltas; - gdouble x, dx, dx2, dx3; - gdouble y, dy, dy2, dy3; - gdouble d, d2, d3; - gint index; - gint i; - - /* construct the geometry matrix from the segment */ - /* assumes that a valid segment containing 4 points is passed in */ - - if (bdist->found) - return; - - for (i = 0; i < 4; i++) - { - if (!points) - gimp_fatal_error ("bezier_draw_segment_for_distance(): Bad bezier segment"); - - geometry[i][0] = points->x; - geometry[i][1] = points->y; - geometry[i][2] = 0; - geometry[i][3] = 0; - - points = points->next; - } - - /* subdivide the curve n times */ - /* n can be adjusted to give a finer or coarser curve */ - - d = 1.0 / subdivisions; - d2 = d * d; - d3 = d * d * d; - - /* construct a temporary matrix for determining the forward diffencing deltas */ - - tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; - tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; - tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; - tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; - - /* compose the basis and geometry matrices */ - bezier_compose (basis, geometry, tmp1); - - /* compose the above results to get the deltas matrix */ - bezier_compose (tmp2, tmp1, deltas); - - /* extract the x deltas */ - x = deltas[0][0]; - dx = deltas[1][0]; - dx2 = deltas[2][0]; - dx3 = deltas[3][0]; - - /* extract the y deltas */ - y = deltas[0][1]; - dy = deltas[1][1]; - dy2 = deltas[2][1]; - dy3 = deltas[3][1]; - - index = 1; - - /* loop over the curve */ - for (i = 0; i < subdivisions; i++) - { - /* increment the x values */ - x += dx; - dx += dx2; - dx2 += dx3; - - /* increment the y values */ - y += dy; - dy += dy2; - dy2 += dy3; - -/* g_print ("x = %g, y = %g\n",x,y); */ - - /* if this point is different than the last one...then draw it */ - /* Note : - * It assumes the data is the place we want the - * floating version of the coords to be stuffed. - * These are needed when we calculate the gradient of the - * curve. - */ - - if (!bdist->firstpnt) - { - gdouble rx = x; - gdouble ry = y; - gdouble dx = bdist->lastx - rx; - gdouble dy = bdist->lasty - ry; - - bdist->curdist += sqrt ((dx * dx) + (dy * dy)); - if(bdist->curdist >= bdist->dist) - { - *(bdist->x) = ROUND ((rx + dx / 2)); - *(bdist->y) = ROUND ((ry + dy / 2)); - - if (dx == 0.0) - *(bdist->gradient) = G_MAXDOUBLE; - else - *(bdist->gradient) = dy / dx; - -/* g_print ("found x = %d, y = %d\n",*(bdist->x),*(bdist->y)); */ - bdist->found = TRUE; - break; - } - bdist->lastx = rx; - bdist->lasty = ry; - } - else - { - bdist->firstpnt = FALSE; - bdist->lastx = x; - bdist->lasty = y; - } - } -} - -static void -bezier_draw_curve_for_distance (BezierSelect *bezier_sel, - BezierDistance *distance) -{ - BezierPoint *points; - BezierPoint *start_pt; - BezierPoint *next_curve; - - points = bezier_sel->points; - start_pt = bezier_sel->points; - - if (bezier_sel->num_points >= 4) - { - do - { - do - { - bezier_draw_segment_for_distance (bezier_sel, points, - SUBDIVIDE, - distance); - points = next_anchor (points, &next_curve); - } - while (points != start_pt && points); - - start_pt = next_curve; - points = next_curve; - } - while (next_curve); - } -} - -gint -bezier_distance_along (BezierSelect *bezier_sel, - gint open_path, - gdouble dist, - gint *x, - gint *y, - gdouble *gradient) -{ - /* Render the curve as points then walk along it... */ - BezierDistance *bdist; - gint ret; - - bdist = g_new0 (BezierDistance, 1); - - bdist->firstpnt = TRUE; - bdist->curdist = 0.0; - bdist->lastx = 0.0; - bdist->lasty = 0.0; - bdist->dist = dist; - bdist->x = x; - bdist->y = y; - bdist->gradient = gradient; - bdist->found = FALSE; - - bezier_draw_curve_for_distance (bezier_sel, bdist); - ret = bdist->found; - - g_free (bdist); - - return ret; -} diff --git a/app/bezier_select.h b/app/bezier_select.h deleted file mode 100644 index 6ec0e61cc8..0000000000 --- a/app/bezier_select.h +++ /dev/null @@ -1,29 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BEZIER_SELECT_H__ -#define __BEZIER_SELECT_H__ - - -Tool * tools_new_bezier_select (void); -void tools_free_bezier_select (Tool *tool); - -gboolean bezier_tool_selected (void); - - -#endif /* __BEZIER_SELECT_H__ */ diff --git a/app/bezier_selectP.h b/app/bezier_selectP.h deleted file mode 100644 index 87b76aec96..0000000000 --- a/app/bezier_selectP.h +++ /dev/null @@ -1,116 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BEZIER_SELECTP_H__ -#define __BEZIER_SELECTP_H__ - -#include "draw_core.h" - -#define BEZIER_START 1 -#define BEZIER_ADD 2 -#define BEZIER_EDIT 4 -#define BEZIER_DRAG 8 - -#define BEZIER_ANCHOR 1 -#define BEZIER_CONTROL 2 -#define BEZIER_MOVE 3 - -#define IMAGE_COORDS 1 -#define AA_IMAGE_COORDS 2 -#define SCREEN_COORDS 3 - -#define SUBDIVIDE 1000 - -enum { EXTEND_EDIT, EXTEND_ADD, EXTEND_REMOVE, EXTEND_NEW }; - -struct _BezierPoint -{ - gint type; /* type of point (anchor/control/move) */ - gdouble x, y; /* location of point in image space */ - gint sx, sy; /* location of point in screen space */ - BezierPoint *next; /* next point on curve */ - BezierPoint *prev; /* prev point on curve */ - BezierPoint *next_curve; /* Next curve segment */ - gint pointflags; /* Status of point 0 = not selected - * 1 = selected - */ -}; - -struct _BezierSelect -{ - gint state; /* start, add, edit or drag */ - gint draw; /* all or part */ - gint closed; /* is the last curve closed */ - DrawCore *core; /* Core drawing object */ - BezierPoint *points; /* the curve */ - BezierPoint *cur_anchor; /* the current active anchor point */ - BezierPoint *cur_control; /* the current active control point */ - BezierPoint *last_point; /* the last point on the curve */ - gint num_points; /* number of points in the curve */ - Channel *mask; /* null if the curve is open */ - GSList **scanlines; /* used in converting a curve */ -}; - -/* All data that are passed to the bezier_draw_curve must - * have this structure as the first element. - */ - -typedef struct -{ - gint count; -} CountCurves; - -typedef void (* BezierPointsFunc) (BezierSelect *bezier_sel, - GdkPoint *points, - gint n_points, - gpointer data); - -/* Functions */ -gint bezier_select_load (GDisplay *gdisp, - BezierPoint *points, - gint n_points, - gint closed); -void bezier_draw_curve (BezierSelect *bezier_sel, - BezierPointsFunc func, - gint coord, - gpointer data); -void bezier_select_reset (BezierSelect *bezier_sel); -void bezier_select_free (BezierSelect *bezier_sel); -void bezier_add_point (BezierSelect *bezier_sel, - gint type, - gdouble x, - gdouble y); -void bezier_paste_bezierselect_to_current (GDisplay *gdisp, - BezierSelect *bezier_sel); -void bezier_select_mode (gint); -void bezier_stroke (BezierSelect *bezier_sel, - GDisplay *gdisp, - gint subdivisions, - gint open_path); -void bezier_to_selection (BezierSelect *bezier_sel, - GDisplay *gdisp); -gint bezier_distance_along (BezierSelect *bezier_sel, - gint open_path, - gdouble dist, - gint *x, - gint *y, - gdouble *gradient); -void bezier_draw (GDisplay *gdisp, - BezierSelect *bezier_sel); - -#endif /* __BEZIER_SELECTP_H__ */ diff --git a/app/blend.c b/app/blend.c deleted file mode 100644 index 982df28bfd..0000000000 --- a/app/blend.c +++ /dev/null @@ -1,1695 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "asupsample.h" -#include "blend.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "drawable.h" -#include "errors.h" -#include "fuzzy_select.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimage_mask.h" -#include "gimpcontext.h" -#include "gimpdnd.h" -#include "gimpprogress.h" -#include "gimpui.h" -#include "gradient.h" -#include "paint_funcs.h" -#include "paint_options.h" -#include "pixel_region.h" -#include "selection.h" -#include "tools.h" -#include "undo.h" - -#include "tile.h" -#include "tile_manager.h" - -#include "libgimp/gimpcolorspace.h" -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* target size */ -#define TARGET_HEIGHT 15 -#define TARGET_WIDTH 15 - -#define STATUSBAR_SIZE 128 - -/* the blend structures */ - -typedef gdouble (* RepeatFunc) (gdouble); - -typedef struct _BlendTool BlendTool; - -struct _BlendTool -{ - DrawCore *core; /* Core select object */ - - gint startx; /* starting x coord */ - gint starty; /* starting y coord */ - - gint endx; /* ending x coord */ - gint endy; /* ending y coord */ - guint context_id; /* for the statusbar */ -}; - -typedef struct _BlendOptions BlendOptions; - -struct _BlendOptions -{ - PaintOptions paint_options; - - gdouble offset; - gdouble offset_d; - GtkObject *offset_w; - - BlendMode blend_mode; - BlendMode blend_mode_d; - GtkWidget *blend_mode_w; - - GradientType gradient_type; - GradientType gradient_type_d; - GtkWidget *gradient_type_w; - - RepeatMode repeat; - RepeatMode repeat_d; - GtkWidget *repeat_w; - - gint supersample; - gint supersample_d; - GtkWidget *supersample_w; - - gint max_depth; - gint max_depth_d; - GtkObject *max_depth_w; - - gdouble threshold; - gdouble threshold_d; - GtkObject *threshold_w; -}; - -typedef struct -{ - gdouble offset; - gdouble sx, sy; - BlendMode blend_mode; - GradientType gradient_type; - GimpRGB fg, bg; - gdouble dist; - gdouble vec[2]; - RepeatFunc repeat_func; -} RenderBlendData; - -typedef struct -{ - PixelRegion *PR; - guchar *row_data; - gint bytes; - gint width; -} PutPixelData; - - -/* the blend tool options */ -static BlendOptions *blend_options = NULL; - -/* variables for the shapeburst algs */ -static PixelRegion distR = -{ - NULL, /* data */ - NULL, /* tiles */ - 0, /* rowstride */ - 0, 0, /* w, h */ - 0, 0, /* x, y */ - 4, /* bytes */ - 0 /* process count */ -}; - -/* dnd stuff */ -static GtkTargetEntry blend_target_table[] = -{ - GIMP_TARGET_GRADIENT, - GIMP_TARGET_TOOL -}; -static guint blend_n_targets = (sizeof (blend_target_table) / - sizeof (blend_target_table[0])); - -/* local function prototypes */ - -static void gradient_type_callback (GtkWidget *widget, - gpointer data); - -static void blend_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void blend_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void blend_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void blend_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void blend_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static void blend_options_drop_gradient (GtkWidget *widget, - gradient_t *gradient, - gpointer data); -static void blend_options_drop_tool (GtkWidget *widget, - ToolType gradient, - gpointer data); - -static gdouble gradient_calc_conical_sym_factor (gdouble dist, - gdouble *axis, - gdouble offset, - gdouble x, - gdouble y); -static gdouble gradient_calc_conical_asym_factor (gdouble dist, - gdouble *axis, - gdouble offset, - gdouble x, - gdouble y); -static gdouble gradient_calc_square_factor (gdouble dist, - gdouble offset, - gdouble x, - gdouble y); -static gdouble gradient_calc_radial_factor (gdouble dist, - gdouble offset, - gdouble x, - gdouble y); -static gdouble gradient_calc_linear_factor (gdouble dist, - gdouble *vec, - gdouble offset, - gdouble x, - gdouble y); -static gdouble gradient_calc_bilinear_factor (gdouble dist, - gdouble *vec, - gdouble offset, - gdouble x, - gdouble y); -static gdouble gradient_calc_spiral_factor (gdouble dist, - gdouble *axis, - gdouble offset, - gdouble x, - gdouble y, - gint cwise); - -static gdouble gradient_calc_shapeburst_angular_factor (gdouble x, - gdouble y); -static gdouble gradient_calc_shapeburst_spherical_factor (gdouble x, - gdouble y); -static gdouble gradient_calc_shapeburst_dimpled_factor (gdouble x, - gdouble y); - -static gdouble gradient_repeat_none (gdouble val); -static gdouble gradient_repeat_sawtooth (gdouble val); -static gdouble gradient_repeat_triangular (gdouble val); - -static void gradient_precalc_shapeburst (GImage *gimage, - GimpDrawable *drawable, - PixelRegion *PR, - gdouble dist); - -static void gradient_render_pixel (gdouble x, - gdouble y, - GimpRGB *color, - gpointer render_data); -static void gradient_put_pixel (gint x, - gint y, - GimpRGB color, - gpointer put_pixel_data); - -static void gradient_fill_region (GImage *gimage, - GimpDrawable *drawable, - PixelRegion *PR, - gint width, - gint height, - BlendMode blend_mode, - GradientType gradient_type, - gdouble offset, - RepeatMode repeat, - gint supersample, - gint max_depth, - gdouble threshold, - gdouble sx, - gdouble sy, - gdouble ex, - gdouble ey, - GimpProgressFunc progress_callback, - gpointer progress_data); - - -/* functions */ - -static void -gradient_type_callback (GtkWidget *widget, - gpointer data) -{ - gimp_menu_item_update (widget, data); - - gtk_widget_set_sensitive (blend_options->repeat_w, - (blend_options->gradient_type < 6)); -} - -static void -blend_options_reset (void) -{ - BlendOptions *options = blend_options; - - paint_options_reset ((PaintOptions *) options); - - options->blend_mode = options->blend_mode_d; - options->gradient_type = options->gradient_type_d; - options->repeat = options->repeat_d; - - gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->blend_mode_w), - blend_options->blend_mode_d); - gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w), - blend_options->gradient_type_d); - gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->repeat_w), - blend_options->repeat_d); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->offset_w), - blend_options->offset_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (blend_options->supersample_w), - blend_options->supersample_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->max_depth_w), - blend_options->max_depth_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->threshold_w), - blend_options->threshold_d); -} - -static BlendOptions * -blend_options_new (void) -{ - BlendOptions *options; - - GtkWidget *vbox; - GtkWidget *table; - GtkWidget *scale; - GtkWidget *frame; - - /* the new blend tool options structure */ - options = g_new (BlendOptions, 1); - paint_options_init ((PaintOptions *) options, - BLEND, - blend_options_reset); - options->offset = options->offset_d = 0.0; - options->blend_mode = options->blend_mode_d = FG_BG_RGB_MODE; - options->gradient_type = options->gradient_type_d = LINEAR; - options->repeat = options->repeat_d = REPEAT_NONE; - options->supersample = options->supersample_d = FALSE; - options->max_depth = options->max_depth_d = 3; - options->threshold = options->threshold_d = 0.2; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* dnd stuff */ - gtk_drag_dest_set (vbox, - GTK_DEST_DEFAULT_HIGHLIGHT | - GTK_DEST_DEFAULT_MOTION | - GTK_DEST_DEFAULT_DROP, - blend_target_table, blend_n_targets, - GDK_ACTION_COPY); - gimp_dnd_gradient_dest_set (vbox, blend_options_drop_gradient, NULL); - gimp_dnd_tool_dest_set (vbox, blend_options_drop_tool, NULL); - - /* the offset scale */ - table = gtk_table_new (4, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 1); - gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); - gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); - - options->offset_w = - gtk_adjustment_new (options->offset_d, 0.0, 100.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->offset_w)); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, - _("Offset:"), 1.0, 1.0, - scale, 1, FALSE); - gtk_signal_connect (GTK_OBJECT (options->offset_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->offset); - - /* the blend mode menu */ - options->blend_mode_w = gimp_option_menu_new2 - (FALSE, gimp_menu_item_update, - &options->blend_mode, (gpointer) options->blend_mode_d, - - _("FG to BG (RGB)"), (gpointer) FG_BG_RGB_MODE, NULL, - _("FG to BG (HSV)"), (gpointer) FG_BG_HSV_MODE, NULL, - _("FG to Transparent"), (gpointer) FG_TRANS_MODE, NULL, - _("Custom Gradient"), (gpointer) CUSTOM_MODE, NULL, - - NULL); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Blend:"), 1.0, 0.5, - options->blend_mode_w, 1, TRUE); - - /* the gradient type menu */ - options->gradient_type_w = gimp_option_menu_new2 - (FALSE, gradient_type_callback, - &options->gradient_type, (gpointer) options->gradient_type_d, - - _("Linear"), (gpointer) LINEAR, NULL, - _("Bi-Linear"), (gpointer) BILINEAR, NULL, - _("Radial"), (gpointer) RADIAL, NULL, - _("Square"), (gpointer) SQUARE, NULL, - _("Conical (symmetric)"), (gpointer) CONICAL_SYMMETRIC, NULL, - _("Conical (asymmetric)"), (gpointer) CONICAL_ASYMMETRIC, NULL, - _("Shapeburst (angular)"), (gpointer) SHAPEBURST_ANGULAR, NULL, - _("Shapeburst (spherical)"), (gpointer) SHAPEBURST_SPHERICAL, NULL, - _("Shapeburst (dimpled)"), (gpointer) SHAPEBURST_DIMPLED, NULL, - _("Spiral (clockwise)"), (gpointer) SPIRAL_CLOCKWISE, NULL, - _("Spiral (anticlockwise)"), (gpointer) SPIRAL_ANTICLOCKWISE, NULL, - - NULL); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, - _("Gradient:"), 1.0, 0.5, - options->gradient_type_w, 1, TRUE); - - /* the repeat option */ - options->repeat_w = gimp_option_menu_new2 - (FALSE, gimp_menu_item_update, - &options->repeat, (gpointer) options->repeat_d, - - _("None"), (gpointer) REPEAT_NONE, NULL, - _("Sawtooth Wave"), (gpointer) REPEAT_SAWTOOTH, NULL, - _("Triangular Wave"), (gpointer) REPEAT_TRIANGULAR, NULL, - - NULL); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 3, - _("Repeat:"), 1.0, 0.5, - options->repeat_w, 1, TRUE); - - /* show the table */ - gtk_widget_show (table); - - /* frame for supersampling options */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); - gtk_widget_show (frame); - - /* vbox for the supersampling stuff */ - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - - /* supersampling toggle */ - options->supersample_w = - gtk_check_button_new_with_label (_("Adaptive Supersampling")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->supersample_w), - options->supersample_d); - gtk_signal_connect (GTK_OBJECT (options->supersample_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->supersample); - gtk_box_pack_start (GTK_BOX (vbox), options->supersample_w, FALSE, FALSE, 0); - gtk_widget_show (options->supersample_w); - - /* table for supersampling options */ - table = gtk_table_new (2, 2, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (table), 2); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 1); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - /* automatically set the sensitive state of the table */ - gtk_widget_set_sensitive (table, options->supersample_d); - gtk_object_set_data (GTK_OBJECT (options->supersample_w), "set_sensitive", - table); - - /* max depth scale */ - options->max_depth_w = - gtk_adjustment_new (options->max_depth_d, 1.0, 10.0, 1.0, 1.0, 1.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->max_depth_w)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, - _("Max Depth:"), 1.0, 1.0, - scale, 1, FALSE); - gtk_signal_connect (GTK_OBJECT(options->max_depth_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_int_adjustment_update), - &options->max_depth); - - /* threshold scale */ - options->threshold_w = - gtk_adjustment_new (options->threshold_d, 0.0, 4.0, 0.01, 0.01, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w)); - gtk_scale_set_digits (GTK_SCALE (scale), 2); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Threshold:"), 1.0, 1.0, - scale, 1, FALSE); - gtk_signal_connect (GTK_OBJECT(options->threshold_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->threshold); - - /* show the table */ - gtk_widget_show (table); - - return options; -} - - -static void -blend_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - BlendTool *blend_tool; - - blend_tool = (BlendTool *) tool->private; - - switch (gimp_drawable_type (gimp_image_active_drawable (gdisp->gimage))) - { - case INDEXED_GIMAGE: case INDEXEDA_GIMAGE: - g_message (_("Blend: Invalid for indexed images.")); - return; - - break; - default: - break; - } - - /* Keep the coordinates of the target */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &blend_tool->startx, &blend_tool->starty, - FALSE, TRUE); - - blend_tool->endx = blend_tool->startx; - blend_tool->endy = blend_tool->starty; - - /* Make the tool active and set the gdisplay which owns it */ - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->gdisp = gdisp; - tool->state = ACTIVE; - - /* initialize the statusbar display */ - blend_tool->context_id = - gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "blend"); - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - blend_tool->context_id, _("Blend: 0, 0")); - - /* Start drawing the blend tool */ - draw_core_start (blend_tool->core, gdisp->canvas->window, tool); -} - -static void -blend_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - GImage *gimage; - BlendTool *blend_tool; -#ifdef BLEND_UI_CALLS_VIA_PDB - Argument *return_vals; - gint nreturn_vals; -#else - GimpProgress *progress; -#endif - - gimage = gdisp->gimage; - blend_tool = (BlendTool *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id); - - draw_core_stop (blend_tool->core, tool); - tool->state = INACTIVE; - - /* if the 3rd button isn't pressed, fill the selected region */ - if (! (bevent->state & GDK_BUTTON3_MASK) && - ((blend_tool->startx != blend_tool->endx) || - (blend_tool->starty != blend_tool->endy))) - { - /* we can't do callbacks easily with the PDB, so this UI/backend - * separation (though good) is ignored for the moment */ -#ifdef BLEND_UI_CALLS_VIA_PDB - return_vals = - procedural_db_run_proc ("gimp_blend", - &nreturn_vals, - PDB_DRAWABLE, drawable_ID (gimp_image_active_drawable (gimage)), - PDB_INT32, (gint32) blend_options->blend_mode, - PDB_INT32, (gint32) PAINT_OPTIONS_GET_PAINT_MODE (blend_options), - PDB_INT32, (gint32) blend_options->gradient_type, - PDB_FLOAT, (gdouble) PAINT_OPTIONS_GET_OPACITY (blend_options) * 100, - PDB_FLOAT, (gdouble) blend_options->offset, - PDB_INT32, (gint32) blend_options->repeat, - PDB_INT32, (gint32) blend_options->supersample, - PDB_INT32, (gint32) blend_options->max_depth, - PDB_FLOAT, (gdouble) blend_options->threshold, - PDB_FLOAT, (gdouble) blend_tool->startx, - PDB_FLOAT, (gdouble) blend_tool->starty, - PDB_FLOAT, (gdouble) blend_tool->endx, - PDB_FLOAT, (gdouble) blend_tool->endy, - PDB_END); - - if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS) - gdisplays_flush (); - else - g_message (_("Blend operation failed.")); - - procedural_db_destroy_args (return_vals, nreturn_vals); - -#else /* ! BLEND_UI_CALLS_VIA_PDB */ - - progress = progress_start (gdisp, _("Blending..."), FALSE, NULL, NULL); - - blend (gimage, - gimp_image_active_drawable (gimage), - blend_options->blend_mode, - gimp_context_get_paint_mode (NULL), - blend_options->gradient_type, - gimp_context_get_opacity (NULL) * 100, - blend_options->offset, - blend_options->repeat, - blend_options->supersample, - blend_options->max_depth, - blend_options->threshold, - blend_tool->startx, - blend_tool->starty, - blend_tool->endx, - blend_tool->endy, - progress ? progress_update_and_flush : (GimpProgressFunc) NULL, - progress); - - if (progress) - progress_end (progress); - - gdisplays_flush (); -#endif /* ! BLEND_UI_CALLS_VIA_PDB */ - } -} - -static void -blend_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - BlendTool *blend_tool; - gchar vector[STATUSBAR_SIZE]; - - blend_tool = (BlendTool *) tool->private; - - /* undraw the current tool */ - draw_core_pause (blend_tool->core, tool); - - /* Get the current coordinates */ - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &blend_tool->endx, &blend_tool->endy, FALSE, 1); - - - /* Restrict to multiples of 15 degrees if ctrl is pressed */ - if (mevent->state & GDK_CONTROL_MASK) - { - int tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; - int cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; - int dx, dy, i, radius, frac; - - dx = blend_tool->endx - blend_tool->startx; - dy = blend_tool->endy - blend_tool->starty; - - if (dy) - { - radius = sqrt (SQR (dx) + SQR (dy)); - frac = abs ((dx << 8) / dy); - for (i = 0; i < 6; i++) - { - if (frac < tangens2[i]) - break; - } - dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); - dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); - } - blend_tool->endx = blend_tool->startx + dx; - blend_tool->endy = blend_tool->starty + dy; - } - - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id); - if (gdisp->dot_for_dot) - { - g_snprintf (vector, sizeof (vector), gdisp->cursor_format_str, - _("Blend: "), - blend_tool->endx - blend_tool->startx, - ", ", - blend_tool->endy - blend_tool->starty); - } - else /* show real world units */ - { - gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit); - - g_snprintf (vector, sizeof (vector), gdisp->cursor_format_str, - _("Blend: "), - blend_tool->endx - blend_tool->startx * unit_factor / - gdisp->gimage->xresolution, - ", ", - blend_tool->endy - blend_tool->starty * unit_factor / - gdisp->gimage->yresolution); - } - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id, - vector); - - /* redraw the current tool */ - draw_core_resume (blend_tool->core, tool); -} - -static void -blend_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - switch (gimp_drawable_type (gimp_image_active_drawable (gdisp->gimage))) - { - case INDEXED_GIMAGE: - case INDEXEDA_GIMAGE: - gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, - BLEND, - CURSOR_MODIFIER_NONE, - FALSE); - break; - default: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - BLEND, - CURSOR_MODIFIER_NONE, - FALSE); - break; - } -} - -static void -blend_draw (Tool *tool) -{ - BlendTool *blend_tool; - gint tx1, ty1, tx2, ty2; - - blend_tool = (BlendTool *) tool->private; - - gdisplay_transform_coords (tool->gdisp, - blend_tool->startx, blend_tool->starty, - &tx1, &ty1, 1); - gdisplay_transform_coords (tool->gdisp, - blend_tool->endx, blend_tool->endy, - &tx2, &ty2, 1); - - /* Draw start target */ - gdk_draw_line (blend_tool->core->win, blend_tool->core->gc, - tx1 - (TARGET_WIDTH >> 1), ty1, - tx1 + (TARGET_WIDTH >> 1), ty1); - gdk_draw_line (blend_tool->core->win, blend_tool->core->gc, - tx1, ty1 - (TARGET_HEIGHT >> 1), - tx1, ty1 + (TARGET_HEIGHT >> 1)); - - /* Draw end target */ - gdk_draw_line (blend_tool->core->win, blend_tool->core->gc, - tx2 - (TARGET_WIDTH >> 1), ty2, - tx2 + (TARGET_WIDTH >> 1), ty2); - gdk_draw_line (blend_tool->core->win, blend_tool->core->gc, - tx2, ty2 - (TARGET_HEIGHT >> 1), - tx2, ty2 + (TARGET_HEIGHT >> 1)); - - /* Draw the line between the start and end coords */ - gdk_draw_line (blend_tool->core->win, blend_tool->core->gc, - tx1, ty1, tx2, ty2); -} - -static void -blend_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - BlendTool * blend_tool; - - blend_tool = (BlendTool *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (blend_tool->core, tool); - break; - - case RESUME: - draw_core_resume (blend_tool->core, tool); - break; - - case HALT: - draw_core_stop (blend_tool->core, tool); - break; - - default: - break; - } -} - - -static void -blend_options_drop_gradient (GtkWidget *widget, - gradient_t *gradient, - gpointer data) -{ - gimp_context_set_gradient (gimp_context_get_user (), gradient); - gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->blend_mode_w), - CUSTOM_MODE); - blend_options->blend_mode = CUSTOM_MODE; -} - -static void -blend_options_drop_tool (GtkWidget *widget, - ToolType tool, - gpointer data) -{ - gimp_context_set_tool (gimp_context_get_user (), tool); -} - - -/* The actual blending procedure */ - -void -blend (GImage *gimage, - GimpDrawable *drawable, - BlendMode blend_mode, - int paint_mode, - GradientType gradient_type, - double opacity, - double offset, - RepeatMode repeat, - int supersample, - int max_depth, - double threshold, - double startx, - double starty, - double endx, - double endy, - GimpProgressFunc progress_callback, - gpointer progress_data) -{ - TileManager *buf_tiles; - PixelRegion bufPR; - gint has_alpha; - gint has_selection; - gint bytes; - gint x1, y1, x2, y2; - - gimp_add_busy_cursors(); - - has_selection = gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); - - has_alpha = gimp_drawable_has_alpha (drawable); - bytes = gimp_drawable_bytes (drawable); - - /* Always create an alpha temp buf (for generality) */ - if (! has_alpha) - { - has_alpha = TRUE; - bytes += 1; - } - - buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes); - pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE); - - gradient_fill_region (gimage, drawable, - &bufPR, (x2 - x1), (y2 - y1), - blend_mode, gradient_type, offset, repeat, - supersample, max_depth, threshold, - (startx - x1), (starty - y1), - (endx - x1), (endy - y1), - progress_callback, progress_data); - - pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &bufPR, TRUE, - (opacity * 255) / 100, paint_mode, NULL, x1, y1); - - /* update the image */ - drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); - - /* free the temporary buffer */ - tile_manager_destroy (buf_tiles); - - gimp_remove_busy_cursors (NULL); -} - -static gdouble -gradient_calc_conical_sym_factor (gdouble dist, - gdouble *axis, - gdouble offset, - gdouble x, - gdouble y) -{ - gdouble vec[2]; - gdouble r; - gdouble rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else if ((x != 0) || (y != 0)) - { - /* Calculate offset from the start in pixels */ - - r = sqrt (x * x + y * y); - - vec[0] = x / r; - vec[1] = y / r; - - rat = axis[0] * vec[0] + axis[1] * vec[1]; /* Dot product */ - - if (rat > 1.0) - rat = 1.0; - else if (rat < -1.0) - rat = -1.0; - - /* This cool idea is courtesy Josh MacDonald, - * Ali Rahimi --- two more XCF losers. */ - - rat = acos (rat) / G_PI; - rat = pow (rat, (offset / 10) + 1); - - rat = CLAMP (rat, 0.0, 1.0); - } - else - { - rat = 0.5; - } - - return rat; -} - -static gdouble -gradient_calc_conical_asym_factor (gdouble dist, - gdouble *axis, - gdouble offset, - gdouble x, - gdouble y) -{ - gdouble ang0, ang1; - gdouble ang; - gdouble rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else - { - if ((x != 0) || (y != 0)) - { - ang0 = atan2(axis[0], axis[1]) + G_PI; - ang1 = atan2(x, y) + G_PI; - - ang = ang1 - ang0; - - if (ang < 0.0) - ang += (2.0 * G_PI); - - rat = ang / (2.0 * G_PI); - rat = pow(rat, (offset / 10) + 1); - - rat = CLAMP(rat, 0.0, 1.0); - } - else - { - rat = 0.5; /* We are on middle point */ - } - } - - return rat; -} - -static gdouble -gradient_calc_square_factor (gdouble dist, - gdouble offset, - gdouble x, - gdouble y) -{ - gdouble r; - gdouble rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else - { - /* Calculate offset from start as a value in [0, 1] */ - - offset = offset / 100.0; - - r = MAX (abs (x), abs (y)); - rat = r / dist; - - if (rat < offset) - rat = 0.0; - else if (offset == 1) - rat = (rat>=1) ? 1 : 0; - else - rat = (rat - offset) / (1.0 - offset); - } - - return rat; -} - -static gdouble -gradient_calc_radial_factor (gdouble dist, - gdouble offset, - gdouble x, - gdouble y) -{ - gdouble r; - gdouble rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else - { - /* Calculate radial offset from start as a value in [0, 1] */ - - offset = offset / 100.0; - - r = sqrt(SQR(x) + SQR(y)); - rat = r / dist; - - if (rat < offset) - rat = 0.0; - else if (offset == 1) - rat = (rat>=1) ? 1 : 0; - else - rat = (rat - offset) / (1.0 - offset); - } - - return rat; -} - -static gdouble -gradient_calc_linear_factor (gdouble dist, - gdouble *vec, - gdouble offset, - gdouble x, - gdouble y) -{ - double r; - double rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else - { - offset = offset / 100.0; - - r = vec[0] * x + vec[1] * y; - rat = r / dist; - - if (rat < offset) - rat = 0.0; - else if (offset == 1) - rat = (rat>=1) ? 1 : 0; - else - rat = (rat - offset) / (1.0 - offset); - } - - return rat; -} - -static gdouble -gradient_calc_bilinear_factor (gdouble dist, - gdouble *vec, - gdouble offset, - gdouble x, - gdouble y) -{ - gdouble r; - gdouble rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else - { - /* Calculate linear offset from the start line outward */ - - offset = offset / 100.0; - - r = vec[0] * x + vec[1] * y; - rat = r / dist; - - if (fabs(rat) < offset) - rat = 0.0; - else if (offset == 1) - rat = (rat>=1) ? 1 : 0; - else - rat = (fabs(rat) - offset) / (1.0 - offset); - } - - return rat; -} - -static gdouble -gradient_calc_spiral_factor (gdouble dist, - gdouble *axis, - gdouble offset, - gdouble x, - gdouble y, - gint cwise) -{ - gdouble ang0, ang1; - gdouble ang, r; - gdouble rat; - - if (dist == 0.0) - { - rat = 0.0; - } - else - { - if (x != 0.0 || y != 0.0) - { - ang0 = atan2 (axis[0], axis[1]) + G_PI; - ang1 = atan2 (x, y) + G_PI; - if(!cwise) - ang = ang0 - ang1; - else - ang = ang1 - ang0; - - if (ang < 0.0) - ang += (2.0 * G_PI); - - r = sqrt (x * x + y * y) / dist; - rat = ang / (2.0 * G_PI) + r + offset; - rat = fmod (rat, 1.0); - } - else - rat = 0.5 ; /* We are on the middle point */ - } - - return rat; -} - -static gdouble -gradient_calc_shapeburst_angular_factor (gdouble x, - gdouble y) -{ - gint ix, iy; - Tile *tile; - gfloat value; - - ix = (int) CLAMP (x, 0, distR.w); - iy = (int) CLAMP (y, 0, distR.h); - tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE); - value = 1.0 - *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT)); - tile_release (tile, FALSE); - - return value; -} - - -static gdouble -gradient_calc_shapeburst_spherical_factor (gdouble x, - gdouble y) -{ - gint ix, iy; - Tile *tile; - gfloat value; - - ix = (int) CLAMP (x, 0, distR.w); - iy = (int) CLAMP (y, 0, distR.h); - tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE); - value = *((gfloat *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT)); - value = 1.0 - sin (0.5 * G_PI * value); - tile_release (tile, FALSE); - - return value; -} - - -static gdouble -gradient_calc_shapeburst_dimpled_factor (gdouble x, - gdouble y) -{ - gint ix, iy; - Tile *tile; - gfloat value; - - ix = (int) CLAMP (x, 0, distR.w); - iy = (int) CLAMP (y, 0, distR.h); - tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE); - value = *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT)); - value = cos (0.5 * G_PI * value); - tile_release (tile, FALSE); - - return value; -} - -static gdouble -gradient_repeat_none (gdouble val) -{ - return CLAMP (val, 0.0, 1.0); -} - -static gdouble -gradient_repeat_sawtooth (gdouble val) -{ - if (val >= 0.0) - return fmod (val, 1.0); - else - return 1.0 - fmod (-val, 1.0); -} - -static gdouble -gradient_repeat_triangular (gdouble val) -{ - gint ival; - - if (val < 0.0) - val = -val; - - ival = (int) val; - - if (ival & 1) - return 1.0 - fmod (val, 1.0); - else - return fmod (val, 1.0); -} - -/*****/ -static void -gradient_precalc_shapeburst (GImage *gimage, - GimpDrawable *drawable, - PixelRegion *PR, - gdouble dist) -{ - Channel *mask; - PixelRegion tempR; - gfloat max_iteration; - gfloat *distp; - gint size; - gpointer pr; - guchar white[1] = { OPAQUE_OPACITY }; - - /* allocate the distance map */ - if (distR.tiles) - tile_manager_destroy (distR.tiles); - distR.tiles = tile_manager_new (PR->w, PR->h, sizeof (gfloat)); - - /* allocate the selection mask copy */ - tempR.tiles = tile_manager_new (PR->w, PR->h, 1); - pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE); - - /* If the gimage mask is not empty, use it as the shape burst source */ - if (! gimage_mask_is_empty (gimage)) - { - PixelRegion maskR; - gint x1, y1, x2, y2; - gint offx, offy; - - gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); - gimp_drawable_offsets (drawable, &offx, &offy); - - /* the selection mask */ - mask = gimp_image_get_mask (gimage); - pixel_region_init (&maskR, gimp_drawable_data (GIMP_DRAWABLE (mask)), - x1 + offx, y1 + offy, (x2 - x1), (y2 - y1), FALSE); - - /* copy the mask to the temp mask */ - copy_region (&maskR, &tempR); - } - /* otherwise... */ - else - { - /* If the intended drawable has an alpha channel, use that */ - if (gimp_drawable_has_alpha (drawable)) - { - PixelRegion drawableR; - - pixel_region_init (&drawableR, gimp_drawable_data (drawable), - PR->x, PR->y, PR->w, PR->h, FALSE); - - extract_alpha_region (&drawableR, NULL, &tempR); - } - else - { - /* Otherwise, just fill the shapeburst to white */ - color_region (&tempR, white); - } - } - - pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE); - pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE); - max_iteration = shapeburst_region (&tempR, &distR); - - /* normalize the shapeburst with the max iteration */ - if (max_iteration > 0) - { - pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE); - - for (pr = pixel_regions_register (1, &distR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - distp = (gfloat *) distR.data; - size = distR.w * distR.h; - - while (size--) - *distp++ /= max_iteration; - } - - pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, FALSE); - } - - tile_manager_destroy (tempR.tiles); -} - - -static void -gradient_render_pixel (double x, - double y, - GimpRGB *color, - gpointer render_data) -{ - RenderBlendData *rbd; - gdouble factor; - - rbd = render_data; - - /* Calculate blending factor */ - - switch (rbd->gradient_type) - { - case RADIAL: - factor = gradient_calc_radial_factor (rbd->dist, rbd->offset, - x - rbd->sx, y - rbd->sy); - break; - - case CONICAL_SYMMETRIC: - factor = gradient_calc_conical_sym_factor (rbd->dist, rbd->vec, rbd->offset, - x - rbd->sx, y - rbd->sy); - break; - - case CONICAL_ASYMMETRIC: - factor = gradient_calc_conical_asym_factor (rbd->dist, rbd->vec, rbd->offset, - x - rbd->sx, y - rbd->sy); - break; - - case SQUARE: - factor = gradient_calc_square_factor (rbd->dist, rbd->offset, - x - rbd->sx, y - rbd->sy); - break; - - case LINEAR: - factor = gradient_calc_linear_factor (rbd->dist, rbd->vec, rbd->offset, - x - rbd->sx, y - rbd->sy); - break; - - case BILINEAR: - factor = gradient_calc_bilinear_factor (rbd->dist, rbd->vec, rbd->offset, - x - rbd->sx, y - rbd->sy); - break; - - case SHAPEBURST_ANGULAR: - factor = gradient_calc_shapeburst_angular_factor (x, y); - break; - - case SHAPEBURST_SPHERICAL: - factor = gradient_calc_shapeburst_spherical_factor (x, y); - break; - - case SHAPEBURST_DIMPLED: - factor = gradient_calc_shapeburst_dimpled_factor (x, y); - break; - - case SPIRAL_CLOCKWISE: - factor = gradient_calc_spiral_factor (rbd->dist, rbd->vec, rbd->offset, - x - rbd->sx, y - rbd->sy,TRUE); - break; - - case SPIRAL_ANTICLOCKWISE: - factor = gradient_calc_spiral_factor (rbd->dist, rbd->vec, rbd->offset, - x - rbd->sx, y - rbd->sy,FALSE); - break; - - default: - gimp_fatal_error ("gradient_render_pixel(): Unknown gradient type %d", - (int) rbd->gradient_type); - return; - } - - /* Adjust for repeat */ - - factor = (*rbd->repeat_func)(factor); - - /* Blend the colors */ - - if (rbd->blend_mode == CUSTOM_MODE) - { - gradient_get_color_at (gimp_context_get_gradient (NULL), factor, color); - } - else - { - /* Blend values */ - - color->r = rbd->fg.r + (rbd->bg.r - rbd->fg.r) * factor; - color->g = rbd->fg.g + (rbd->bg.g - rbd->fg.g) * factor; - color->b = rbd->fg.b + (rbd->bg.b - rbd->fg.b) * factor; - color->a = rbd->fg.a + (rbd->bg.a - rbd->fg.a) * factor; - - if (rbd->blend_mode == FG_BG_HSV_MODE) - gimp_hsv_to_rgb_double (&color->r, &color->g, &color->b); - } -} - -static void -gradient_put_pixel (int x, - int y, - GimpRGB color, - void *put_pixel_data) -{ - PutPixelData *ppd; - guchar *data; - - ppd = put_pixel_data; - - /* Paint */ - - data = ppd->row_data + ppd->bytes * x; - - if (ppd->bytes >= 3) - { - *data++ = color.r * 255.0; - *data++ = color.g * 255.0; - *data++ = color.b * 255.0; - *data++ = color.a * 255.0; - } - else - { - /* Convert to grayscale */ - - *data++ = 255.0 * INTENSITY (color.r, color.g, color.b); - *data++ = color.a * 255.0; - } - - /* Paint whole row if we are on the rightmost pixel */ - - if (x == (ppd->width - 1)) - pixel_region_set_row(ppd->PR, 0, y, ppd->width, ppd->row_data); -} - -static void -gradient_fill_region (GImage *gimage, - GimpDrawable *drawable, - PixelRegion *PR, - gint width, - gint height, - BlendMode blend_mode, - GradientType gradient_type, - gdouble offset, - RepeatMode repeat, - gint supersample, - gint max_depth, - gdouble threshold, - gdouble sx, - gdouble sy, - gdouble ex, - gdouble ey, - GimpProgressFunc progress_callback, - gpointer progress_data) -{ - RenderBlendData rbd; - PutPixelData ppd; - gint x, y; - gint endx, endy; - gpointer *pr; - guchar *data; - GimpRGB color; - - /* Get foreground and background colors, normalized */ - - gimp_context_get_foreground (NULL, &rbd.fg); - - /* rbd.fg.a = 1.0; */ /* Foreground is always opaque */ - - gimp_context_get_background (NULL, &rbd.bg); - - /* rbd.bg.a = 1.0; */ /* opaque, for now */ - - switch (blend_mode) - { - case FG_BG_RGB_MODE: - break; - - case FG_BG_HSV_MODE: - /* Convert to HSV */ - - gimp_rgb_to_hsv_double (&rbd.fg.r, &rbd.fg.g, &rbd.fg.b); - gimp_rgb_to_hsv_double (&rbd.bg.r, &rbd.bg.g, &rbd.bg.b); - - break; - - case FG_TRANS_MODE: - /* Color does not change, just the opacity */ - - rbd.bg = rbd.fg; - rbd.bg.a = 0.0; /* transparent */ - - break; - - case CUSTOM_MODE: - break; - - default: - gimp_fatal_error ("gradient_fill_region(): Unknown blend mode %d", - (gint) blend_mode); - break; - } - - /* Calculate type-specific parameters */ - - switch (gradient_type) - { - case RADIAL: - rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy)); - break; - - case SQUARE: - rbd.dist = MAX (fabs (ex - sx), fabs (ey - sy)); - break; - - case CONICAL_SYMMETRIC: - case CONICAL_ASYMMETRIC: - case SPIRAL_CLOCKWISE: - case SPIRAL_ANTICLOCKWISE: - case LINEAR: - case BILINEAR: - rbd.dist = sqrt (SQR (ex - sx) + SQR (ey - sy)); - - if (rbd.dist > 0.0) - { - rbd.vec[0] = (ex - sx) / rbd.dist; - rbd.vec[1] = (ey - sy) / rbd.dist; - } - - break; - - case SHAPEBURST_ANGULAR: - case SHAPEBURST_SPHERICAL: - case SHAPEBURST_DIMPLED: - rbd.dist = sqrt (SQR (ex - sx) + SQR (ey - sy)); - gradient_precalc_shapeburst (gimage, drawable, PR, rbd.dist); - break; - - default: - gimp_fatal_error ("gradient_fill_region(): Unknown gradient type %d", - (gint) gradient_type); - break; - } - - /* Set repeat function */ - - switch (repeat) - { - case REPEAT_NONE: - rbd.repeat_func = gradient_repeat_none; - break; - - case REPEAT_SAWTOOTH: - rbd.repeat_func = gradient_repeat_sawtooth; - break; - - case REPEAT_TRIANGULAR: - rbd.repeat_func = gradient_repeat_triangular; - break; - - default: - gimp_fatal_error ("gradient_fill_region(): Unknown repeat mode %d", - (gint) repeat); - break; - } - - /* Initialize render data */ - - rbd.offset = offset; - rbd.sx = sx; - rbd.sy = sy; - rbd.blend_mode = blend_mode; - rbd.gradient_type = gradient_type; - - /* Render the gradient! */ - - if (supersample) - { - /* Initialize put pixel data */ - - ppd.PR = PR; - ppd.row_data = g_malloc (width * PR->bytes); - ppd.bytes = PR->bytes; - ppd.width = width; - - /* Render! */ - - adaptive_supersample_area (0, 0, (width - 1), (height - 1), - max_depth, threshold, - gradient_render_pixel, &rbd, - gradient_put_pixel, &ppd, - progress_callback, progress_data); - - /* Clean up */ - - g_free (ppd.row_data); - } - else - { - gint max_progress = PR->w * PR->h; - gint progress = 0; - - for (pr = pixel_regions_register(1, PR); - pr != NULL; - pr = pixel_regions_process(pr)) - { - data = PR->data; - endx = PR->x + PR->w; - endy = PR->y + PR->h; - - for (y = PR->y; y < endy; y++) - for (x = PR->x; x < endx; x++) - { - gradient_render_pixel(x, y, &color, &rbd); - - if (PR->bytes >= 3) - { - *data++ = color.r * 255.0; - *data++ = color.g * 255.0; - *data++ = color.b * 255.0; - *data++ = color.a * 255.0; - } - else - { - /* Convert to grayscale */ - - *data++ = 255.0 * INTENSITY (color.r, color.g, color.b); - *data++ = color.a * 255.0; - } - } - - progress += PR->w * PR->h; - if (progress_callback) - (* progress_callback) (0, max_progress, progress, progress_data); - } - } -} - -/****************************/ -/* Global blend functions */ -/****************************/ - -Tool * -tools_new_blend (void) -{ - Tool *tool; - BlendTool *private; - - /* The tool options */ - if (! blend_options) - { - blend_options = blend_options_new (); - tools_register (BLEND, (ToolOptions *) blend_options); - } - - tool = tools_new_tool (BLEND); - private = g_new0 (BlendTool, 1); - - private->core = draw_core_new (blend_draw); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - - tool->private = (void *) private; - - tool->button_press_func = blend_button_press; - tool->button_release_func = blend_button_release; - tool->motion_func = blend_motion; - tool->cursor_update_func = blend_cursor_update; - tool->control_func = blend_control; - - return tool; -} - -void -tools_free_blend (Tool *tool) -{ - BlendTool *blend_tool; - - blend_tool = (BlendTool *) tool->private; - - if (tool->state == ACTIVE) - draw_core_stop (blend_tool->core, tool); - - draw_core_free (blend_tool->core); - - /* free the distance map data if it exists */ - if (distR.tiles) - tile_manager_destroy (distR.tiles); - distR.tiles = NULL; - - g_free (blend_tool); -} diff --git a/app/blend.h b/app/blend.h deleted file mode 100644 index e0d8bd3874..0000000000 --- a/app/blend.h +++ /dev/null @@ -1,78 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BLEND_H__ -#define __BLEND_H__ - - -typedef enum -{ - LINEAR, - BILINEAR, - RADIAL, - SQUARE, - CONICAL_SYMMETRIC, - CONICAL_ASYMMETRIC, - SHAPEBURST_ANGULAR, - SHAPEBURST_SPHERICAL, - SHAPEBURST_DIMPLED, - SPIRAL_CLOCKWISE, - SPIRAL_ANTICLOCKWISE, - GRADIENT_TYPE_LAST /*< skip >*/ -} GradientType; - -typedef enum /*< chop=_MODE >*/ -{ - FG_BG_RGB_MODE, - FG_BG_HSV_MODE, - FG_TRANS_MODE, - CUSTOM_MODE, - BLEND_MODE_LAST /*< skip >*/ -} BlendMode; - -typedef enum -{ - REPEAT_NONE, - REPEAT_SAWTOOTH, - REPEAT_TRIANGULAR, - REPEAT_LAST /*< skip >*/ -} RepeatMode; - -void blend (GimpImage *gimage, - GimpDrawable *drawable, - BlendMode blend_mode, - gint paint_mode, - GradientType gradient_type, - gdouble opacity, - gdouble offset, - RepeatMode repeat, - gint supersample, - gint max_depth, - gdouble threshold, - gdouble startx, - gdouble starty, - gdouble endx, - gdouble endy, - GimpProgressFunc progress_callback, - gpointer progress_data); - -Tool * tools_new_blend (void); -void tools_free_blend (Tool *tool); - - -#endif /* __BLEND_H__ */ diff --git a/app/blob.c b/app/blob.c deleted file mode 100644 index 5d7d6d2cc1..0000000000 --- a/app/blob.c +++ /dev/null @@ -1,774 +0,0 @@ -/* blob.c: routines for manipulating scan converted convex - * polygons. - * - * Copyright 1998-1999, Owen Taylor - * - * > Please contact the above author before modifying the copy < - * > of this file in the GIMP distribution. Thanks. < - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "config.h" - -#include -#include -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "blob.h" - -#include "libgimp/gimpmath.h" - - -static Blob * -blob_new (int y, int height) -{ - Blob *result; - - result = g_malloc (sizeof (Blob) + sizeof(BlobSpan) * (height-1)); - result->y = y; - result->height = height; - - return result; -} - -typedef enum { - EDGE_NONE = 0, - EDGE_LEFT = 1 << 0, - EDGE_RIGHT = 1 << 1 -} EdgeType; - -static void -blob_fill (Blob *b, EdgeType *present) -{ - int start; - int x1, x2, i1, i2; - int i; - - /* Mark empty lines at top and bottom as unused */ - - start = 0; - while (!(present[start])) - { - b->data[start].left = 0; - b->data[start].right = -1; - start++; - } - if (present[start] != (EDGE_RIGHT | EDGE_LEFT)) - { - if (present[start] == EDGE_RIGHT) - b->data[start].left = b->data[start].right; - else - b->data[start].right = b->data[start].left; - - present[start] = EDGE_RIGHT | EDGE_LEFT; - } - - for (i=b->height-1;!present[i];i--) - { - b->data[i].left = 0; - b->data[i].right = -1; - } - if (present[i] != (EDGE_RIGHT | EDGE_LEFT)) - { - if (present[i] == EDGE_RIGHT) - b->data[i].left = b->data[i].right; - else - b->data[i].right = b->data[i].left; - - present[i] = EDGE_RIGHT | EDGE_LEFT; - } - - - /* Restore missing edges */ - - /* We fill only interior regions of convex hull, as if we were filling - polygons. But since we draw ellipses with nearest points, not interior - points, maybe it would look better if we did the same here. Probably - not a big deal either way after anti-aliasing */ - - /* left edge */ - for (i1=start; i1height-2; i1++) - { - /* Find empty gaps */ - if (!(present[i1+1] & EDGE_LEFT)) - { - int increment; /* fractional part */ - int denom; /* denominator of fraction */ - int step; /* integral step */ - int frac; /* fractional step */ - int reverse; - - /* find bottom of gap */ - i2 = i1+2; - while (!(present[i2] & EDGE_LEFT) && i2 < b->height) i2++; - - if (i2 < b->height) - { - denom = i2-i1; - x1 = b->data[i1].left; - x2 = b->data[i2].left; - step = (x2-x1)/denom; - frac = x2-x1 - step*denom; - if (frac < 0) - { - frac = -frac; - reverse = 1; - } - else - reverse = 0; - - increment = 0; - for (i=i1+1; i= denom) - { - increment -= denom; - x1 += reverse ? -1 : 1; - } - if (increment == 0 || reverse) - b->data[i].left = x1; - else - b->data[i].left = x1 + 1; - } - } - i1 = i2-1; /* advance to next possibility */ - } - } - - /* right edge */ - for (i1=start; i1height-2; i1++) - { - /* Find empty gaps */ - if (!(present[i1+1] & EDGE_RIGHT)) - { - int increment; /* fractional part */ - int denom; /* denominator of fraction */ - int step; /* integral step */ - int frac; /* fractional step */ - int reverse; - - /* find bottom of gap */ - i2 = i1+2; - while (!(present[i2] & EDGE_RIGHT) && i2 < b->height) i2++; - - if (i2 < b->height) - { - denom = i2-i1; - x1 = b->data[i1].right; - x2 = b->data[i2].right; - step = (x2-x1)/denom; - frac = x2-x1 - step*denom; - if (frac < 0) - { - frac = -frac; - reverse = 1; - } - else - reverse = 0; - - increment = 0; - for (i=i1+1; i= denom) - { - increment -= denom; - x1 += reverse ? -1 : 1; - } - if (reverse && increment != 0) - b->data[i].right = x1 - 1; - else - b->data[i].right = x1; - } - } - i1 = i2-1; /* advance to next possibility */ - } - } - -} - -static void -blob_make_convex (Blob *b, EdgeType *present) -{ - int x1, x2, y1, y2, i1, i2; - int i; - int start; - - /* Walk through edges, deleting points that aren't on convex hull */ - - start = 0; - while (!(present[start])) start++; - - /* left edge */ - - i1 = start-1; - i2 = start; - x1 = b->data[start].left - b->data[start].right; - y1 = 0; - - for (i=start+1;iheight;i++) - { - if (!(present[i] & EDGE_LEFT)) - continue; - - x2 = b->data[i].left - b->data[i2].left; - y2 = i-i2; - - while (x2*y1 - x1*y2 < 0) /* clockwise rotation */ - { - present[i2] &= ~EDGE_LEFT; - i2 = i1; - while (!(present[--i1] & EDGE_LEFT) && i1>=start); - - if (i1data[start].left - b->data[start].right; - y1 = 0; - } - else - { - x1 = b->data[i2].left - b->data[i1].left; - y1 = i2 - i1; - } - x2 = b->data[i].left - b->data[i2].left; - y2 = i - i2; - } - x1 = x2; - y1 = y2; - i1 = i2; - i2 = i; - } - - /* Right edge */ - - i1 = start -1; - i2 = start; - x1 = b->data[start].right - b->data[start].left; - y1 = 0; - - for (i=start+1;iheight;i++) - { - if (!(present[i] & EDGE_RIGHT)) - continue; - - x2 = b->data[i].right - b->data[i2].right; - y2 = i-i2; - - while (x2*y1 - x1*y2 > 0) /* counter-clockwise rotation */ - { - present[i2] &= ~EDGE_RIGHT; - i2 = i1; - while (!(present[--i1] & EDGE_RIGHT) && i1>=start); - - if (i1data[start].right - b->data[start].left; - y1 = 0; - } - else - { - x1 = b->data[i2].right - b->data[i1].right; - y1 = i2 - i1; - } - x2 = b->data[i].right - b->data[i2].right; - y2 = i - i2; - } - x1 = x2; - y1 = y2; - i1 = i2; - i2 = i; - } - - blob_fill (b, present); -} - -Blob * -blob_convex_union (Blob *b1, Blob *b2) -{ - Blob *result; - int y; - int i, j; - EdgeType *present; - - /* Create the storage for the result */ - - y = MIN(b1->y,b2->y); - result = blob_new (y, MAX(b1->y+b1->height,b2->y+b2->height)-y); - - if (result->height == 0) - return result; - - present = g_new0 (EdgeType, result->height); - - /* Initialize spans from original objects */ - - for (i=0, j=b1->y-y; iheight; i++,j++) - { - if (b1->data[i].right >= b1->data[i].left) - { - present[j] = EDGE_LEFT | EDGE_RIGHT; - result->data[j].left = b1->data[i].left; - result->data[j].right = b1->data[i].right; - } - } - - for (i=0, j=b2->y-y; iheight; i++,j++) - { - if (b2->data[i].right >= b2->data[i].left) - { - if (present[j]) - { - if (result->data[j].left > b2->data[i].left) - result->data[j].left = b2->data[i].left; - if (result->data[j].right < b2->data[i].right) - result->data[j].right = b2->data[i].right; - } - else - { - present[j] = EDGE_LEFT | EDGE_RIGHT; - result->data[j].left = b2->data[i].left; - result->data[j].right = b2->data[i].right; - } - } - } - - blob_make_convex (result, present); - - g_free (present); - return result; -} - -static void -blob_line_add_pixel (Blob *b, int x, int y) -{ - if (b->data[y-b->y].left > b->data[y-b->y].right) - b->data[y-b->y].left = b->data[y-b->y].right = x; - else - { - b->data[y-b->y].left = MIN (b->data[y-b->y].left, x); - b->data[y-b->y].right = MAX (b->data[y-b->y].right, x); - } -} - -void -blob_line (Blob *b, int x0, int y0, int x1, int y1) -{ - int dx, dy, d; - int incrE, incrNE; - int x, y; - - int xstep = 1; - int ystep = 1; - - dx = x1 - x0; - dy = y1 - y0; - - if (dx < 0) - { - dx = -dx; - xstep = -1; - } - - if (dy < 0) - { - dy = -dy; - ystep = -1; - } - - /* for (y = y0; y != y1 + ystep ; y += ystep) - { - b->data[y-b->y].left = 0; - b->data[y-b->y].right = -1; - }*/ - - x = x0; - y = y0; - - if (dy < dx) - { - d = 2*dy - dx; /* initial value of d */ - incrE = 2 * dy; /* increment used for move to E */ - incrNE = 2 * (dy-dx); /* increment used for move to NE */ - - blob_line_add_pixel (b, x, y); - - while (x != x1) - { - if (d <= 0) - { - d += incrE; - x += xstep; - } - else - { - d += incrNE; - x += xstep; - y += ystep; - } - blob_line_add_pixel (b, x, y); - } - } - else - { - d = 2*dx - dy; /* initial value of d */ - incrE = 2 * dx; /* increment used for move to E */ - incrNE = 2 * (dx-dy); /* increment used for move to NE */ - - blob_line_add_pixel (b, x, y); - - while (y != y1) - { - if (d <= 0) - { - d += incrE; - y += ystep; - } - else - { - d += incrNE; - x += xstep; - y += ystep; - } - blob_line_add_pixel (b, x, y); - } - } -} - -#define TABLE_SIZE 256 - -#define ELLIPSE_SHIFT 2 -#define TABLE_SHIFT 12 -#define TOTAL_SHIFT (ELLIPSE_SHIFT + TABLE_SHIFT) - -/* - * The choose of this values limits the maximal image_size to - * 16384 x 16384 pixels. The values will overflow as soon as - * x or y > INT_MAX / (1 << (ELLIPSE_SHIFT + TABLE_SHIFT)) / SUBSAMPLE - * - * Alternatively the code could be change the code as follows: - * - * xc_base = floor (xc) - * xc_shift = 0.5 + (xc - xc_base) * (1 << TOTAL_SHIFT); - * - * gint x = xc_base + (xc_shift + c * xp_shift + s * xq_shift + - * (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - * - * which would change the limit from the image to the ellipse size - */ - -static int trig_initialized = 0; -static int trig_table[TABLE_SIZE]; - -/* Return blob for the given (convex) polygon - */ -Blob * -blob_polygon (BlobPoint *points, int npoints) -{ - int i; - int im1; - int ip1; - int ymin, ymax; - Blob *result; - EdgeType *present; - - ymax = points[0].y; - ymin = points[0].y; - - for (i=1; i < npoints; i++) - { - if (points[i].y > ymax) - ymax = points[i].y; - if (points[i].y < ymin) - ymin = points[i].y; - } - - result = blob_new (ymin, ymax - ymin + 1); - present = g_new0 (EdgeType, result->height); - - im1 = npoints - 1; - i = 0; - ip1 = 1; - - for (; i < npoints ; i++) - { - int sides = 0; - int j = points[i].y - ymin; - - if (points[i].y < points[im1].y) - sides |= EDGE_RIGHT; - else if (points[i].y > points[im1].y) - sides |= EDGE_LEFT; - - if (points[ip1].y < points[i].y) - sides |= EDGE_RIGHT; - else if (points[ip1].y > points[i].y) - sides |= EDGE_LEFT; - - if (sides & EDGE_RIGHT) - { - if (present[j] & EDGE_RIGHT) - { - result->data[j].right = MAX (result->data[j].right, points[i].x); - } - else - { - present[j] |= EDGE_RIGHT; - result->data[j].right = points[i].x; - } - } - - if (sides & EDGE_LEFT) - { - if (present[j] & EDGE_LEFT) - { - result->data[j].left = MIN (result->data[j].left, points[i].x); - } - else - { - present[j] |= EDGE_LEFT; - result->data[j].left = points[i].x; - } - } - - im1 = i; - ip1++; - if (ip1 == npoints) - ip1 = 0; - } - - blob_fill (result, present); - g_free (present); - - return result; -} - -/* Scan convert a square specified by _offsets_ of major and - minor axes, and by center into a blob */ -Blob * -blob_square (double xc, double yc, double xp, double yp, double xq, double yq) -{ - BlobPoint points[4]; - - /* Make sure we order points ccw */ - - if (xp * yq - yq * xp < 0) - { - xq = -xq; - yq = -yq; - } - - points[0].x = xc + xp + xq; - points[0].y = yc + yp + yq; - points[1].x = xc + xp - xq; - points[1].y = yc + yp - yq; - points[2].x = xc - xp - xq; - points[2].y = yc - yp - yq; - points[3].x = xc - xp + xq; - points[3].y = yc - yp + yq; - - return blob_polygon (points, 4); -} - -/* Scan convert a diamond specified by _offsets_ of major and - minor axes, and by center into a blob */ -Blob * -blob_diamond (double xc, double yc, double xp, double yp, double xq, double yq) -{ - BlobPoint points[4]; - - /* Make sure we order points ccw */ - - if (xp * yq - yq * xp < 0) - { - xq = -xq; - yq = -yq; - } - - points[0].x = xc + xp; - points[0].y = yc + yp; - points[1].x = xc - xq; - points[1].y = yc - yq; - points[2].x = xc - xp; - points[2].y = yc - yp; - points[3].x = xc + xq; - points[3].y = yc + yq; - - return blob_polygon (points, 4); -} - -/* Scan convert an ellipse specified by _offsets_ of major and - minor axes, and by center into a blob */ -Blob * -blob_ellipse (double xc, double yc, double xp, double yp, double xq, double yq) -{ - int i; - Blob *r; - gdouble r1, r2; - gint maxy, miny; - gint step; - double max_radius; - - gint xc_shift, yc_shift; - gint xp_shift, yp_shift; - gint xq_shift, yq_shift; - - EdgeType *present; - - if (!trig_initialized) - { - trig_initialized = 1; - for (i=0; i<256; i++) - trig_table[i] = 0.5 + sin(i * (G_PI / 128.)) * (1 << TABLE_SHIFT); - } - - /* Make sure we traverse ellipse in ccw direction */ - - if (xp * yq - yq * xp < 0) - { - xq = -xq; - yq = -yq; - - } - - /* Compute bounds as if we were drawing a rectangle */ - - maxy = ceil (yc + fabs (yp) + fabs(yq)); - miny = floor (yc - fabs (yp) - fabs(yq)); - - r = blob_new (miny, maxy - miny + 1); - present = g_new0 (EdgeType, r->height); - - /* Figure out a step that will draw most of the points */ - - r1 = sqrt (xp * xp + yp * yp); - r2 = sqrt (xq * xq + yq * yq); - max_radius = MAX (r1, r2); - step = TABLE_SIZE; - - while (step > 1 && (TABLE_SIZE / step < 4*max_radius)) - step >>= 1; - - /* Fill in the edge points */ - - xc_shift = 0.5 + xc * (1 << TOTAL_SHIFT); - yc_shift = 0.5 + yc * (1 << TOTAL_SHIFT); - xp_shift = 0.5 + xp * (1 << ELLIPSE_SHIFT); - yp_shift = 0.5 + yp * (1 << ELLIPSE_SHIFT); - xq_shift = 0.5 + xq * (1 << ELLIPSE_SHIFT); - yq_shift = 0.5 + yq * (1 << ELLIPSE_SHIFT); - - for (i = 0 ; i < TABLE_SIZE ; i += step) - { - gint s = trig_table[i]; - gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE]; - - gint x = (xc_shift + c * xp_shift + s * xq_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT; - gint y = ((yc_shift + c * yp_shift + s * yq_shift + - (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - r->y; - - gint dydi = c * yq_shift - s * yp_shift; - - if (dydi <= 0) /* left edge */ - { - if (present[y] & EDGE_LEFT) - { - r->data[y].left = MIN (r->data[y].left, x); - } - else - { - present[y] |= EDGE_LEFT; - r->data[y].left = x; - } - } - - if (dydi >= 0) /* right edge */ - { - if (present[y] & EDGE_RIGHT) - { - r->data[y].right = MAX (r->data[y].right, x); - } - else - { - present[y] |= EDGE_RIGHT; - r->data[y].right = x; - } - } - } - - /* Now fill in missing points */ - - blob_fill (r, present); - g_free (present); - - return r; -} - -void -blob_bounds(Blob *b, int *x, int *y, int *width, int *height) -{ - int i; - int x0, x1, y0, y1; - - i = 0; - while (iheight && b->data[i].left > b->data[i].right) - i++; - - if (iheight) - { - y0 = b->y + i; - x0 = b->data[i].left; - x1 = b->data[i].right + 1; - while (iheight && b->data[i].left <= b->data[i].right) - { - x0 = MIN(b->data[i].left, x0); - x1 = MAX(b->data[i].right+1, x1); - i++; - } - y1 = b->y + i; - } - else - { - x0 = y0 = 0; - x1 = y1 = 0; - } - - *x = x0; - *y = y0; - *width = x1 - x0; - *height = y1 - y0; -} - -void -blob_dump(Blob *b) { - int i,j; - for (i=0; iheight; i++) - { - for (j=0;jdata[i].left;j++) - putchar(' '); - for (j=b->data[i].left;j<=b->data[i].right;j++) - putchar('*'); - putchar('\n'); - } -} diff --git a/app/blob.h b/app/blob.h deleted file mode 100644 index 3f7fd96646..0000000000 --- a/app/blob.h +++ /dev/null @@ -1,82 +0,0 @@ -/* blob.h: routines for manipulating scan converted convex - * polygons. - * - * Copyright 1998, Owen Taylor - * - * > Please contact the above author before modifying the copy < - * > of this file in the GIMP distribution. Thanks. < - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * -*/ - -#ifndef __BLOB_H__ -#define __BLOB_H__ - - -typedef struct _BlobPoint BlobPoint; -typedef struct _BlobSpan BlobSpan; -typedef struct _Blob Blob; - -struct _BlobPoint -{ - gint x; - gint y; -}; - -struct _BlobSpan -{ - gint left; - gint right; -}; - -struct _Blob -{ - gint y; - gint height; - BlobSpan data[1]; -}; - - -Blob * blob_convex_union (Blob *b1, - Blob *b2); -Blob * blob_polygon (BlobPoint *points, - gint npoints); -Blob * blob_square (gdouble xc, - gdouble yc, - gdouble xp, - gdouble yp, - gdouble xq, - gdouble yq); -Blob * blob_diamond (gdouble xc, - gdouble yc, - gdouble xp, - gdouble yp, - gdouble xq, - gdouble yq); -Blob * blob_ellipse (gdouble xc, - gdouble yc, - gdouble xp, - gdouble yp, - gdouble xq, - gdouble yq); -void blob_bounds (Blob *b, - gint *x, - gint *y, - gint *width, - gint *height); - - -#endif /* __BLOB_H__ */ diff --git a/app/brightness_contrast.c b/app/brightness_contrast.c deleted file mode 100644 index 1fc828e8c2..0000000000 --- a/app/brightness_contrast.c +++ /dev/null @@ -1,499 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "brightness_contrast.h" -#include "drawable.h" -#include "gimpcontext.h" -#include "gimplut.h" -#include "gimpui.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "image_map.h" -#include "lut_funcs.h" -#include "tool_options.h" -#include "tools.h" - -#include "libgimp/gimpintl.h" - -#define SLIDER_WIDTH 200 - -#define BRIGHTNESS 0x1 -#define CONTRAST 0x2 -#define ALL (BRIGHTNESS | CONTRAST) - -/* the brightness-contrast structures */ - -typedef struct _BrightnessContrast BrightnessContrast; - -struct _BrightnessContrast -{ - gint x, y; /* coords for last mouse click */ -}; - -typedef struct _BrightnessContrastDialog BrightnessContrastDialog; - -struct _BrightnessContrastDialog -{ - GtkWidget *shell; - GtkWidget *gimage_name; - - GtkAdjustment *brightness_data; - GtkAdjustment *contrast_data; - - GimpDrawable *drawable; - ImageMap image_map; - - gdouble brightness; - gdouble contrast; - - gboolean preview; - - GimpLut *lut; -}; - - -/* the brightness-contrast tool options */ -static ToolOptions *brightness_contrast_options = NULL; - -/* the brightness-contrast dialog */ -static BrightnessContrastDialog *brightness_contrast_dialog = NULL; - - -/* brightness contrast action functions */ - -static void brightness_contrast_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static BrightnessContrastDialog * brightness_contrast_dialog_new (void); - -static void brightness_contrast_update (BrightnessContrastDialog *, - gint); -static void brightness_contrast_preview (BrightnessContrastDialog *); -static void brightness_contrast_reset_callback (GtkWidget *, gpointer); -static void brightness_contrast_ok_callback (GtkWidget *, gpointer); -static void brightness_contrast_cancel_callback (GtkWidget *, gpointer); -static void brightness_contrast_preview_update (GtkWidget *, gpointer); -static void brightness_contrast_brightness_adjustment_update (GtkAdjustment *, - gpointer); -static void brightness_contrast_contrast_adjustment_update (GtkAdjustment *, - gpointer); - -/* brightness-contrast select action functions */ - -static void -brightness_contrast_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - brightness_contrast_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_brightness_contrast (void) -{ - Tool * tool; - BrightnessContrast * private; - - /* The tool options */ - if (!brightness_contrast_options) - { - brightness_contrast_options = - tool_options_new (_("Brightness-Contrast")); - tools_register (BRIGHTNESS_CONTRAST, brightness_contrast_options); - } - - tool = tools_new_tool (BRIGHTNESS_CONTRAST); - private = g_new0 (BrightnessContrast, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = brightness_contrast_control; - - return tool; -} - -void -brightness_contrast_dialog_hide (void) -{ - if (brightness_contrast_dialog) - brightness_contrast_cancel_callback (NULL, - (gpointer) brightness_contrast_dialog); -} - -void -tools_free_brightness_contrast (Tool *tool) -{ - BrightnessContrast * bc; - - bc = (BrightnessContrast *) tool->private; - - /* Close the brightness-contrast dialog */ - brightness_contrast_dialog_hide (); - - g_free (bc); -} - -void -brightness_contrast_initialize (GDisplay *gdisp) -{ - if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Brightness-Contrast does not operate on indexed drawables.")); - return; - } - - /* The brightness-contrast dialog */ - if (!brightness_contrast_dialog) - brightness_contrast_dialog = brightness_contrast_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (brightness_contrast_dialog->shell)) - gtk_widget_show (brightness_contrast_dialog->shell); - - brightness_contrast_dialog->brightness = 0.0; - brightness_contrast_dialog->contrast = 0.0; - - brightness_contrast_dialog->drawable = - gimp_image_active_drawable (gdisp->gimage); - brightness_contrast_dialog->image_map = - image_map_create (gdisp, brightness_contrast_dialog->drawable); - - brightness_contrast_update (brightness_contrast_dialog, ALL); -} - -/********************************/ -/* Brightness Contrast dialog */ -/********************************/ - -static BrightnessContrastDialog * -brightness_contrast_dialog_new (void) -{ - BrightnessContrastDialog *bcd; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *table; - GtkWidget *label; - GtkWidget *abox; - GtkWidget *spinbutton; - GtkWidget *slider; - GtkWidget *toggle; - GtkObject *data; - - bcd = g_new (BrightnessContrastDialog, 1); - bcd->preview = TRUE; - - bcd->lut = gimp_lut_new (); - - /* The shell and main vbox */ - bcd->shell = - gimp_dialog_new (_("Brightness-Contrast"), "brightness_contrast", - tools_help_func, NULL, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), brightness_contrast_ok_callback, - bcd, NULL, NULL, TRUE, FALSE, - _("Reset"), brightness_contrast_reset_callback, - bcd, NULL, NULL, TRUE, FALSE, - _("Cancel"), brightness_contrast_cancel_callback, - bcd, NULL, NULL, FALSE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (bcd->shell)->vbox), vbox); - - /* The table containing sliders */ - table = gtk_table_new (2, 3, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - /* Create the brightness scale widget */ - label = gtk_label_new (_("Brightness:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - data = gtk_adjustment_new (0, -127, 127.0, 1.0, 10.0, 0.0); - bcd->brightness_data = GTK_ADJUSTMENT (data); - slider = gtk_hscale_new (GTK_ADJUSTMENT (data)); - gtk_widget_set_usize (slider, SLIDER_WIDTH, -1); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1); - - abox = gtk_vbox_new (FALSE, 0); - spinbutton = gtk_spin_button_new (bcd->brightness_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0); - gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_signal_connect (GTK_OBJECT (data), "value_changed", - GTK_SIGNAL_FUNC (brightness_contrast_brightness_adjustment_update), - bcd); - - gtk_widget_show (label); - gtk_widget_show (slider); - gtk_widget_show (spinbutton); - gtk_widget_show (abox); - - /* Create the contrast scale widget */ - label = gtk_label_new (_("Contrast:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - data = gtk_adjustment_new (0, -127.0, 127.0, 1.0, 10.0, 0.0); - bcd->contrast_data = GTK_ADJUSTMENT (data); - slider = gtk_hscale_new (GTK_ADJUSTMENT (data)); - gtk_widget_set_usize (slider, SLIDER_WIDTH, -1); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2); - - abox = gtk_vbox_new (FALSE, 0); - spinbutton = gtk_spin_button_new (bcd->contrast_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0); - gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_signal_connect (GTK_OBJECT (data), "value_changed", - GTK_SIGNAL_FUNC (brightness_contrast_contrast_adjustment_update), - bcd); - - gtk_widget_show (label); - gtk_widget_show (slider); - gtk_widget_show (spinbutton); - gtk_widget_show (abox); - - /* Horizontal box for preview toggle button */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* The preview toggle */ - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bcd->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (brightness_contrast_preview_update), - bcd); - - gtk_widget_show (toggle); - gtk_widget_show (hbox); - - gtk_widget_show (table); - gtk_widget_show (vbox); - gtk_widget_show (bcd->shell); - - return bcd; -} - -static void -brightness_contrast_update (BrightnessContrastDialog *bcd, - gint update) -{ - if (update & BRIGHTNESS) - { - gtk_adjustment_set_value (bcd->brightness_data, bcd->brightness); - } - if (update & CONTRAST) - { - gtk_adjustment_set_value (bcd->contrast_data, bcd->contrast); - } -} - -static void -brightness_contrast_preview (BrightnessContrastDialog *bcd) -{ - if (!bcd->image_map) - { - g_message ("brightness_contrast_preview(): No image map"); - return; - } - - active_tool->preserve = TRUE; - brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0, - bcd->contrast / 127.0, - gimp_drawable_bytes (bcd->drawable)); - image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2, - (void *) bcd->lut); - active_tool->preserve = FALSE; -} - -static void -brightness_contrast_reset_callback (GtkWidget *widget, - gpointer data) -{ - BrightnessContrastDialog *bcd; - - bcd = (BrightnessContrastDialog *) data; - - bcd->brightness = 0.0; - bcd->contrast = 0.0; - - brightness_contrast_update (bcd, ALL); - - if (bcd->preview) - brightness_contrast_preview (bcd); -} - -static void -brightness_contrast_ok_callback (GtkWidget *widget, - gpointer data) -{ - BrightnessContrastDialog *bcd; - - bcd = (BrightnessContrastDialog *) data; - - gimp_dialog_hide (bcd->shell); - - active_tool->preserve = TRUE; - - if (!bcd->preview) - { - brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0, - bcd->contrast / 127.0, - gimp_drawable_bytes (bcd->drawable)); - image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2, - (void *) bcd->lut); - } - - if (bcd->image_map) - image_map_commit (bcd->image_map); - - active_tool->preserve = FALSE; - - bcd->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -brightness_contrast_cancel_callback (GtkWidget *widget, - gpointer data) -{ - BrightnessContrastDialog *bcd; - - bcd = (BrightnessContrastDialog *) data; - - gimp_dialog_hide (bcd->shell); - - if (bcd->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (bcd->image_map); - active_tool->preserve = FALSE; - - bcd->image_map = NULL; - gdisplays_flush (); - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -brightness_contrast_preview_update (GtkWidget *widget, - gpointer data) -{ - BrightnessContrastDialog *bcd; - - bcd = (BrightnessContrastDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - bcd->preview = TRUE; - brightness_contrast_preview (bcd); - } - else - { - bcd->preview = FALSE; - if (bcd->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (bcd->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } -} - -static void -brightness_contrast_brightness_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - BrightnessContrastDialog *bcd; - - bcd = (BrightnessContrastDialog *) data; - - if (bcd->brightness != adjustment->value) - { - bcd->brightness = adjustment->value; - - if (bcd->preview) - brightness_contrast_preview (bcd); - } -} - -static void -brightness_contrast_contrast_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - BrightnessContrastDialog *bcd; - - bcd = (BrightnessContrastDialog *) data; - - if (bcd->contrast != adjustment->value) - { - bcd->contrast = adjustment->value; - - if (bcd->preview) - brightness_contrast_preview (bcd); - } -} diff --git a/app/brightness_contrast.h b/app/brightness_contrast.h deleted file mode 100644 index 9cd9077287..0000000000 --- a/app/brightness_contrast.h +++ /dev/null @@ -1,31 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BRIGHTNESS_CONTRAST_H__ -#define __BRIGHTNESS_CONTRAST_H__ - - -Tool * tools_new_brightness_contrast (void); -void tools_free_brightness_contrast (Tool *tool); - -void brightness_contrast_dialog_hide (void); - -void brightness_contrast_initialize (GDisplay *gdisp); - - -#endif /* __BRIGHTNESS_CONTRAST_H__ */ diff --git a/app/brush_select.c b/app/brush_select.c index d5be3301cc..ff62d1345a 100644 --- a/app/brush_select.c +++ b/app/brush_select.c @@ -37,10 +37,11 @@ #include "gimplist.h" #include "gimprc.h" #include "gimpui.h" -#include "paint_options.h" #include "session.h" #include "temp_buf.h" +#include "tools/paint_options.h" + #include "pdb/procedural_db.h" #include "libgimp/gimphelpui.h" diff --git a/app/bucket_fill.c b/app/bucket_fill.c deleted file mode 100644 index b9a77539c9..0000000000 --- a/app/bucket_fill.c +++ /dev/null @@ -1,663 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "bucket_fill.h" -#include "channel.h" -#include "cursorutil.h" -#include "drawable.h" -#include "fuzzy_select.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimage_mask.h" -#include "gimpcontext.h" -#include "gimprc.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_options.h" -#include "patterns.h" -#include "pixel_region.h" -#include "selection.h" -#include "temp_buf.h" -#include "tile_manager.h" -#include "tools.h" -#include "undo.h" - -#include "pdb/procedural_db.h" - -#include "libgimp/gimpintl.h" - - -/* the bucket fill structures */ - -typedef struct _BucketTool BucketTool; - -struct _BucketTool -{ - gint target_x; /* starting x coord */ - gint target_y; /* starting y coord */ -}; - -typedef struct _BucketOptions BucketOptions; - -struct _BucketOptions -{ - PaintOptions paint_options; - - gboolean sample_merged; - gboolean sample_merged_d; - GtkWidget *sample_merged_w; - - gdouble threshold; - /* gdouble threshold_d; (from gimprc) */ - GtkObject *threshold_w; - - BucketFillMode fill_mode; - BucketFillMode fill_mode_d; - GtkWidget *fill_mode_w[3]; -}; - - -/* the bucket fill tool options */ -static BucketOptions *bucket_options = NULL; - - -/* local function prototypes */ - -static void bucket_fill_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void bucket_fill_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void bucket_fill_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); - -static void bucket_fill_line_color (guchar *, - guchar *, - guchar *, - gboolean , - gint , - gint ); -static void bucket_fill_line_pattern (guchar *, - guchar *, - TempBuf *, - gboolean , - gint , - gint , - gint , - gint ); - - -/* functions */ - -static void -bucket_options_reset (void) -{ - BucketOptions *options = bucket_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w), - options->sample_merged_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->threshold_w), - default_threshold); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->fill_mode_w[options->fill_mode_d]), TRUE); -} - -static BucketOptions * -bucket_options_new (void) -{ - BucketOptions *options; - - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *scale; - GtkWidget *frame; - - /* the new bucket fill tool options structure */ - options = g_new (BucketOptions, 1); - paint_options_init ((PaintOptions *) options, - BUCKET_FILL, - bucket_options_reset); - options->sample_merged = options->sample_merged_d = FALSE; - options->threshold = default_threshold; - options->fill_mode = options->fill_mode_d = FG_BUCKET_FILL; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* the sample merged toggle */ - options->sample_merged_w = - gtk_check_button_new_with_label (_("Sample Merged")); - gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->sample_merged); - gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0); - gtk_widget_show (options->sample_merged_w); - - /* the threshold scale */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Threshold:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - options->threshold_w = - gtk_adjustment_new (default_threshold, 1.0, 255.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w)); - gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->threshold_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->threshold); - gtk_widget_show (scale); - - gtk_widget_show (hbox); - - /* fill type */ - frame = - gimp_radio_group_new2 (TRUE, _("Fill Type"), - gimp_radio_button_update, - &options->fill_mode, (gpointer) options->fill_mode, - - _("FG Color Fill"), - (gpointer) FG_BUCKET_FILL, - &options->fill_mode_w[0], - _("BG Color Fill"), - (gpointer) BG_BUCKET_FILL, - &options->fill_mode_w[1], - _("Pattern Fill"), - (gpointer) PATTERN_BUCKET_FILL, - &options->fill_mode_w[2], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -/* bucket fill action functions */ - -static void -bucket_fill_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - BucketTool *bucket_tool; - gboolean use_offsets; - - bucket_tool = (BucketTool *) tool->private; - - use_offsets = (bucket_options->sample_merged) ? FALSE : TRUE; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &bucket_tool->target_x, - &bucket_tool->target_y, FALSE, use_offsets); - - /* Make the tool active and set the gdisplay which owns it */ - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - /* Make the tool active and set the gdisplay which owns it */ - tool->gdisp = gdisp; - tool->state = ACTIVE; -} - -static void -bucket_fill_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - BucketTool *bucket_tool; - Argument *return_vals; - gint nreturn_vals; - - bucket_tool = (BucketTool *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - /* if the 3rd button isn't pressed, fill the selected region */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - return_vals = - procedural_db_run_proc ("gimp_bucket_fill", - &nreturn_vals, - PDB_DRAWABLE, gimp_drawable_get_ID (gimp_image_active_drawable (gdisp->gimage)), - PDB_INT32, (gint32) bucket_options->fill_mode, - PDB_INT32, (gint32) gimp_context_get_paint_mode (NULL), - PDB_FLOAT, (gdouble) gimp_context_get_opacity (NULL) * 100, - PDB_FLOAT, (gdouble) bucket_options->threshold, - PDB_INT32, (gint32) bucket_options->sample_merged, - PDB_FLOAT, (gdouble) bucket_tool->target_x, - PDB_FLOAT, (gdouble) bucket_tool->target_y, - PDB_END); - - if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS) - gdisplays_flush (); - else - g_message (_("Bucket Fill operation failed.")); - - procedural_db_destroy_args (return_vals, nreturn_vals); - } - - tool->state = INACTIVE; -} - -static void -bucket_fill_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Layer *layer; - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; - CursorModifier cmodifier = CURSOR_MODIFIER_NONE; - gint x, y; - gint off_x, off_y; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &x, &y, FALSE, FALSE); - if ((layer = gimp_image_get_active_layer (gdisp->gimage))) - { - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); - - if (x >= off_x && y >= off_y && - x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && - y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) - { - /* One more test--is there a selected region? - * if so, is cursor inside? - */ - if (gimage_mask_is_empty (gdisp->gimage) || - gimage_mask_value (gdisp->gimage, x, y)) - { - ctype = GIMP_MOUSE_CURSOR; - - switch (bucket_options->fill_mode) - { - case FG_BUCKET_FILL: - cmodifier = CURSOR_MODIFIER_FOREGROUND; - break; - case BG_BUCKET_FILL: - cmodifier = CURSOR_MODIFIER_BACKGROUND; - break; - case PATTERN_BUCKET_FILL: - cmodifier = CURSOR_MODIFIER_PATTERN; - break; - } - } - } - } - - gdisplay_install_tool_cursor (gdisp, ctype, - BUCKET_FILL, - cmodifier, - FALSE); -} - -static void -bucket_fill_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: case GDK_Alt_R: - break; - case GDK_Shift_L: case GDK_Shift_R: - break; - case GDK_Control_L: case GDK_Control_R: - switch (bucket_options->fill_mode) - { - case FG_BUCKET_FILL: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[BG_BUCKET_FILL]), TRUE); - break; - case BG_BUCKET_FILL: - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[FG_BUCKET_FILL]), TRUE); - break; - default: - break; - } - break; - } -} - -void -bucket_fill (GimpImage *gimage, - GimpDrawable *drawable, - BucketFillMode fill_mode, - gint paint_mode, - gdouble opacity, - gdouble threshold, - gboolean sample_merged, - gdouble x, - gdouble y) -{ - TileManager *buf_tiles; - PixelRegion bufPR, maskPR; - Channel *mask = NULL; - gint bytes; - gboolean has_alpha; - gint x1, y1, x2, y2; - guchar col [MAX_CHANNELS]; - guchar *d1, *d2; - GPattern *pattern; - TempBuf *pat_buf; - gboolean new_buf = FALSE; - - pat_buf = NULL; - - if (fill_mode == FG_BUCKET_FILL) - gimp_image_get_foreground (gimage, drawable, col); - else if (fill_mode == BG_BUCKET_FILL) - gimp_image_get_background (gimage, drawable, col); - else if (fill_mode == PATTERN_BUCKET_FILL) - { - pattern = gimp_context_get_pattern (NULL); - - if (!pattern) - { - g_message (_("No available patterns for this operation.")); - return; - } - - /* If the pattern doesn't match the image in terms of color type, - * transform it. (ie pattern is RGB, image is indexed) - */ - if (((pattern->mask->bytes == 3) && !gimp_drawable_is_rgb (drawable)) || - ((pattern->mask->bytes == 1) && !gimp_drawable_is_gray (drawable))) - { - int size; - - if ((pattern->mask->bytes == 1) && gimp_drawable_is_rgb (drawable)) - pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height, - 3, 0, 0, NULL); - else - pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height, - 1, 0, 0, NULL); - - d1 = temp_buf_data (pattern->mask); - d2 = temp_buf_data (pat_buf); - - size = pattern->mask->width * pattern->mask->height; - while (size--) - { - gimp_image_transform_color (gimage, drawable, d1, d2, - (pattern->mask->bytes == 3) ? RGB : GRAY); - d1 += pattern->mask->bytes; - d2 += pat_buf->bytes; - } - - new_buf = TRUE; - } - else - pat_buf = pattern->mask; - } - - gimp_add_busy_cursors (); - - bytes = gimp_drawable_bytes (drawable); - has_alpha = gimp_drawable_has_alpha (drawable); - - /* If there is no selection mask, the do a seed bucket - * fill...To do this, calculate a new contiguous region - */ - if (! gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2)) - { - mask = find_contiguous_region (gimage, drawable, TRUE, (int) threshold, - (int) x, (int) y, sample_merged); - - channel_bounds (mask, &x1, &y1, &x2, &y2); - - /* make sure we handle the mask correctly if it was sample-merged */ - if (sample_merged) - { - gint off_x, off_y; - - /* Limit the channel bounds to the drawable's extents */ - gimp_drawable_offsets (drawable, &off_x, &off_y); - x1 = CLAMP (x1, off_x, (off_x + gimp_drawable_width (drawable))); - y1 = CLAMP (y1, off_y, (off_y + gimp_drawable_height (drawable))); - x2 = CLAMP (x2, off_x, (off_x + gimp_drawable_width (drawable))); - y2 = CLAMP (y2, off_y, (off_y + gimp_drawable_height (drawable))); - - pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)), - x1, y1, (x2 - x1), (y2 - y1), TRUE); - - /* translate mask bounds to drawable coords */ - x1 -= off_x; - y1 -= off_y; - x2 -= off_x; - y2 -= off_y; - } - else - pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)), - x1, y1, (x2 - x1), (y2 - y1), TRUE); - - /* if the gimage doesn't have an alpha channel, - * make sure that the temp buf does. We need the - * alpha channel to fill with the region calculated above - */ - if (! has_alpha) - { - bytes ++; - has_alpha = TRUE; - } - } - - buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes); - pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE); - - if (mask) - bucket_fill_region (fill_mode, &bufPR, &maskPR, col, pat_buf, x1, y1, has_alpha); - else - bucket_fill_region (fill_mode, &bufPR, NULL, col, pat_buf, x1, y1, has_alpha); - - pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); - gimp_image_apply_image (gimage, drawable, &bufPR, TRUE, - (opacity * 255) / 100, paint_mode, NULL, x1, y1); - - /* update the image */ - drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); - - /* free the temporary buffer */ - tile_manager_destroy (buf_tiles); - - /* free the mask */ - if (mask) - channel_delete (mask); - - if (new_buf) - temp_buf_free (pat_buf); - - gimp_remove_busy_cursors (NULL); -} - -static void -bucket_fill_line_color (guchar *buf, - guchar *mask, - guchar *col, - gboolean has_alpha, - gint bytes, - gint width) -{ - gint alpha, b; - - alpha = (has_alpha) ? bytes - 1 : bytes; - while (width--) - { - for (b = 0; b < alpha; b++) - buf[b] = col[b]; - - if (has_alpha) - { - if (mask) - buf[alpha] = *mask++; - else - buf[alpha] = OPAQUE_OPACITY; - } - - buf += bytes; - } -} - -static void -bucket_fill_line_pattern (guchar *buf, - guchar *mask, - TempBuf *pattern, - gboolean has_alpha, - gint bytes, - gint x, - gint y, - gint width) -{ - guchar *pat, *p; - gint alpha, b; - gint i; - - /* Get a pointer to the appropriate scanline of the pattern buffer */ - pat = temp_buf_data (pattern) + - (y % pattern->height) * pattern->width * pattern->bytes; - - alpha = (has_alpha) ? bytes - 1 : bytes; - for (i = 0; i < width; i++) - { - p = pat + ((i + x) % pattern->width) * pattern->bytes; - - for (b = 0; b < alpha; b++) - buf[b] = p[b]; - - if (has_alpha) - { - if (mask) - buf[alpha] = *mask++; - else - buf[alpha] = OPAQUE_OPACITY; - } - - buf += bytes; - } -} - -void -bucket_fill_region (BucketFillMode fill_mode, - PixelRegion *bufPR, - PixelRegion *maskPR, - guchar *col, - TempBuf *pattern, - gint off_x, - gint off_y, - gboolean has_alpha) -{ - guchar *s, *m; - gint y; - void *pr; - - for (pr = pixel_regions_register (2, bufPR, maskPR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - s = bufPR->data; - if (maskPR) - m = maskPR->data; - else - m = NULL; - - for (y = 0; y < bufPR->h; y++) - { - switch (fill_mode) - { - case FG_BUCKET_FILL: - case BG_BUCKET_FILL: - bucket_fill_line_color (s, m, col, has_alpha, bufPR->bytes, bufPR->w); - break; - case PATTERN_BUCKET_FILL: - bucket_fill_line_pattern (s, m, pattern, has_alpha, bufPR->bytes, - off_x + bufPR->x, off_y + y + bufPR->y, bufPR->w); - break; - } - s += bufPR->rowstride; - - if (maskPR) - m += maskPR->rowstride; - } - } -} - -/**********************************/ -/* Global bucket fill functions */ -/**********************************/ - -Tool * -tools_new_bucket_fill (void) -{ - Tool *tool; - BucketTool *private; - - /* The tool options */ - if (! bucket_options) - { - bucket_options = bucket_options_new (); - tools_register (BUCKET_FILL, (ToolOptions *) bucket_options); - - /* press all default buttons */ - bucket_options_reset (); - } - - tool = tools_new_tool (BUCKET_FILL); - private = g_new0 (BucketTool, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - - tool->private = (gpointer) private; - - tool->button_press_func = bucket_fill_button_press; - tool->button_release_func = bucket_fill_button_release; - tool->modifier_key_func = bucket_fill_modifier_key_func; - tool->cursor_update_func = bucket_fill_cursor_update; - - return tool; -} - -void -tools_free_bucket_fill (Tool *tool) -{ - BucketTool *bucket_tool; - - bucket_tool = (BucketTool *) tool->private; - - g_free (bucket_tool); -} diff --git a/app/bucket_fill.h b/app/bucket_fill.h deleted file mode 100644 index 195b5098fd..0000000000 --- a/app/bucket_fill.h +++ /dev/null @@ -1,54 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BUCKET_FILL_H__ -#define __BUCKET_FILL_H__ - - -typedef enum -{ - FG_BUCKET_FILL, - BG_BUCKET_FILL, - PATTERN_BUCKET_FILL -} BucketFillMode; - - -void bucket_fill (GimpImage *gimage, - GimpDrawable *drawable, - BucketFillMode fill_mode, - gint paint_mode, - gdouble opacity, - gdouble threshold, - gboolean sample_merged, - gdouble x, - gdouble y); - -void bucket_fill_region (BucketFillMode fill_mode, - PixelRegion *bufPR, - PixelRegion *maskPR, - guchar *col, - TempBuf *pattern, - gint off_x, - gint off_y, - gboolean has_alpha); - -Tool * tools_new_bucket_fill (void); -void tools_free_bucket_fill (Tool *tool); - - -#endif /* __BUCKET_FILL_H__ */ diff --git a/app/by_color_select.c b/app/by_color_select.c deleted file mode 100644 index 992d3b29dd..0000000000 --- a/app/by_color_select.c +++ /dev/null @@ -1,1262 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "boundary.h" -#include "by_color_select.h" -#include "channel.h" -#include "cursorutil.h" -#include "drawable.h" -#include "draw_core.h" -#include "gimage_mask.h" -#include "gimpdnd.h" -#include "gimpimage.h" -#include "gimprc.h" -#include "gimpset.h" -#include "gimpui.h" -#include "gdisplay.h" -#include "paint_funcs.h" -#include "pixel_region.h" -#include "selection_options.h" -#include "temp_buf.h" -#include "tile.h" -#include "tile_manager.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpintl.h" - - -#define PREVIEW_WIDTH 256 -#define PREVIEW_HEIGHT 256 -#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \ - GDK_BUTTON_PRESS_MASK | \ - GDK_ENTER_NOTIFY_MASK - -/* the by color selection structures */ - -typedef struct _ByColorSelect ByColorSelect; - -struct _ByColorSelect -{ - gint x, y; /* Point from which to execute seed fill */ - SelectOps operation; /* add, subtract, normal color selection */ -}; - -typedef struct _ByColorDialog ByColorDialog; - -struct _ByColorDialog -{ - GtkWidget *shell; - - GtkWidget *preview; - GtkWidget *gimage_name; - - GtkWidget *replace_button; - GtkObject *threshold_adj; - - gint threshold; /* threshold value for color select */ - gint operation; /* Add, Subtract, Replace */ - GImage *gimage; /* gimage which is currently under examination */ -}; - - -/* the by color selection tool options */ -static SelectionOptions * by_color_options = NULL; - -/* the by color selection dialog */ -static ByColorDialog * by_color_dialog = NULL; - -/* dnd stuff */ -static GtkTargetEntry by_color_select_targets[] = -{ - GIMP_TARGET_COLOR -}; -static guint n_by_color_select_targets = (sizeof (by_color_select_targets) / - sizeof (by_color_select_targets[0])); - - -static void by_color_select_color_drop (GtkWidget *widget, - const GimpRGB *color, - gpointer data); - -/* by_color select action functions */ - -static void by_color_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void by_color_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void by_color_select_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -static void by_color_select_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void by_color_select_oper_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void by_color_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static ByColorDialog * by_color_select_dialog_new (void); - -static void by_color_select_render (ByColorDialog *, - GImage *); -static void by_color_select_draw (ByColorDialog *, - GImage *); -static gint by_color_select_preview_events (GtkWidget *, - GdkEventButton *, - ByColorDialog *); -static void by_color_select_invert_callback (GtkWidget *, - gpointer ); -static void by_color_select_select_all_callback (GtkWidget *, - gpointer ); -static void by_color_select_select_none_callback (GtkWidget *, - gpointer ); -static void by_color_select_reset_callback (GtkWidget *, - gpointer ); -static void by_color_select_close_callback (GtkWidget *, - gpointer ); -static void by_color_select_preview_button_press (ByColorDialog *, - GdkEventButton *); - -static gint is_pixel_sufficiently_different (guchar *, - guchar *, - gint , - gint , - gint , - gint ); -static Channel * by_color_select_color (GImage *, - GimpDrawable *, - guchar *, - gint , - gint , - gint ); - - -/* by_color selection machinery */ - -static gint -is_pixel_sufficiently_different (guchar *col1, - guchar *col2, - gint antialias, - gint threshold, - gint bytes, - gint has_alpha) -{ - gint diff; - gint max; - gint b; - gint alpha; - - max = 0; - alpha = (has_alpha) ? bytes - 1 : bytes; - - /* if there is an alpha channel, never select transparent regions */ - if (has_alpha && col2[alpha] == 0) - return 0; - - for (b = 0; b < alpha; b++) - { - diff = col1[b] - col2[b]; - diff = abs (diff); - if (diff > max) - max = diff; - } - - if (antialias && threshold > 0) - { - gfloat aa; - - aa = 1.5 - ((gfloat) max / threshold); - if (aa <= 0) - return 0; - else if (aa < 0.5) - return (guchar) (aa * 512); - else - return 255; - } - else - { - if (max > threshold) - return 0; - else - return 255; - } -} - -static Channel * -by_color_select_color (GImage *gimage, - GimpDrawable *drawable, - guchar *color, - gboolean antialias, - gint threshold, - gboolean sample_merged) -{ - /* Scan over the gimage's active layer, finding pixels within the specified - * threshold from the given R, G, & B values. If antialiasing is on, - * use the same antialiasing scheme as in fuzzy_select. Modify the gimage's - * mask to reflect the additional selection - */ - Channel *mask; - PixelRegion imagePR, maskPR; - guchar *image_data; - guchar *mask_data; - guchar *idata, *mdata; - guchar rgb[MAX_CHANNELS]; - gint has_alpha, indexed; - gint width, height; - gint bytes, color_bytes, alpha; - gint i, j; - gpointer pr; - gint d_type; - - /* Get the image information */ - if (sample_merged) - { - bytes = gimp_image_composite_bytes (gimage); - d_type = gimp_image_composite_type (gimage); - has_alpha = (d_type == RGBA_GIMAGE || - d_type == GRAYA_GIMAGE || - d_type == INDEXEDA_GIMAGE); - indexed = d_type == INDEXEDA_GIMAGE || d_type == INDEXED_GIMAGE; - width = gimage->width; - height = gimage->height; - pixel_region_init (&imagePR, gimp_image_composite (gimage), - 0, 0, width, height, FALSE); - } - else - { - bytes = gimp_drawable_bytes (drawable); - d_type = gimp_drawable_type (drawable); - has_alpha = gimp_drawable_has_alpha (drawable); - indexed = gimp_drawable_is_indexed (drawable); - width = gimp_drawable_width (drawable); - height = gimp_drawable_height (drawable); - - pixel_region_init (&imagePR, gimp_drawable_data (drawable), - 0, 0, width, height, FALSE); - } - - if (indexed) - { - /* indexed colors are always RGB or RGBA */ - color_bytes = has_alpha ? 4 : 3; - } - else - { - /* RGB, RGBA, GRAY and GRAYA colors are shaped just like the image */ - color_bytes = bytes; - } - - alpha = bytes - 1; - mask = channel_new_mask (gimage, width, height); - pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)), - 0, 0, width, height, TRUE); - - /* iterate over the entire image */ - for (pr = pixel_regions_register (2, &imagePR, &maskPR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - image_data = imagePR.data; - mask_data = maskPR.data; - - for (i = 0; i < imagePR.h; i++) - { - idata = image_data; - mdata = mask_data; - for (j = 0; j < imagePR.w; j++) - { - /* Get the rgb values for the color */ - gimp_image_get_color (gimage, d_type, rgb, idata); - - /* Plug the alpha channel in there */ - if (has_alpha) - rgb[color_bytes - 1] = idata[alpha]; - - /* Find how closely the colors match */ - *mdata++ = is_pixel_sufficiently_different (color, - rgb, - antialias, - threshold, - color_bytes, - has_alpha); - - idata += bytes; - } - - image_data += imagePR.rowstride; - mask_data += maskPR.rowstride; - } - } - - return mask; -} - -void -by_color_select (GImage *gimage, - GimpDrawable *drawable, - guchar *color, - gint threshold, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius, - gboolean sample_merged) -{ - Channel *new_mask; - gint off_x, off_y; - - if (!drawable) - return; - - new_mask = by_color_select_color (gimage, drawable, color, - antialias, threshold, sample_merged); - - /* if applicable, replace the current selection */ - if (op == SELECTION_REPLACE) - gimage_mask_clear (gimage); - else - gimage_mask_undo (gimage); - - if (sample_merged) - { - off_x = 0; off_y = 0; - } - else - { - gimp_drawable_offsets (drawable, &off_x, &off_y); - } - - if (feather) - channel_feather (new_mask, gimp_image_get_mask (gimage), - feather_radius, - feather_radius, - op, off_x, off_y); - else - channel_combine_mask (gimp_image_get_mask (gimage), - new_mask, op, off_x, off_y); - - channel_delete (new_mask); -} - -/* by_color select action functions */ - -static void -by_color_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - ByColorSelect *by_color_sel; - - by_color_sel = (ByColorSelect *) tool->private; - - tool->drawable = gimp_image_active_drawable (gdisp->gimage); - - if (!by_color_dialog) - return; - - by_color_sel->x = bevent->x; - by_color_sel->y = bevent->y; - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - /* Make sure the "by color" select dialog is visible */ - if (! GTK_WIDGET_VISIBLE (by_color_dialog->shell)) - gtk_widget_show (by_color_dialog->shell); - - /* Update the by_color_dialog's active gdisp pointer */ - if (by_color_dialog->gimage) - by_color_dialog->gimage->by_color_select = FALSE; - - if (by_color_dialog->gimage != gdisp->gimage) - { - gdk_draw_rectangle - (by_color_dialog->preview->window, - by_color_dialog->preview->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - 0, 0, - by_color_dialog->preview->allocation.width, - by_color_dialog->preview->allocation.width); - } - - by_color_dialog->gimage = gdisp->gimage; - gdisp->gimage->by_color_select = TRUE; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); -} - -static void -by_color_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - ByColorSelect *by_color_sel; - gint x, y; - GimpDrawable *drawable; - guchar *color; - gint use_offsets; - - by_color_sel = (ByColorSelect *) tool->private; - drawable = gimp_image_active_drawable (gdisp->gimage); - - gdk_pointer_ungrab (bevent->time); - - tool->state = INACTIVE; - - /* First take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - use_offsets = (by_color_options->sample_merged) ? FALSE : TRUE; - gdisplay_untransform_coords (gdisp, by_color_sel->x, by_color_sel->y, - &x, &y, FALSE, use_offsets); - - if( x >= 0 && x < gimp_drawable_width (drawable) && - y >= 0 && y < gimp_drawable_height (drawable)) - { - /* Get the start color */ - if (by_color_options->sample_merged) - { - if (!(color = gimp_image_get_color_at (gdisp->gimage, x, y))) - return; - } - else - { - if (!(color = gimp_drawable_get_color_at (drawable, x, y))) - return; - } - - /* select the area */ - by_color_select (gdisp->gimage, drawable, color, - by_color_dialog->threshold, - by_color_sel->operation, - by_color_options->antialias, - by_color_options->feather, - by_color_options->feather_radius, - by_color_options->sample_merged); - - g_free (color); - - /* show selection on all views */ - gdisplays_flush (); - - /* update the preview window */ - by_color_select_render (by_color_dialog, gdisp->gimage); - by_color_select_draw (by_color_dialog, gdisp->gimage); - } - } -} - -static void -by_color_select_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - ByColorSelect *by_col_sel; - Layer *layer; - gint x, y; - - by_col_sel = (ByColorSelect *) tool->private; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &x, &y, FALSE, FALSE); - - if (by_color_options->sample_merged || - ((layer = gimp_image_pick_correlate_layer (gdisp->gimage, x, y)) && - layer == gdisp->gimage->active_layer)) - { - switch (by_col_sel->operation) - { - case SELECTION_ADD: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_PLUS, - FALSE); - break; - case SELECTION_SUB: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_MINUS, - FALSE); - break; - case SELECTION_INTERSECT: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_INTERSECT, - FALSE); - break; - case SELECTION_REPLACE: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_NONE, - FALSE); - break; - case SELECTION_MOVE_MASK: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_MOVE, - FALSE); - break; - case SELECTION_MOVE: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - MOVE, - CURSOR_MODIFIER_NONE, - FALSE); - break; - case SELECTION_ANCHOR: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_ANCHOR, - FALSE); - } - - return; - } - - gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_NONE, - FALSE); -} - -static void -by_color_select_update_op_state (ByColorSelect *by_col_sel, - gint state, - GDisplay *gdisp) -{ - if (active_tool->state == ACTIVE) - return; - - if ((state & GDK_SHIFT_MASK) && - !(state & GDK_CONTROL_MASK)) - by_col_sel->operation = SELECTION_ADD; /* add to the selection */ - else if ((state & GDK_CONTROL_MASK) && - !(state & GDK_SHIFT_MASK)) - by_col_sel->operation = SELECTION_SUB; /* subtract from the selection */ - else if ((state & GDK_CONTROL_MASK) && - (state & GDK_SHIFT_MASK)) - by_col_sel->operation = SELECTION_INTERSECT; /* intersect with selection */ - else - by_col_sel->operation = by_color_dialog->operation; -} - -static void -by_color_select_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - ByColorSelect *by_col_sel; - gint state; - - by_col_sel = (ByColorSelect *) tool->private; - - state = kevent->state; - - switch (kevent->keyval) - { - case GDK_Alt_L: case GDK_Alt_R: - if (state & GDK_MOD1_MASK) - state &= ~GDK_MOD1_MASK; - else - state |= GDK_MOD1_MASK; - break; - - case GDK_Shift_L: case GDK_Shift_R: - if (state & GDK_SHIFT_MASK) - state &= ~GDK_SHIFT_MASK; - else - state |= GDK_SHIFT_MASK; - break; - - case GDK_Control_L: case GDK_Control_R: - if (state & GDK_CONTROL_MASK) - state &= ~GDK_CONTROL_MASK; - else - state |= GDK_CONTROL_MASK; - break; - } - - by_color_select_update_op_state (by_col_sel, state, gdisp); -} - -static void -by_color_select_oper_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - ByColorSelect *by_col_sel; - - by_col_sel = (ByColorSelect *) tool->private; - - by_color_select_update_op_state (by_col_sel, mevent->state, gdisp); -} - -static void -by_color_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - if (by_color_dialog) - by_color_select_close_callback (NULL, (gpointer) by_color_dialog); - break; - - default: - break; - } -} - -static void -by_color_select_options_reset (void) -{ - selection_options_reset (by_color_options); -} - -Tool * -tools_new_by_color_select (void) -{ - Tool *tool; - ByColorSelect *private; - - /* The tool options */ - if (!by_color_options) - { - by_color_options = - selection_options_new (BY_COLOR_SELECT, by_color_select_options_reset); - tools_register (BY_COLOR_SELECT, (ToolOptions *) by_color_options); - } - - tool = tools_new_tool (BY_COLOR_SELECT); - private = g_new0 (ByColorSelect, 1); - - private->operation = SELECTION_REPLACE; - - tool->private = (void *) private; - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - - tool->button_press_func = by_color_select_button_press; - tool->button_release_func = by_color_select_button_release; - tool->cursor_update_func = by_color_select_cursor_update; - tool->modifier_key_func = by_color_select_modifier_update; - tool->oper_update_func = by_color_select_oper_update; - tool->control_func = by_color_select_control; - - return tool; -} - -void -tools_free_by_color_select (Tool *tool) -{ - ByColorSelect *by_color_sel; - - by_color_sel = (ByColorSelect *) tool->private; - - /* Close the color select dialog */ - if (by_color_dialog) - by_color_select_close_callback (NULL, (gpointer) by_color_dialog); - - g_free (by_color_sel); -} - -void -by_color_select_initialize_by_image (GImage *gimage) -{ - /* update the preview window */ - if (by_color_dialog) - { - by_color_dialog->gimage = gimage; - gimage->by_color_select = TRUE; - by_color_select_render (by_color_dialog, gimage); - by_color_select_draw (by_color_dialog, gimage); - } -} - -void -by_color_select_initialize (GDisplay *gdisp) -{ - /* The "by color" dialog */ - if (!by_color_dialog) - by_color_dialog = by_color_select_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (by_color_dialog->shell)) - gtk_widget_show (by_color_dialog->shell); - - by_color_select_initialize_by_image (gdisp->gimage); -} - -/****************************/ -/* Select by Color dialog */ -/****************************/ - -static ByColorDialog * -by_color_select_dialog_new (void) -{ - ByColorDialog *bcd; - GtkWidget *hbox; - GtkWidget *frame; - GtkWidget *options_box; - GtkWidget *label; - GtkWidget *util_box; - GtkWidget *slider; - GtkWidget *table; - GtkWidget *button; - - bcd = g_new (ByColorDialog, 1); - bcd->gimage = NULL; - bcd->operation = SELECTION_REPLACE; - bcd->threshold = default_threshold; - - /* The shell and main vbox */ - bcd->shell = gimp_dialog_new (_("By Color Selection"), "by_color_selection", - tools_help_func, NULL, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("Reset"), by_color_select_reset_callback, - bcd, NULL, NULL, FALSE, FALSE, - _("Close"), by_color_select_close_callback, - bcd, NULL, NULL, TRUE, TRUE, - - NULL); - - /* The main hbox */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (bcd->shell)->vbox), hbox); - - /* The preview */ - util_box = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), util_box, FALSE, FALSE, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (util_box), frame, FALSE, FALSE, 0); - - bcd->preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE); - gtk_preview_size (GTK_PREVIEW (bcd->preview), PREVIEW_WIDTH, PREVIEW_HEIGHT); - gtk_widget_set_events (bcd->preview, PREVIEW_EVENT_MASK); - gtk_container_add (GTK_CONTAINER (frame), bcd->preview); - - gtk_signal_connect (GTK_OBJECT (bcd->preview), "button_press_event", - GTK_SIGNAL_FUNC (by_color_select_preview_events), - bcd); - - /* dnd colors to the image window */ - gtk_drag_dest_set (bcd->preview, - GTK_DEST_DEFAULT_HIGHLIGHT | - GTK_DEST_DEFAULT_MOTION | - GTK_DEST_DEFAULT_DROP, - by_color_select_targets, - n_by_color_select_targets, - GDK_ACTION_COPY); - gimp_dnd_color_dest_set (bcd->preview, by_color_select_color_drop, bcd); - - gtk_widget_show (bcd->preview); - gtk_widget_show (frame); - gtk_widget_show (util_box); - - /* options box */ - options_box = gtk_vbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (hbox), options_box, FALSE, FALSE, 0); - - /* Create the active image label */ - util_box = gtk_hbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (options_box), util_box, FALSE, FALSE, 0); - - bcd->gimage_name = gtk_label_new (_("Inactive")); - gtk_box_pack_start (GTK_BOX (util_box), bcd->gimage_name, FALSE, FALSE, 0); - - gtk_widget_show (bcd->gimage_name); - gtk_widget_show (util_box); - - /* Create the selection mode radio box */ - frame = - gimp_radio_group_new2 (TRUE, _("Selection Mode"), - gimp_radio_button_update, - &bcd->operation, - (gpointer) bcd->operation, - - _("Replace"), (gpointer) SELECTION_REPLACE, - &bcd->replace_button, - _("Add"), (gpointer) SELECTION_ADD, NULL, - _("Subtract"), (gpointer) SELECTION_SUB, NULL, - _("Intersect"), (gpointer) SELECTION_INTERSECT, NULL, - - NULL); - - gtk_box_pack_start (GTK_BOX (options_box), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - /* Create the opacity scale widget */ - util_box = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (options_box), util_box, FALSE, FALSE, 0); - - label = gtk_label_new (_("Fuzziness Threshold")); - gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2); - - gtk_widget_show (label); - gtk_widget_show (util_box); - - bcd->threshold_adj = - gtk_adjustment_new (bcd->threshold, 0.0, 255.0, 1.0, 1.0, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (bcd->threshold_adj)); - gtk_box_pack_start (GTK_BOX (util_box), slider, TRUE, TRUE, 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - - gtk_signal_connect (GTK_OBJECT (bcd->threshold_adj), "value_changed", - GTK_SIGNAL_FUNC (gimp_int_adjustment_update), - &bcd->threshold); - - gtk_widget_show (slider); - - frame = gtk_frame_new (_("Selection")); - gtk_box_pack_end (GTK_BOX (options_box), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - table = gtk_table_new (2, 2, TRUE); - gtk_container_set_border_width (GTK_CONTAINER (table), 2); - gtk_table_set_col_spacings (GTK_TABLE (table), 2); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - gtk_container_add (GTK_CONTAINER (frame), table); - gtk_widget_show (table); - - button = gtk_button_new_with_label (_("Invert")); - gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 0, 1); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (by_color_select_invert_callback), - bcd); - gtk_widget_show (button); - - button = gtk_button_new_with_label (_("All")); - gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 1, 2); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (by_color_select_select_all_callback), - bcd); - gtk_widget_show (button); - - button = gtk_button_new_with_label (_("None")); - gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 1, 2); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (by_color_select_select_none_callback), - bcd); - gtk_widget_show (button); - - gtk_widget_show (options_box); - gtk_widget_show (hbox); - gtk_widget_show (bcd->shell); - - gtk_signal_connect_object (GTK_OBJECT (bcd->shell), "unmap_event", - GTK_SIGNAL_FUNC (gimp_dialog_hide), - (gpointer) bcd->shell); - - return bcd; -} - -static void -by_color_select_render (ByColorDialog *bcd, - GImage *gimage) -{ - Channel * mask; - MaskBuf * scaled_buf = NULL; - guchar *buf; - PixelRegion srcPR, destPR; - guchar *src; - gint subsample; - gint width, height; - gint srcwidth; - gint i; - gint scale; - - mask = gimp_image_get_mask (gimage); - if ((gimp_drawable_width (GIMP_DRAWABLE(mask)) > PREVIEW_WIDTH) || - (gimp_drawable_height (GIMP_DRAWABLE(mask)) > PREVIEW_HEIGHT)) - { - if (((float) gimp_drawable_width (GIMP_DRAWABLE (mask)) / (float) PREVIEW_WIDTH) > - ((float) gimp_drawable_height (GIMP_DRAWABLE (mask)) / (float) PREVIEW_HEIGHT)) - { - width = PREVIEW_WIDTH; - height = ((gimp_drawable_height (GIMP_DRAWABLE (mask)) * PREVIEW_WIDTH) / - gimp_drawable_width (GIMP_DRAWABLE (mask))); - } - else - { - width = ((gimp_drawable_width (GIMP_DRAWABLE (mask)) * PREVIEW_HEIGHT) / - gimp_drawable_height (GIMP_DRAWABLE (mask))); - height = PREVIEW_HEIGHT; - } - - scale = TRUE; - } - else - { - width = gimp_drawable_width (GIMP_DRAWABLE (mask)); - height = gimp_drawable_height (GIMP_DRAWABLE (mask)); - - scale = FALSE; - } - - if ((width != bcd->preview->requisition.width) || - (height != bcd->preview->requisition.height)) - gtk_preview_size (GTK_PREVIEW (bcd->preview), width, height); - - /* clear the image buf */ - buf = g_new0 (guchar, bcd->preview->requisition.width); - for (i = 0; i < bcd->preview->requisition.height; i++) - gtk_preview_draw_row (GTK_PREVIEW (bcd->preview), buf, - 0, i, bcd->preview->requisition.width); - g_free (buf); - - /* if the mask is empty, no need to scale and update again */ - if (gimage_mask_is_empty (gimage)) - return; - - if (scale) - { - /* calculate 'acceptable' subsample */ - subsample = 1; - while ((width * (subsample + 1) * 2 < gimp_drawable_width (GIMP_DRAWABLE (mask))) && - (height * (subsample + 1) * 2 < gimp_drawable_height (GIMP_DRAWABLE (mask)))) - subsample = subsample + 1; - - pixel_region_init (&srcPR, gimp_drawable_data (GIMP_DRAWABLE (mask)), - 0, 0, - gimp_drawable_width (GIMP_DRAWABLE (mask)), - gimp_drawable_height (GIMP_DRAWABLE (mask)), FALSE); - - scaled_buf = mask_buf_new (width, height); - destPR.bytes = 1; - destPR.x = 0; - destPR.y = 0; - destPR.w = width; - destPR.h = height; - destPR.rowstride = srcPR.bytes * width; - destPR.data = mask_buf_data (scaled_buf); - destPR.tiles = NULL; - - subsample_region (&srcPR, &destPR, subsample); - } - else - { - pixel_region_init (&srcPR, gimp_drawable_data (GIMP_DRAWABLE (mask)), - 0, 0, - gimp_drawable_width (GIMP_DRAWABLE (mask)), - gimp_drawable_height (GIMP_DRAWABLE (mask)), FALSE); - - scaled_buf = mask_buf_new (width, height); - destPR.bytes = 1; - destPR.x = 0; - destPR.y = 0; - destPR.w = width; - destPR.h = height; - destPR.rowstride = srcPR.bytes * width; - destPR.data = mask_buf_data (scaled_buf); - destPR.tiles = NULL; - - copy_region (&srcPR, &destPR); - } - - src = mask_buf_data (scaled_buf); - srcwidth = scaled_buf->width; - for (i = 0; i < height; i++) - { - gtk_preview_draw_row (GTK_PREVIEW (bcd->preview), src, 0, i, width); - src += srcwidth; - } - - mask_buf_free (scaled_buf); -} - -static void -by_color_select_draw (ByColorDialog *bcd, - GImage *gimage) -{ - /* Draw the image buf to the preview window */ - gtk_widget_draw (bcd->preview, NULL); - - /* Update the gimage label to reflect the displayed gimage name */ - gtk_label_set_text (GTK_LABEL (bcd->gimage_name), - g_basename (gimp_image_filename (gimage))); -} - -static gint -by_color_select_preview_events (GtkWidget *widget, - GdkEventButton *bevent, - ByColorDialog *bcd) -{ - switch (bevent->type) - { - case GDK_BUTTON_PRESS: - by_color_select_preview_button_press (bcd, bevent); - break; - - default: - break; - } - - return FALSE; -} - -static void -by_color_select_reset_callback (GtkWidget *widget, - gpointer data) -{ - ByColorDialog *bcd; - - bcd = (ByColorDialog *) data; - - gtk_widget_activate (bcd->replace_button); - gtk_adjustment_set_value (GTK_ADJUSTMENT (bcd->threshold_adj), - default_threshold); -} - -static void -by_color_select_invert_callback (GtkWidget *widget, - gpointer data) -{ - ByColorDialog *bcd; - - bcd = (ByColorDialog *) data; - - if (!bcd->gimage) - return; - - /* check if the image associated to the mask still exists */ - if (! gimp_drawable_gimage (GIMP_DRAWABLE (gimp_image_get_mask (bcd->gimage)))) - return; - - /* invert the mask */ - gimage_mask_invert (bcd->gimage); - - /* show selection on all views */ - gdisplays_flush (); - - /* update the preview window */ - by_color_select_render (bcd, bcd->gimage); - by_color_select_draw (bcd, bcd->gimage); -} - -static void -by_color_select_select_all_callback (GtkWidget *widget, - gpointer data) -{ - ByColorDialog *bcd; - - bcd = (ByColorDialog *) data; - - if (!bcd->gimage) - return; - - /* check if the image associated to the mask still exists */ - if (! gimp_drawable_gimage (GIMP_DRAWABLE (gimp_image_get_mask (bcd->gimage)))) - return; - - /* fill the mask */ - gimage_mask_all (bcd->gimage); - - /* show selection on all views */ - gdisplays_flush (); - - /* update the preview window */ - by_color_select_render (bcd, bcd->gimage); - by_color_select_draw (bcd, bcd->gimage); -} - -static void -by_color_select_select_none_callback (GtkWidget *widget, - gpointer data) -{ - ByColorDialog *bcd; - - bcd = (ByColorDialog *) data; - - if (!bcd->gimage) - return; - - /* check if the image associated to the mask still exists */ - if (! gimp_drawable_gimage (GIMP_DRAWABLE (gimp_image_get_mask (bcd->gimage)))) - return; - - /* reset the mask */ - gimage_mask_clear (bcd->gimage); - - /* show selection on all views */ - gdisplays_flush (); - - /* update the preview window */ - by_color_select_render (bcd, bcd->gimage); - by_color_select_draw (bcd, bcd->gimage); -} - -static void -by_color_select_close_callback (GtkWidget *widget, - gpointer data) -{ - ByColorDialog *bcd; - - bcd = (ByColorDialog *) data; - - gimp_dialog_hide (bcd->shell); - - if (bcd->gimage && gimp_set_have (image_context, bcd->gimage)) - { - bcd->gimage->by_color_select = FALSE; - bcd->gimage = NULL; - } -} - -static void -by_color_select_preview_button_press (ByColorDialog *bcd, - GdkEventButton *bevent) -{ - gint x, y; - gboolean replace; - SelectOps operation; - GimpDrawable *drawable; - Tile *tile; - guchar *col; - - if (!bcd->gimage) - return; - - drawable = gimp_image_active_drawable (bcd->gimage); - - /* check if the gimage associated to the drawable still exists */ - if (! gimp_drawable_gimage (drawable)) - return; - - /* Defaults */ - replace = FALSE; - operation = SELECTION_REPLACE; - - /* Based on modifiers, and the "by color" dialog's selection mode */ - if ((bevent->state & GDK_SHIFT_MASK) && - !(bevent->state & GDK_CONTROL_MASK)) - operation = SELECTION_ADD; - else if ((bevent->state & GDK_CONTROL_MASK) && - !(bevent->state & GDK_SHIFT_MASK)) - operation = SELECTION_SUB; - else if ((bevent->state & GDK_CONTROL_MASK) && - (bevent->state & GDK_SHIFT_MASK)) - operation = SELECTION_INTERSECT; - else - operation = by_color_dialog->operation; - - /* Find x, y and modify selection */ - - /* Get the start color */ - if (by_color_options->sample_merged) - { - x = bcd->gimage->width * bevent->x / bcd->preview->requisition.width; - y = bcd->gimage->height * bevent->y / bcd->preview->requisition.height; - if (x < 0 || y < 0 || x >= bcd->gimage->width || y >= bcd->gimage->height) - return; - tile = tile_manager_get_tile (gimp_image_composite (bcd->gimage), - x, y, TRUE, FALSE); - col = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT); - } - else - { - gint offx, offy; - - gimp_drawable_offsets (drawable, &offx, &offy); - x = gimp_drawable_width (drawable) * bevent->x / bcd->preview->requisition.width - offx; - y = gimp_drawable_height (drawable) * bevent->y / bcd->preview->requisition.height - offy; - if (x < 0 || y < 0 || - x >= gimp_drawable_width (drawable) || y >= gimp_drawable_height (drawable)) - return; - tile = tile_manager_get_tile (gimp_drawable_data (drawable), - x, y, TRUE, FALSE); - col = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT); - } - - by_color_select (bcd->gimage, drawable, col, - bcd->threshold, - operation, - by_color_options->antialias, - by_color_options->feather, - by_color_options->feather_radius, - by_color_options->sample_merged); - - tile_release (tile, FALSE); - - /* show selection on all views */ - gdisplays_flush (); - - /* update the preview window */ - by_color_select_render (bcd, bcd->gimage); - by_color_select_draw (bcd, bcd->gimage); -} - -static void -by_color_select_color_drop (GtkWidget *widget, - const GimpRGB *color, - gpointer data) - -{ - GimpDrawable *drawable; - ByColorDialog *bcd; - guchar col[3]; - - bcd = (ByColorDialog*) data; - drawable = gimp_image_active_drawable (bcd->gimage); - - gimp_rgb_get_uchar (color, &col[0], &col[1], &col[2]); - - by_color_select (bcd->gimage, - drawable, - col, - bcd->threshold, - bcd->operation, - by_color_options->antialias, - by_color_options->feather, - by_color_options->feather_radius, - by_color_options->sample_merged); - - /* show selection on all views */ - gdisplays_flush (); - - /* update the preview window */ - by_color_select_render (bcd, bcd->gimage); - by_color_select_draw (bcd, bcd->gimage); -} diff --git a/app/by_color_select.h b/app/by_color_select.h deleted file mode 100644 index b75f1145ed..0000000000 --- a/app/by_color_select.h +++ /dev/null @@ -1,40 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __BY_COLOR_SELECT_H__ -#define __BY_COLOR_SELECT_H__ - - -Tool * tools_new_by_color_select (void); -void tools_free_by_color_select (Tool *tool); - -void by_color_select_initialize (GDisplay *gdisp); -void by_color_select_initialize_by_image (GImage *gimage); - -void by_color_select (GimpImage *gimage, - GimpDrawable *drawable, - guchar *color, - gint threshold, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius, - gboolean sample_merged); - - -#endif /* __BY_COLOR_SELECT_H__ */ diff --git a/app/clone.c b/app/clone.c deleted file mode 100644 index 3c7ba8f8c9..0000000000 --- a/app/clone.c +++ /dev/null @@ -1,773 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpcontext.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "patterns.h" -#include "pixel_region.h" -#include "clone.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" -#include "cursorutil.h" - -#include "libgimp/gimpintl.h" - - -#define TARGET_HEIGHT 15 -#define TARGET_WIDTH 15 - -/* default types */ -#define CLONE_DEFAULT_TYPE IMAGE_CLONE -#define CLONE_DEFAULT_ALIGNED ALIGN_NO - -/* the clone structures */ - -typedef enum -{ - ALIGN_NO, - ALIGN_YES, - ALIGN_REGISTERED -} AlignType; - -typedef struct _CloneOptions CloneOptions; - -struct _CloneOptions -{ - PaintOptions paint_options; - - CloneType type; - CloneType type_d; - GtkWidget *type_w[2]; /* 2 radio buttons */ - - AlignType aligned; - AlignType aligned_d; - GtkWidget *aligned_w[3]; /* 3 radio buttons */ -}; - - -/* forward function declarations */ - -static gpointer clone_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); -static void clone_draw (Tool *tool); -static void clone_motion (PaintCore *paint_core, - GimpDrawable *drawable, - GimpDrawable *src_drawable, - PaintPressureOptions *pressure_options, - CloneType type, - gint offset_x, - gint offset_y); -static void clone_line_image (GImage *dest, - GImage *src, - GimpDrawable *d_drawable, - GimpDrawable *s_drawable, - guchar *s, - guchar *d, - gint has_alpha, - gint src_bytes, - gint dest_bytes, - gint width); -static void clone_line_pattern (GImage *dest, - GimpDrawable *drawable, - GPattern *pattern, - guchar *d, - gint x, - gint y, - gint bytes, - gint width); - - -/* the clone tool options */ -static CloneOptions *clone_options = NULL; - -/* local variables */ -static gint src_x = 0; /* */ -static gint src_y = 0; /* position of clone src */ -static gint dest_x = 0; /* */ -static gint dest_y = 0; /* position of clone src */ -static gint offset_x = 0; /* */ -static gint offset_y = 0; /* offset for cloning */ -static gint first = TRUE; -static gint trans_tx, trans_ty; /* transformed target */ -static GDisplay *the_src_gdisp = NULL; /* ID of source gdisplay */ -static GimpDrawable *src_drawable_ = NULL; /* source drawable */ - -static GimpDrawable *non_gui_src_drawable; -static gint non_gui_offset_x; -static gint non_gui_offset_y; -static CloneType non_gui_type; - - -/* functions */ - -static void -clone_options_reset (void) -{ - CloneOptions *options = clone_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->aligned_w[options->aligned_d]), TRUE); -} - -static CloneOptions * -clone_options_new (void) -{ - CloneOptions *options; - GtkWidget *vbox; - GtkWidget *frame; - - /* the new clone tool options structure */ - options = g_new (CloneOptions, 1); - paint_options_init ((PaintOptions *) options, - CLONE, - clone_options_reset); - options->type = options->type_d = CLONE_DEFAULT_TYPE; - options->aligned = options->aligned_d = CLONE_DEFAULT_ALIGNED; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - frame = gimp_radio_group_new2 (TRUE, _("Source"), - gimp_radio_button_update, - &options->type, (gpointer) options->type, - - _("Image Source"), (gpointer) IMAGE_CLONE, - &options->type_w[0], - _("Pattern Source"), (gpointer) PATTERN_CLONE, - &options->type_w[1], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - frame = gimp_radio_group_new2 (TRUE, _("Alignment"), - gimp_radio_button_update, - &options->aligned, (gpointer) options->aligned, - - _("Non Aligned"), (gpointer) ALIGN_NO, - &options->aligned_w[0], - _("Aligned"), (gpointer) ALIGN_YES, - &options->aligned_w[1], - _("Registered"), (gpointer) ALIGN_REGISTERED, - &options->aligned_w[2], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -static void -clone_src_drawable_destroyed_cb (GimpDrawable *drawable, - GimpDrawable **src_drawable) -{ - if (drawable == *src_drawable) - { - *src_drawable = NULL; - the_src_gdisp = NULL; - } -} - -static void -clone_set_src_drawable (GimpDrawable *drawable) -{ - if (src_drawable_ == drawable) - return; - if (src_drawable_) - gtk_signal_disconnect_by_data (GTK_OBJECT (src_drawable_), &src_drawable_); - src_drawable_ = drawable; - if (drawable) - { - gtk_signal_connect (GTK_OBJECT (drawable), "destroy", - GTK_SIGNAL_FUNC (clone_src_drawable_destroyed_cb), - &src_drawable_); - } -} - -static gpointer -clone_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - GDisplay *gdisp; - GDisplay *src_gdisp; - gint x1, y1, x2, y2; - static gint orig_src_x, orig_src_y; - - gdisp = (GDisplay *) active_tool->gdisp; - - switch (state) - { - case PRETRACE_PAINT: - draw_core_pause (paint_core->core, active_tool); - break; - - case MOTION_PAINT: - x1 = paint_core->curx; - y1 = paint_core->cury; - x2 = paint_core->lastx; - y2 = paint_core->lasty; - - /* If the control key is down, move the src target and return */ - if (paint_core->state & GDK_CONTROL_MASK) - { - src_x = x1; - src_y = y1; - first = TRUE; - } - /* otherwise, update the target */ - else - { - dest_x = x1; - dest_y = y1; - - if (clone_options->aligned == ALIGN_REGISTERED) - { - offset_x = 0; - offset_y = 0; - } - else if (first) - { - offset_x = src_x - dest_x; - offset_y = src_y - dest_y; - first = FALSE; - } - - src_x = dest_x + offset_x; - src_y = dest_y + offset_y; - - clone_motion (paint_core, drawable, src_drawable_, - clone_options->paint_options.pressure_options, - clone_options->type, offset_x, offset_y); - } - - break; - - case INIT_PAINT: - if (paint_core->state & GDK_CONTROL_MASK) - { - the_src_gdisp = gdisp; - clone_set_src_drawable(drawable); - src_x = paint_core->curx; - src_y = paint_core->cury; - first = TRUE; - } - else if (clone_options->aligned == ALIGN_NO) - { - first = TRUE; - orig_src_x = src_x; - orig_src_y = src_y; - } - if (clone_options->type == PATTERN_CLONE) - if (! gimp_context_get_pattern (NULL)) - g_message (_("No patterns available for this operation.")); - break; - - case FINISH_PAINT: - draw_core_stop (paint_core->core, active_tool); - if (clone_options->aligned == ALIGN_NO && !first) - { - src_x = orig_src_x; - src_y = orig_src_y; - } - return NULL; - break; - - default: - break; - } - - /* Calculate the coordinates of the target */ - src_gdisp = the_src_gdisp; - if (!src_gdisp) - { - the_src_gdisp = gdisp; - src_gdisp = the_src_gdisp; - } - - if (state == INIT_PAINT) - /* Initialize the tool drawing core */ - draw_core_start (paint_core->core, - src_gdisp->canvas->window, - active_tool); - else if (state == POSTTRACE_PAINT) - { - /* Find the target cursor's location onscreen */ - gdisplay_transform_coords (src_gdisp, src_x, src_y, - &trans_tx, &trans_ty, 1); - draw_core_resume (paint_core->core, active_tool); - } - return NULL; -} - -void -clone_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Layer *layer; - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; - gint x, y; - - gdisplay_untransform_coords (gdisp, (double) mevent->x, (double) mevent->y, - &x, &y, TRUE, FALSE); - - if ((layer = gimp_image_get_active_layer (gdisp->gimage))) - { - int off_x, off_y; - - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); - - if (x >= off_x && y >= off_y && - x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && - y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) - { - /* One more test--is there a selected region? - * if so, is cursor inside? - */ - if (gimage_mask_is_empty (gdisp->gimage)) - ctype = GIMP_MOUSE_CURSOR; - else if (gimage_mask_value (gdisp->gimage, x, y)) - ctype = GIMP_MOUSE_CURSOR; - } - } - - if (clone_options->type == IMAGE_CLONE) - { - if (mevent->state & GDK_CONTROL_MASK) - ctype = GIMP_CROSSHAIR_SMALL_CURSOR; - else if (!src_drawable_) - ctype = GIMP_BAD_CURSOR; - } - - gdisplay_install_tool_cursor (gdisp, ctype, - ctype == GIMP_CROSSHAIR_SMALL_CURSOR ? - TOOL_TYPE_NONE : CLONE, - CURSOR_MODIFIER_NONE, - FALSE); -} - -Tool * -tools_new_clone (void) -{ - Tool * tool; - PaintCore * private; - - /* The tool options */ - if (! clone_options) - { - clone_options = clone_options_new (); - tools_register (CLONE, (ToolOptions *) clone_options); - - /* press all default buttons */ - clone_options_reset (); - } - - tool = paint_core_new (CLONE); - /* the clone tool provides its own cursor_update_function - until I figure out somethinh nicer -- Sven */ - tool->cursor_update_func = clone_cursor_update; - - private = (PaintCore *) tool->private; - private->paint_func = clone_paint_func; - private->core->draw_func = clone_draw; - private->flags |= TOOL_TRACES_ON_WINDOW; - - return tool; -} - -void -tools_free_clone (Tool *tool) -{ - paint_core_free (tool); -} - -static void -clone_draw (Tool *tool) -{ - PaintCore * paint_core; - - paint_core = (PaintCore *) tool->private; - - if (paint_core->core->gc != NULL && clone_options->type == IMAGE_CLONE) - { - gdk_draw_line (paint_core->core->win, paint_core->core->gc, - trans_tx - (TARGET_WIDTH >> 1), trans_ty, - trans_tx + (TARGET_WIDTH >> 1), trans_ty); - gdk_draw_line (paint_core->core->win, paint_core->core->gc, - trans_tx, trans_ty - (TARGET_HEIGHT >> 1), - trans_tx, trans_ty + (TARGET_HEIGHT >> 1)); - } -} - -static void -clone_motion (PaintCore *paint_core, - GimpDrawable *drawable, - GimpDrawable *src_drawable, - PaintPressureOptions *pressure_options, - CloneType type, - int offset_x, - int offset_y) -{ - GImage *gimage; - GImage *src_gimage = NULL; - unsigned char * s; - unsigned char * d; - TempBuf * orig; - TempBuf * area; - void * pr; - int y; - int x1, y1, x2, y2; - int has_alpha = -1; - PixelRegion srcPR, destPR; - GPattern *pattern; - gint opacity; - gdouble scale; - - pr = NULL; - pattern = NULL; - - /* Make sure we still have a source if we are doing image cloning */ - if (type == IMAGE_CLONE) - { - if (!src_drawable) - return; - if (! (src_gimage = gimp_drawable_gimage (src_drawable))) - return; - /* Determine whether the source image has an alpha channel */ - has_alpha = gimp_drawable_has_alpha (src_drawable); - } - - /* We always need a destination image */ - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - /* Get a region which can be used to paint to */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - switch (type) - { - case IMAGE_CLONE: - /* Set the paint area to transparent */ - temp_buf_data_clear (area); - - /* If the source gimage is different from the destination, - * then we should copy straight from the destination image - * to the canvas. - * Otherwise, we need a call to get_orig_image to make sure - * we get a copy of the unblemished (offset) image - */ - if (src_drawable != drawable) - { - x1 = CLAMP (area->x + offset_x, 0, gimp_drawable_width (src_drawable)); - y1 = CLAMP (area->y + offset_y, 0, gimp_drawable_height (src_drawable)); - x2 = CLAMP (area->x + offset_x + area->width, - 0, gimp_drawable_width (src_drawable)); - y2 = CLAMP (area->y + offset_y + area->height, - 0, gimp_drawable_height (src_drawable)); - - if (!(x2 - x1) || !(y2 - y1)) - return; - - pixel_region_init (&srcPR, gimp_drawable_data (src_drawable), - x1, y1, (x2 - x1), (y2 - y1), FALSE); - } - else - { - x1 = CLAMP (area->x + offset_x, 0, gimp_drawable_width (drawable)); - y1 = CLAMP (area->y + offset_y, 0, gimp_drawable_height (drawable)); - x2 = CLAMP (area->x + offset_x + area->width, - 0, gimp_drawable_width (drawable)); - y2 = CLAMP (area->y + offset_y + area->height, - 0, gimp_drawable_height (drawable)); - - if (!(x2 - x1) || !(y2 - y1)) - return; - - /* get the original image */ - orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2); - - srcPR.bytes = orig->bytes; - srcPR.x = 0; srcPR.y = 0; - srcPR.w = x2 - x1; - srcPR.h = y2 - y1; - srcPR.rowstride = srcPR.bytes * orig->width; - srcPR.data = temp_buf_data (orig); - } - - offset_x = x1 - (area->x + offset_x); - offset_y = y1 - (area->y + offset_y); - - /* configure the destination */ - destPR.bytes = area->bytes; - destPR.x = 0; destPR.y = 0; - destPR.w = srcPR.w; - destPR.h = srcPR.h; - destPR.rowstride = destPR.bytes * area->width; - destPR.data = temp_buf_data (area) + offset_y * destPR.rowstride + - offset_x * destPR.bytes; - - pr = pixel_regions_register (2, &srcPR, &destPR); - break; - - case PATTERN_CLONE: - pattern = gimp_context_get_pattern (NULL); - - if (!pattern) - return; - - destPR.bytes = area->bytes; - destPR.x = 0; destPR.y = 0; - destPR.w = area->width; - destPR.h = area->height; - destPR.rowstride = destPR.bytes * area->width; - destPR.data = temp_buf_data (area); - - pr = pixel_regions_register (1, &destPR); - break; - } - - for (; pr != NULL; pr = pixel_regions_process (pr)) - { - s = srcPR.data; - d = destPR.data; - for (y = 0; y < destPR.h; y++) - { - switch (type) - { - case IMAGE_CLONE: - clone_line_image (gimage, src_gimage, drawable, src_drawable, s, d, - has_alpha, srcPR.bytes, destPR.bytes, destPR.w); - s += srcPR.rowstride; - break; - case PATTERN_CLONE: - clone_line_pattern (gimage, drawable, pattern, d, - area->x + offset_x, area->y + y + offset_y, - destPR.bytes, destPR.w); - break; - } - - d += destPR.rowstride; - } - } - - opacity = 255.0 * gimp_context_get_opacity (NULL); - if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; - - /* paste the newly painted canvas to the gimage which is being worked on */ - paint_core_paste_canvas (paint_core, drawable, - MIN (opacity, 255), - (int) (gimp_context_get_opacity (NULL) * 255), - gimp_context_get_paint_mode (NULL), - pressure_options->pressure ? PRESSURE : SOFT, - scale, CONSTANT); -} - - -static void -clone_line_image (GImage *dest, - GImage *src, - GimpDrawable *d_drawable, - GimpDrawable *s_drawable, - unsigned char *s, - unsigned char *d, - int has_alpha, - int src_bytes, - int dest_bytes, - int width) -{ - unsigned char rgb[3]; - int src_alpha, dest_alpha; - - src_alpha = src_bytes - 1; - dest_alpha = dest_bytes - 1; - - while (width--) - { - gimp_image_get_color (src, gimp_drawable_type (s_drawable), rgb, s); - gimp_image_transform_color (dest, d_drawable, rgb, d, RGB); - - if (has_alpha) - d[dest_alpha] = s[src_alpha]; - else - d[dest_alpha] = OPAQUE_OPACITY; - - s += src_bytes; - d += dest_bytes; - } -} - -static void -clone_line_pattern (GImage *dest, - GimpDrawable *drawable, - GPattern *pattern, - unsigned char *d, - int x, - int y, - int bytes, - int width) -{ - guchar *pat, *p; - gint color, alpha; - gint i; - - /* Make sure x, y are positive */ - while (x < 0) - x += pattern->mask->width; - while (y < 0) - y += pattern->mask->height; - - /* Get a pointer to the appropriate scanline of the pattern buffer */ - pat = temp_buf_data (pattern->mask) + - (y % pattern->mask->height) * pattern->mask->width * pattern->mask->bytes; - color = (pattern->mask->bytes == 3) ? RGB : GRAY; - - alpha = bytes - 1; - - for (i = 0; i < width; i++) - { - p = pat + ((i + x) % pattern->mask->width) * pattern->mask->bytes; - - gimp_image_transform_color (dest, drawable, p, d, color); - - d[alpha] = OPAQUE_OPACITY; - - d += bytes; - } -} - -static gpointer -clone_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - clone_motion (paint_core, drawable, non_gui_src_drawable, - &non_gui_pressure_options, - non_gui_type, non_gui_offset_x, non_gui_offset_y); - - return NULL; -} - -gboolean -clone_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array) -{ - GimpDrawable *src_drawable = NULL; - CloneType clone_type = CLONE_DEFAULT_TYPE; - gdouble local_src_x = 0.0; - gdouble local_src_y = 0.0; - CloneOptions *options = clone_options; - - if (options) - { - clone_type = options->type; - src_drawable = src_drawable_; - local_src_x = src_x; - local_src_y = src_y; - } - - return clone_non_gui (drawable, - src_drawable, - clone_type, - local_src_x,local_src_y, - num_strokes, stroke_array); -} - -gboolean -clone_non_gui (GimpDrawable *drawable, - GimpDrawable *src_drawable, - CloneType clone_type, - gdouble src_x, - gdouble src_y, - gint num_strokes, - gdouble *stroke_array) -{ - gint i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = clone_non_gui_paint_func; - - non_gui_type = clone_type; - - non_gui_src_drawable = src_drawable; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - non_gui_offset_x = (int) (src_x - non_gui_paint_core.startx); - non_gui_offset_y = (int) (src_y - non_gui_paint_core.starty); - - clone_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - return TRUE; - } - else - return FALSE; -} diff --git a/app/clone.h b/app/clone.h deleted file mode 100644 index fcc2f1d247..0000000000 --- a/app/clone.h +++ /dev/null @@ -1,44 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __CLONE_H__ -#define __CLONE_H__ - - -typedef enum -{ - IMAGE_CLONE, - PATTERN_CLONE -} CloneType; - - -gboolean clone_non_gui (GimpDrawable *drawable, - GimpDrawable *src_drawable, - CloneType clone_type, - gdouble src_x, - gdouble src_y, - gint num_strokes, - gdouble *stroke_array); -gboolean clone_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array); -Tool * tools_new_clone (void); -void tools_free_clone (Tool *tool); - - -#endif /* __CLONE_H__ */ diff --git a/app/color_balance.c b/app/color_balance.c deleted file mode 100644 index 2c05f61eb3..0000000000 --- a/app/color_balance.c +++ /dev/null @@ -1,749 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "color_balance.h" -#include "color_transfer.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "image_map.h" -#include "pixel_region.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpintl.h" -#include "libgimp/gimpmath.h" -#include "libgimp/gimpcolorspace.h" - - -#define CYAN_RED 0x1 -#define MAGENTA_GREEN 0x2 -#define YELLOW_BLUE 0x4 -#define ALL (CYAN_RED | MAGENTA_GREEN | YELLOW_BLUE) - -/* the color balance structures */ - -typedef struct _ColorBalance ColorBalance; - -struct _ColorBalance -{ - gint x, y; /* coords for last mouse click */ -}; - -/* the color balance tool options */ -static ToolOptions *color_balance_options = NULL; - -/* the color balance dialog */ -static ColorBalanceDialog *color_balance_dialog = NULL; - - -/* color balance action functions */ - -static void color_balance_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static ColorBalanceDialog * color_balance_dialog_new (void); - -static void color_balance_update (ColorBalanceDialog *cbd, - gint ); -static void color_balance_preview (ColorBalanceDialog *cbd); -static void color_balance_reset_callback (GtkWidget *widget, - gpointer data); -static void color_balance_ok_callback (GtkWidget *widget, - gpointer data); -static void color_balance_cancel_callback (GtkWidget *widget, - gpointer data); -static void color_balance_range_callback (GtkWidget *widget, - gpointer data); -static void color_balance_preserve_update (GtkWidget *widget, - gpointer data); -static void color_balance_preview_update (GtkWidget *widget, - gpointer data); -static void color_balance_cr_adjustment_update (GtkAdjustment *adj, - gpointer data); -static void color_balance_mg_adjustment_update (GtkAdjustment *adj, - gpointer data); -static void color_balance_yb_adjustment_update (GtkAdjustment *adj, - gpointer data); - -/* color balance machinery */ - -void -color_balance (PixelRegion *srcPR, - PixelRegion *destPR, - void *data) -{ - ColorBalanceDialog *cbd; - guchar *src, *s; - guchar *dest, *d; - gboolean alpha; - gint r, g, b; - gint r_n, g_n, b_n; - gint w, h; - - cbd = (ColorBalanceDialog *) data; - - h = srcPR->h; - src = srcPR->data; - dest = destPR->data; - alpha = (srcPR->bytes == 4) ? TRUE : FALSE; - - while (h--) - { - w = srcPR->w; - s = src; - d = dest; - while (w--) - { - r = s[RED_PIX]; - g = s[GREEN_PIX]; - b = s[BLUE_PIX]; - - r_n = cbd->r_lookup[r]; - g_n = cbd->g_lookup[g]; - b_n = cbd->b_lookup[b]; - - if (cbd->preserve_luminosity) - { - gimp_rgb_to_hls_int (&r_n, &g_n, &b_n); - g_n = gimp_rgb_to_l_int (r, g, b); - gimp_hls_to_rgb_int (&r_n, &g_n, &b_n); - } - - d[RED_PIX] = r_n; - d[GREEN_PIX] = g_n; - d[BLUE_PIX] = b_n; - - if (alpha) - d[ALPHA_PIX] = s[ALPHA_PIX]; - - s += srcPR->bytes; - d += destPR->bytes; - } - - src += srcPR->rowstride; - dest += destPR->rowstride; - } -} - -/* color balance action functions */ - -static void -color_balance_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - ColorBalance * color_bal; - - color_bal = (ColorBalance *) tool->private; - - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - color_balance_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_color_balance (void) -{ - Tool * tool; - ColorBalance * private; - - /* The tool options */ - if (!color_balance_options) - { - color_balance_options = tool_options_new (_("Color Balance")); - tools_register (COLOR_BALANCE, color_balance_options); - } - - tool = tools_new_tool (COLOR_BALANCE); - private = g_new0 (ColorBalance, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = color_balance_control; - - return tool; -} - -void -color_balance_dialog_hide (void) -{ - if (color_balance_dialog) - color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog); -} - -void -tools_free_color_balance (Tool *tool) -{ - ColorBalance * color_bal; - - color_bal = (ColorBalance *) tool->private; - - /* Close the color select dialog */ - color_balance_dialog_hide (); - - g_free (color_bal); -} - -void -color_balance_initialize (GDisplay *gdisp) -{ - gint i; - - if (! gimp_drawable_is_rgb (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Color balance operates only on RGB color drawables.")); - return; - } - - /* The color balance dialog */ - if (!color_balance_dialog) - color_balance_dialog = color_balance_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (color_balance_dialog->shell)) - gtk_widget_show (color_balance_dialog->shell); - - for (i = 0; i < 3; i++) - { - color_balance_dialog->cyan_red[i] = 0.0; - color_balance_dialog->magenta_green[i] = 0.0; - color_balance_dialog->yellow_blue[i] = 0.0; - } - - color_balance_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - color_balance_dialog->image_map = - image_map_create (gdisp, color_balance_dialog->drawable); - - color_balance_update (color_balance_dialog, ALL); -} - -/**************************/ -/* Color Balance dialog */ -/**************************/ - -static ColorBalanceDialog * -color_balance_dialog_new (void) -{ - ColorBalanceDialog *cbd; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *table; - GtkWidget *start_label; - GtkWidget *end_label; - GtkWidget *label; - GtkWidget *spinbutton; - GtkWidget *slider; - GtkWidget *toggle; - GtkWidget *radio_button; - GtkObject *data; - GSList *group = NULL; - gint i; - - gchar *appl_mode_names[] = - { - N_("Shadows"), - N_("Midtones"), - N_("Highlights") - }; - - cbd = g_new (ColorBalanceDialog, 1); - cbd->preserve_luminosity = TRUE; - cbd->preview = TRUE; - cbd->application_mode = SHADOWS; - - /* The shell and main vbox */ - cbd->shell = gimp_dialog_new (_("Color Balance"), "color_balance", - tools_help_func, NULL, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), color_balance_ok_callback, - cbd, NULL, NULL, TRUE, FALSE, - _("Reset"), color_balance_reset_callback, - cbd, NULL, NULL, TRUE, FALSE, - _("Cancel"), color_balance_cancel_callback, - cbd, NULL, NULL, FALSE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (cbd->shell)->vbox), vbox); - - /* Horizontal box for application mode */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Color Levels:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* cyan-red spinbutton */ - data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0); - cbd->cyan_red_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (cbd->cyan_red_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - gtk_widget_show (spinbutton); - - /* magenta-green spinbutton */ - data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0); - cbd->magenta_green_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (cbd->magenta_green_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - gtk_widget_show (spinbutton); - - /* yellow-blue spinbutton */ - data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0); - cbd->yellow_blue_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (cbd->yellow_blue_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - gtk_widget_show (spinbutton); - - gtk_widget_show (hbox); - - /* The table containing sliders */ - table = gtk_table_new (3, 3, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - /* Create the cyan-red scale widget */ - start_label = gtk_label_new (_("Cyan")); - gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - slider = gtk_hscale_new (cbd->cyan_red_data); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1); - - gtk_signal_connect (GTK_OBJECT (cbd->cyan_red_data), "value_changed", - GTK_SIGNAL_FUNC (color_balance_cr_adjustment_update), - cbd); - - end_label = gtk_label_new (_("Red")); - gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0); - gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_widget_show (start_label); - gtk_widget_show (end_label); - gtk_widget_show (slider); - - /* Create the magenta-green scale widget */ - start_label = gtk_label_new (_("Magenta")); - gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - slider = gtk_hscale_new (cbd->magenta_green_data); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2); - - gtk_signal_connect (GTK_OBJECT (cbd->magenta_green_data), "value_changed", - GTK_SIGNAL_FUNC (color_balance_mg_adjustment_update), - cbd); - - end_label = gtk_label_new (_("Green")); - gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0); - gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_widget_show (start_label); - gtk_widget_show (end_label); - gtk_widget_show (slider); - - /* Create the yellow-blue scale widget */ - start_label = gtk_label_new (_("Yellow")); - gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 2, 3, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - slider = gtk_hscale_new (cbd->yellow_blue_data); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 2, 3); - - gtk_signal_connect (GTK_OBJECT (cbd->yellow_blue_data), "value_changed", - GTK_SIGNAL_FUNC (color_balance_yb_adjustment_update), - cbd); - - end_label = gtk_label_new (_("Blue")); - gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0); - gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 2, 3, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_widget_show (start_label); - gtk_widget_show (end_label); - gtk_widget_show (slider); - - gtk_widget_show (table); - - /* Horizontal box for application mode */ - hbox = gtk_hbox_new (TRUE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* the radio buttons for application mode */ - for (i = 0; i < 3; i++) - { - radio_button = - gtk_radio_button_new_with_label (group, gettext (appl_mode_names[i])); - group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button)); - gtk_box_pack_start (GTK_BOX (hbox), radio_button, TRUE, FALSE, 0); - - gtk_object_set_user_data (GTK_OBJECT (radio_button), (gpointer) i); - gtk_signal_connect (GTK_OBJECT (radio_button), "toggled", - GTK_SIGNAL_FUNC (color_balance_range_callback), - cbd); - - gtk_widget_show (radio_button); - } - - gtk_widget_show (hbox); - - /* Horizontal box for preview and preserve luminosity toggle buttons */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* The preserve luminosity toggle */ - toggle = gtk_check_button_new_with_label (_("Preserve Luminosity")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), - cbd->preserve_luminosity); - gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (color_balance_preserve_update), - cbd); - gtk_widget_show (toggle); - - /* The preview toggle */ - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cbd->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (color_balance_preview_update), - cbd); - gtk_widget_show (toggle); - - gtk_widget_show (hbox); - - gtk_widget_show (vbox); - gtk_widget_show (cbd->shell); - - return cbd; -} - -static void -color_balance_update (ColorBalanceDialog *cbd, - gint update) -{ - if (update & CYAN_RED) - { - gtk_adjustment_set_value (cbd->cyan_red_data, - cbd->cyan_red[cbd->application_mode]); - } - if (update & MAGENTA_GREEN) - { - gtk_adjustment_set_value (cbd->magenta_green_data, - cbd->magenta_green[cbd->application_mode]); - } - if (update & YELLOW_BLUE) - { - gtk_adjustment_set_value (cbd->yellow_blue_data, - cbd->yellow_blue[cbd->application_mode]); - } -} - -void -color_balance_create_lookup_tables (ColorBalanceDialog *cbd) -{ - gdouble *cyan_red_transfer[3]; - gdouble *magenta_green_transfer[3]; - gdouble *yellow_blue_transfer[3]; - gint i; - gint32 r_n, g_n, b_n; - - /* Set the transfer arrays (for speed) */ - cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub; - cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub; - cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub; - magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub; - magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub; - magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub; - yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub; - yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub; - yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub; - - for (i = 0; i < 256; i++) - { - r_n = i; - g_n = i; - b_n = i; - - r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n]; - r_n = CLAMP0255 (r_n); - r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n]; - r_n = CLAMP0255 (r_n); - r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n]; - r_n = CLAMP0255 (r_n); - - g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n]; - g_n = CLAMP0255 (g_n); - g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n]; - g_n = CLAMP0255 (g_n); - g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n]; - g_n = CLAMP0255 (g_n); - - b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n]; - b_n = CLAMP0255 (b_n); - b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n]; - b_n = CLAMP0255 (b_n); - b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n]; - b_n = CLAMP0255 (b_n); - - cbd->r_lookup[i] = r_n; - cbd->g_lookup[i] = g_n; - cbd->b_lookup[i] = b_n; - } -} - -static void -color_balance_preview (ColorBalanceDialog *cbd) -{ - if (!cbd->image_map) - { - g_message ("color_balance_preview(): No image map"); - return; - } - - active_tool->preserve = TRUE; - color_balance_create_lookup_tables (cbd); - image_map_apply (cbd->image_map, color_balance, (void *) cbd); - active_tool->preserve = FALSE; -} - -static void -color_balance_reset_callback (GtkWidget *widget, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - cbd->cyan_red[cbd->application_mode] = 0.0; - cbd->magenta_green[cbd->application_mode] = 0.0; - cbd->yellow_blue[cbd->application_mode] = 0.0; - - color_balance_update (cbd, ALL); - - if (cbd->preview) - color_balance_preview (cbd); -} - -static void -color_balance_ok_callback (GtkWidget *widget, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - gimp_dialog_hide (cbd->shell); - - active_tool->preserve = TRUE; - - if (!cbd->preview) - image_map_apply (cbd->image_map, color_balance, (void *) cbd); - - if (cbd->image_map) - image_map_commit (cbd->image_map); - - active_tool->preserve = FALSE; - - cbd->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -color_balance_cancel_callback (GtkWidget *widget, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - gimp_dialog_hide (cbd->shell); - - if (cbd->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (cbd->image_map); - active_tool->preserve = FALSE; - - gdisplays_flush (); - cbd->image_map = NULL; - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -color_balance_range_callback (GtkWidget *widget, - gpointer data) -{ - ColorBalanceDialog *cbd; - TransferMode range; - - cbd = (ColorBalanceDialog *) data; - - range = (TransferMode) gtk_object_get_user_data (GTK_OBJECT (widget)); - cbd->application_mode = range; - - color_balance_update (cbd, ALL); -} - -static void -color_balance_preserve_update (GtkWidget *widget, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - cbd->preserve_luminosity = TRUE; - else - cbd->preserve_luminosity = FALSE; - - if (cbd->preview) - color_balance_preview (cbd); -} - -static void -color_balance_preview_update (GtkWidget *widget, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - cbd->preview = TRUE; - color_balance_preview (cbd); - } - else - { - cbd->preview = FALSE; - if (cbd->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (cbd->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } -} - -static void -color_balance_cr_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - if (cbd->cyan_red[cbd->application_mode] != adjustment->value) - { - cbd->cyan_red[cbd->application_mode] = adjustment->value; - - if (cbd->preview) - color_balance_preview (cbd); - } -} - -static void -color_balance_mg_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - if (cbd->magenta_green[cbd->application_mode] != adjustment->value) - { - cbd->magenta_green[cbd->application_mode] = adjustment->value; - - if (cbd->preview) - color_balance_preview (cbd); - } -} - -static void -color_balance_yb_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - ColorBalanceDialog *cbd; - - cbd = (ColorBalanceDialog *) data; - - if (cbd->yellow_blue[cbd->application_mode] != adjustment->value) - { - cbd->yellow_blue[cbd->application_mode] = adjustment->value; - - if (cbd->preview) - color_balance_preview (cbd); - } -} diff --git a/app/color_balance.h b/app/color_balance.h deleted file mode 100644 index 0f14e5fac4..0000000000 --- a/app/color_balance.h +++ /dev/null @@ -1,68 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __COLOR_BALANCE_H__ -#define __COLOR_BALANCE_H__ - - -typedef enum -{ - SHADOWS, - MIDTONES, - HIGHLIGHTS -} TransferMode; - -typedef struct _ColorBalanceDialog ColorBalanceDialog; - -struct _ColorBalanceDialog -{ - GtkWidget *shell; - - GtkAdjustment *cyan_red_data; - GtkAdjustment *magenta_green_data; - GtkAdjustment *yellow_blue_data; - - GimpDrawable *drawable; - ImageMap image_map; - - gdouble cyan_red[3]; - gdouble magenta_green[3]; - gdouble yellow_blue[3]; - - guchar r_lookup[256]; - guchar g_lookup[256]; - guchar b_lookup[256]; - - gboolean preserve_luminosity; - gboolean preview; - TransferMode application_mode; -}; - -Tool * tools_new_color_balance (void); -void tools_free_color_balance (Tool *tool); - -void color_balance_initialize (GDisplay *gdisp); -void color_balance_dialog_hide (void); -void color_balance (PixelRegion *srcPR, - PixelRegion *destPR, - void *data); - -void color_balance_create_lookup_tables (ColorBalanceDialog *cbd); - - -#endif /* __COLOR_BALANCE_H__ */ diff --git a/app/color_picker.c b/app/color_picker.c deleted file mode 100644 index 2a78f3d781..0000000000 --- a/app/color_picker.c +++ /dev/null @@ -1,824 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "libgimp/gimpcolorarea.h" - -#include "appenv.h" -#include "color_picker.h" -#include "draw_core.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "gimprc.h" -#include "cursorutil.h" -#include "info_dialog.h" -#include "palette.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpintl.h" - - -/* maximum information buffer size */ -#define MAX_INFO_BUF 8 - -/* the color picker structures */ - -typedef struct _ColorPickerOptions ColorPickerOptions; - -struct _ColorPickerOptions -{ - ToolOptions tool_options; - - gboolean sample_merged; - gboolean sample_merged_d; - GtkWidget *sample_merged_w; - - gboolean sample_average; - gboolean sample_average_d; - GtkWidget *sample_average_w; - - gdouble average_radius; - gdouble average_radius_d; - GtkObject *average_radius_w; - - gboolean update_active; - gboolean update_active_d; - GtkWidget *update_active_w; -}; - -typedef struct _ColorPickerTool ColorPickerTool; - -struct _ColorPickerTool -{ - DrawCore *core; /* Core select object */ - - gint centerx; /* starting x coord */ - gint centery; /* starting y coord */ -}; - -/* the color picker tool options */ -static ColorPickerOptions * color_picker_options = NULL; - -/* the color value */ -gint col_value[5] = { 0, 0, 0, 0, 0 }; - -/* the color picker dialog */ -static gint update_type; -static GimpImageType sample_type; -static InfoDialog *color_picker_info = NULL; -static GtkWidget *color_area = NULL; -static gchar red_buf [MAX_INFO_BUF]; -static gchar green_buf [MAX_INFO_BUF]; -static gchar blue_buf [MAX_INFO_BUF]; -static gchar alpha_buf [MAX_INFO_BUF]; -static gchar index_buf [MAX_INFO_BUF]; -static gchar gray_buf [MAX_INFO_BUF]; -static gchar hex_buf [MAX_INFO_BUF]; - - -/* local function prototypes */ - -static void color_picker_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void color_picker_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void color_picker_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void color_picker_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void color_picker_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static void color_picker_info_window_close_callback (GtkWidget *widget, - gpointer data); -static void color_picker_info_update (Tool *tool, - gboolean valid); - -static gboolean pick_color_do (GimpImage *gimage, - GimpDrawable *drawable, - gint x, - gint y, - gboolean sample_merged, - gboolean sample_average, - gdouble average_radius, - gboolean update_active, - gint final); - -/* functions */ - -static void -color_picker_options_reset (void) -{ - ColorPickerOptions *options = color_picker_options; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w), - options->sample_merged_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_average_w), - options->sample_average_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->average_radius_w), - options->average_radius_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->update_active_w), - options->update_active_d); -} - -static ColorPickerOptions * -color_picker_options_new (void) -{ - ColorPickerOptions *options; - - GtkWidget *vbox; - GtkWidget *abox; - GtkWidget *table; - GtkWidget *label; - GtkWidget *scale; - - /* the new color picker tool options structure */ - options = g_new (ColorPickerOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Color Picker"), - color_picker_options_reset); - options->sample_merged = options->sample_merged_d = FALSE; - options->sample_average = options->sample_average_d = FALSE; - options->average_radius = options->average_radius_d = 1.0; - options->update_active = options->update_active_d = TRUE; - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* the sample merged toggle button */ - options->sample_merged_w = - gtk_check_button_new_with_label (_("Sample Merged")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w), - options->sample_merged_d); - gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->sample_merged); - gtk_widget_show (options->sample_merged_w); - - /* the sample average options */ - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - options->sample_average_w = - gtk_check_button_new_with_label (_("Sample Average")); - gtk_table_attach (GTK_TABLE (table), options->sample_average_w, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_average_w), - options->sample_average_d); - gtk_signal_connect (GTK_OBJECT (options->sample_average_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->sample_average); - gtk_widget_show (options->sample_average_w); - - label = gtk_label_new (_("Radius:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - /* the feather radius scale */ - abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); - gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 0, 2, - GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (abox); - - options->average_radius_w = - gtk_adjustment_new (options->average_radius_d, 1.0, 15.0, 2.0, 2.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->average_radius_w)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_container_add (GTK_CONTAINER (abox), scale); - gtk_widget_set_sensitive (scale, options->sample_average_d); - gtk_object_set_data (GTK_OBJECT (options->sample_average_w), "set_sensitive", - scale); - gtk_widget_set_sensitive (label, options->sample_average_d); - gtk_object_set_data (GTK_OBJECT (scale), "set_sensitive", - label); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->average_radius_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->average_radius); - gtk_widget_show (scale); - gtk_widget_show (table); - - /* the update active color toggle button */ - options->update_active_w = - gtk_check_button_new_with_label (_("Update Active Color")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->update_active_w), - options->update_active_d); - gtk_box_pack_start (GTK_BOX (vbox), options->update_active_w, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->update_active_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->update_active); - gtk_widget_show (options->update_active_w); - - return options; -} - -static void -color_picker_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - ColorPickerTool *cp_tool; - gint x, y; - - cp_tool = (ColorPickerTool *) tool->private; - - /* Make the tool active and set it's gdisplay & drawable */ - tool->gdisp = gdisp; - tool->drawable = gimp_image_active_drawable (gdisp->gimage); - tool->state = ACTIVE; - - /* create the info dialog if it doesn't exist */ - if (! color_picker_info) - { - GtkWidget *hbox; - GtkWidget *frame; - GimpRGB color; - - color_picker_info = info_dialog_new (_("Color Picker"), - tools_help_func, NULL); - - /* if the gdisplay is for a color image, the dialog must have RGB */ - switch (gimp_drawable_type (tool->drawable)) - { - case RGB_GIMAGE: case RGBA_GIMAGE: - info_dialog_add_label (color_picker_info, _("Red:"), red_buf); - info_dialog_add_label (color_picker_info, _("Green:"), green_buf); - info_dialog_add_label (color_picker_info, _("Blue:"), blue_buf); - info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf); - info_dialog_add_label (color_picker_info, _("Hex Triplet:"), hex_buf); - break; - - case INDEXED_GIMAGE: case INDEXEDA_GIMAGE: - info_dialog_add_label (color_picker_info, _("Index:"), index_buf); - info_dialog_add_label (color_picker_info, _("Red:"), red_buf); - info_dialog_add_label (color_picker_info, _("Green:"), green_buf); - info_dialog_add_label (color_picker_info, _("Blue:"), blue_buf); - info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf); - info_dialog_add_label (color_picker_info, _("Hex Triplet"), hex_buf); - break; - - case GRAY_GIMAGE: case GRAYA_GIMAGE: - info_dialog_add_label (color_picker_info, _("Intensity:"), gray_buf); - info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf); - info_dialog_add_label (color_picker_info, _("Hex Triplet:"), hex_buf); - break; - - default : - break; - } - - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (color_picker_info->vbox), hbox, - FALSE, FALSE, 0); - gtk_widget_show (hbox); - - gtk_widget_reparent (color_picker_info->info_table, hbox); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); - - gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.0); - color_area = - gimp_color_area_new (&color, - gimp_drawable_has_alpha (tool->drawable) ? - GIMP_COLOR_AREA_LARGE_CHECKS : - GIMP_COLOR_AREA_FLAT, - GDK_BUTTON1_MASK | GDK_BUTTON2_MASK); - gtk_widget_set_usize (color_area, 48, 64); - gtk_drag_dest_unset (color_area); - gtk_container_add (GTK_CONTAINER (frame), color_area); - gtk_widget_show (color_area); - gtk_widget_show (frame); - - /* create the action area */ - gimp_dialog_create_action_area - (GTK_DIALOG (color_picker_info->shell), - - _("Close"), color_picker_info_window_close_callback, - color_picker_info, NULL, NULL, TRUE, FALSE, - - NULL); - } - - /* Keep the coordinates of the target */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &cp_tool->centerx, &cp_tool->centery, FALSE, 1); - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - (GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK), - NULL, NULL, bevent->time); - - /* First, transform the coordinates to gimp image space */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, - FALSE, FALSE); - - /* if the shift key is down, create a new color. - * otherwise, modify the current color. - */ - if (bevent->state & GDK_SHIFT_MASK) - { - color_picker_info_update - (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, - color_picker_options->sample_merged, - color_picker_options->sample_average, - color_picker_options->average_radius, - color_picker_options->update_active, - COLOR_NEW)); - update_type = COLOR_UPDATE_NEW; - } - else - { - color_picker_info_update - (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, - color_picker_options->sample_merged, - color_picker_options->sample_average, - color_picker_options->average_radius, - color_picker_options->update_active, - COLOR_UPDATE)); - update_type = COLOR_UPDATE; - } - - /* Start drawing the colorpicker tool */ - draw_core_start (cp_tool->core, gdisp->canvas->window, tool); -} - -static void -color_picker_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - ColorPickerTool *cp_tool; - gint x, y; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - cp_tool = (ColorPickerTool *) tool->private; - - /* First, transform the coordinates to gimp image space */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, - FALSE, FALSE); - - color_picker_info_update - (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, - color_picker_options->sample_merged, - color_picker_options->sample_average, - color_picker_options->average_radius, - color_picker_options->update_active, - update_type)); - - draw_core_stop (cp_tool->core, tool); - tool->state = INACTIVE; -} - -static void -color_picker_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - ColorPickerTool *cp_tool; - gint x, y; - - cp_tool = (ColorPickerTool *) tool->private; - - /* undraw the current tool */ - draw_core_pause (cp_tool->core, tool); - - /* First, transform the coordinates to gimp image space */ - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, - FALSE, FALSE); - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &cp_tool->centerx, &cp_tool->centery, - FALSE, TRUE); - - color_picker_info_update - (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, - color_picker_options->sample_merged, - color_picker_options->sample_average, - color_picker_options->average_radius, - color_picker_options->update_active, - update_type)); - - /* redraw the current tool */ - draw_core_resume (cp_tool->core, tool); -} - -static void -color_picker_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - gint x, y; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, - FALSE, FALSE); - - /* We used to use the following code here: - * - * if (gimp_image_pick_correlate_layer (gdisp->gimage, x, y)) { ... } - */ - - if (gdisp->gimage && - x > 0 && x < gdisp->gimage->width && - y > 0 && y < gdisp->gimage->height) - { - gdisplay_install_tool_cursor (gdisp, GIMP_COLOR_PICKER_CURSOR, - COLOR_PICKER, - CURSOR_MODIFIER_NONE, - FALSE); - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, - COLOR_PICKER, - CURSOR_MODIFIER_NONE, - FALSE); - } -} - -static void -color_picker_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - ColorPickerTool *cp_tool; - - cp_tool = (ColorPickerTool *) tool->private; - - switch (action) - { - case PAUSE : - draw_core_pause (cp_tool->core, tool); - break; - - case RESUME : - draw_core_resume (cp_tool->core, tool); - break; - - case HALT : - draw_core_stop (cp_tool->core, tool); - info_dialog_popdown (color_picker_info); - break; - - default: - break; - } -} - - -typedef guchar * (*GetColorFunc) (GimpObject *object, - gint x, - gint y); - - -static gboolean -pick_color_do (GimpImage *gimage, - GimpDrawable *drawable, - gint x, - gint y, - gboolean sample_merged, - gboolean sample_average, - gdouble average_radius, - gboolean update_active, - gint final) -{ - guchar *color; - gint offx, offy; - gint has_alpha; - gint is_indexed; - GetColorFunc get_color_func; - GimpObject *get_color_obj; - - - if (!drawable && !sample_merged) - return FALSE; - - if (!sample_merged) - { - gimp_drawable_offsets (drawable, &offx, &offy); - x -= offx; - y -= offy; - - sample_type = gimp_drawable_type (drawable); - is_indexed = gimp_drawable_is_indexed (drawable); - - get_color_func = (GetColorFunc) gimp_drawable_get_color_at; - get_color_obj = GIMP_OBJECT (drawable); - } - else - { - sample_type = gimp_image_composite_type (gimage); - is_indexed = FALSE; - - get_color_func = (GetColorFunc) gimp_image_get_color_at; - get_color_obj = GIMP_OBJECT (gimage); - } - - has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (sample_type); - - if (!(color = (* get_color_func) (get_color_obj, x, y))) - return FALSE; - - if (sample_average) - { - gint i, j; - gint count = 0; - gint color_avg[4] = { 0, 0, 0, 0 }; - guchar *tmp_color; - gint radius = (gint) average_radius; - - for (i = x - radius; i <= x + radius; i++) - for (j = y - radius; j <= y + radius; j++) - if ((tmp_color = (* get_color_func) (get_color_obj, i, j))) - { - count++; - - color_avg[RED_PIX] += tmp_color[RED_PIX]; - color_avg[GREEN_PIX] += tmp_color[GREEN_PIX]; - color_avg[BLUE_PIX] += tmp_color[BLUE_PIX]; - if (has_alpha) - color_avg[ALPHA_PIX] += tmp_color[ALPHA_PIX]; - - g_free (tmp_color); - } - - color[RED_PIX] = (guchar) (color_avg[RED_PIX] / count); - color[GREEN_PIX] = (guchar) (color_avg[GREEN_PIX] / count); - color[BLUE_PIX] = (guchar) (color_avg[BLUE_PIX] / count); - if (has_alpha) - color[ALPHA_PIX] = (guchar) (color_avg[ALPHA_PIX] / count); - - is_indexed = FALSE; - } - - col_value[RED_PIX] = color[RED_PIX]; - col_value[GREEN_PIX] = color[GREEN_PIX]; - col_value[BLUE_PIX] = color[BLUE_PIX]; - if (has_alpha) - col_value[ALPHA_PIX] = color[ALPHA_PIX]; - if (is_indexed) - col_value[4] = color[4]; - - if (update_active) - palette_set_active_color (col_value [RED_PIX], - col_value [GREEN_PIX], - col_value [BLUE_PIX], - final); - - g_free (color); - - return TRUE; -} - -gboolean -pick_color (GimpImage *gimage, - GimpDrawable *drawable, - gint x, - gint y, - gboolean sample_merged, - gboolean sample_average, - gdouble average_radius, - gint final) -{ - return pick_color_do (gimage, drawable, - x, y, - sample_merged, - sample_average, - average_radius, - TRUE, - final); -} - -static void -colorpicker_draw (Tool *tool) -{ - ColorPickerTool *cp_tool; - gint tx, ty; - gint radiusx, radiusy; - gint cx, cy; - - if (! color_picker_options->sample_average) - return; - - cp_tool = (ColorPickerTool *) tool->private; - - gdisplay_transform_coords (tool->gdisp, cp_tool->centerx, cp_tool->centery, - &tx, &ty, TRUE); - - radiusx = SCALEX (tool->gdisp, color_picker_options->average_radius); - radiusy = SCALEY (tool->gdisp, color_picker_options->average_radius); - cx = SCALEX (tool->gdisp, 1); - cy = SCALEY (tool->gdisp, 1); - - /* Draw the circle around the collecting area */ - gdk_draw_rectangle (cp_tool->core->win, cp_tool->core->gc, 0, - tx - radiusx, - ty - radiusy, - 2 * radiusx + cx, 2 * radiusy + cy); - - if (radiusx > 1 && radiusy > 1) - { - gdk_draw_rectangle (cp_tool->core->win, cp_tool->core->gc, 0, - tx - radiusx + 2, - ty - radiusy + 2, - 2 * radiusx + cx - 4, 2 * radiusy + cy - 4); - } -} - -static void -color_picker_info_update (Tool *tool, - gboolean valid) -{ - if (!valid) - { - if (GTK_WIDGET_IS_SENSITIVE (color_area)) - gtk_widget_set_sensitive (color_area, FALSE); - - g_snprintf (red_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (green_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (blue_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (index_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (gray_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (hex_buf, MAX_INFO_BUF, _("N/A")); - } - else - { - GimpRGB color; - guchar r = 0; - guchar g = 0; - guchar b = 0; - guchar a = 0; - - if (! GTK_WIDGET_IS_SENSITIVE (color_area)) - gtk_widget_set_sensitive (color_area, TRUE); - - switch (sample_type) - { - case RGB_GIMAGE: case RGBA_GIMAGE: - g_snprintf (index_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (red_buf, MAX_INFO_BUF, "%d", col_value [RED_PIX]); - g_snprintf (green_buf, MAX_INFO_BUF, "%d", col_value [GREEN_PIX]); - g_snprintf (blue_buf, MAX_INFO_BUF, "%d", col_value [BLUE_PIX]); - if (sample_type == RGBA_GIMAGE) - g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]); - else - g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x", - col_value [RED_PIX], - col_value [GREEN_PIX], - col_value [BLUE_PIX]); - - r = col_value [RED_PIX]; - g = col_value [GREEN_PIX]; - b = col_value [BLUE_PIX]; - if (sample_type == RGBA_GIMAGE) - a = col_value [ALPHA_PIX]; - break; - - case INDEXED_GIMAGE: case INDEXEDA_GIMAGE: - g_snprintf (index_buf, MAX_INFO_BUF, "%d", col_value [4]); - g_snprintf (red_buf, MAX_INFO_BUF, "%d", col_value [RED_PIX]); - g_snprintf (green_buf, MAX_INFO_BUF, "%d", col_value [GREEN_PIX]); - g_snprintf (blue_buf, MAX_INFO_BUF, "%d", col_value [BLUE_PIX]); - if (sample_type == INDEXEDA_GIMAGE) - g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]); - else - g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x", - col_value [RED_PIX], - col_value [GREEN_PIX], - col_value [BLUE_PIX]); - - r = col_value [RED_PIX]; - g = col_value [GREEN_PIX]; - b = col_value [BLUE_PIX]; - if (sample_type == INDEXEDA_GIMAGE) - a = col_value [ALPHA_PIX]; - break; - - case GRAY_GIMAGE: case GRAYA_GIMAGE: - g_snprintf (gray_buf, MAX_INFO_BUF, "%d", col_value [GRAY_PIX]); - if (sample_type == GRAYA_GIMAGE) - g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]); - else - g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A")); - g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x", - col_value [GRAY_PIX], - col_value [GRAY_PIX], - col_value [GRAY_PIX]); - - r = col_value [GRAY_PIX]; - g = col_value [GRAY_PIX]; - b = col_value [GRAY_PIX]; - if (sample_type == GRAYA_GIMAGE) - a = col_value [ALPHA_PIX]; - break; - } - - gimp_rgba_set_uchar (&color, r, g, b, a); - - gimp_color_area_set_color (GIMP_COLOR_AREA (color_area), &color); - } - - info_dialog_update (color_picker_info); - info_dialog_popup (color_picker_info); -} - -static void -color_picker_info_window_close_callback (GtkWidget *widget, - gpointer client_data) -{ - info_dialog_popdown ((InfoDialog *) client_data); -} - -Tool * -tools_new_color_picker () -{ - Tool * tool; - ColorPickerTool * private; - - /* The tool options */ - if (! color_picker_options) - { - color_picker_options = color_picker_options_new (); - tools_register (COLOR_PICKER, (ToolOptions *) color_picker_options); - } - - tool = tools_new_tool (COLOR_PICKER); - private = g_new0 (ColorPickerTool, 1); - - private->core = draw_core_new (colorpicker_draw); - - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->button_press_func = color_picker_button_press; - tool->button_release_func = color_picker_button_release; - tool->motion_func = color_picker_motion; - tool->cursor_update_func = color_picker_cursor_update; - tool->control_func = color_picker_control; - - return tool; -} - -void -tools_free_color_picker (Tool *tool) -{ - ColorPickerTool * cp_tool; - - cp_tool = (ColorPickerTool *) tool->private; - - if (tool->state == ACTIVE) - draw_core_stop (cp_tool->core, tool); - - draw_core_free (cp_tool->core); - - if (color_picker_info) - { - info_dialog_free (color_picker_info); - color_picker_info = NULL; - - color_area = NULL; - } - - g_free (cp_tool); -} diff --git a/app/color_picker.h b/app/color_picker.h deleted file mode 100644 index 66ba4ded50..0000000000 --- a/app/color_picker.h +++ /dev/null @@ -1,39 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __COLOR_PICKER_H__ -#define __COLOR_PICKER_H__ - - -extern gint col_value[5]; - - -gboolean pick_color (GimpImage *gimage, - GimpDrawable *drawable, - gint x, - gint y, - gboolean sample_merged, - gboolean sample_average, - double average_radius, - gint final); - -Tool * tools_new_color_picker (void); -void tools_free_color_picker (Tool *tool); - - -#endif /* __COLOR_PICKER_H__ */ diff --git a/app/commands.c b/app/commands.c index 2b9a4f109e..9763a89629 100644 --- a/app/commands.c +++ b/app/commands.c @@ -68,13 +68,14 @@ #include "scale.h" #include "selection.h" #include "tips_dialog.h" -#include "tools.h" #include "undo.h" #ifdef DISPLAY_FILTERS #include "gdisplay_color_ui.h" #endif /* DISPLAY_FILTERS */ +#include "tools/tools.h" + #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/context_manager.c b/app/context_manager.c index 6e3f96103a..32c22f7447 100644 --- a/app/context_manager.c +++ b/app/context_manager.c @@ -28,8 +28,9 @@ #include "gdisplay.h" #include "gimpcontext.h" #include "gimprc.h" -#include "paint_options.h" -#include "tools.h" + +#include "tools/paint_options.h" +#include "tools/tools.h" static GimpContext * global_tool_context; diff --git a/app/convert.c b/app/convert.c index 7d29b2adbc..b5d85d628e 100644 --- a/app/convert.c +++ b/app/convert.c @@ -94,30 +94,31 @@ #include "apptypes.h" #include "appenv.h" -#include "brightness_contrast.h" -#include "color_balance.h" #include "convert.h" #include "cursorutil.h" -#include "curves.h" #include "drawable.h" #include "floating_sel.h" #include "fsdither.h" #include "gdisplay.h" #include "gimpimage.h" #include "gimpui.h" -#include "hue_saturation.h" #include "layer.h" -#include "levels.h" #include "undo.h" #include "palette.h" #include "gimppalette.h" #include "palette_select.h" #include "pixel_region.h" -#include "posterize.h" -#include "threshold.h" #include "tile_manager.h" #include "tile_manager_pvt.h" /* ick ick ick. */ +#include "tools/brightness_contrast.h" +#include "tools/color_balance.h" +#include "tools/curves.h" +#include "tools/hue_saturation.h" +#include "tools/levels.h" +#include "tools/posterize.h" +#include "tools/threshold.h" + #include "libgimp/gimpcolorspace.h" #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/convolve.c b/app/convolve.c deleted file mode 100644 index d5d5d04375..0000000000 --- a/app/convolve.c +++ /dev/null @@ -1,696 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "convolve.h" -#include "gdisplay.h" -#include "gimpbrush.h" -#include "gimpcontext.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "pixel_region.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" -#include "gimage.h" - -#include "libgimp/gimpintl.h" - - -#define FIELD_COLS 4 -#define MIN_BLUR 64 /* (8/9 original pixel) */ -#define MAX_BLUR 0.25 /* (1/33 original pixel) */ -#define MIN_SHARPEN -512 -#define MAX_SHARPEN -64 - -/* defaults */ -#define DEFAULT_CONVOLVE_RATE 50.0 -#define DEFAULT_CONVOLVE_TYPE BLUR_CONVOLVE - - -/* Different clip relationships between a blur-blob and edges: - see convolve_motion */ - -typedef enum -{ - CONVOLVE_NCLIP, /* Left or top edge */ - CONVOLVE_NOT_CLIPPED, /* No edges */ - CONVOLVE_PCLIP /* Right or bottom edge */ -} ConvolveClipType; - - -/* the convolve structures */ - -typedef struct _ConvolveOptions ConvolveOptions; - -struct _ConvolveOptions -{ - PaintOptions paint_options; - - ConvolveType type; - ConvolveType type_d; - GtkWidget *type_w[2]; - - gdouble rate; - gdouble rate_d; - GtkObject *rate_w; -}; - - -/* forward function declarations */ -static void calculate_matrix (ConvolveType type, - gdouble rate); -static void integer_matrix (gfloat *source, - gint *dest, - gint size); -static void copy_matrix (gfloat *src, - gfloat *dest, - gint size); -static gint sum_matrix (gint *matrix, - gint size); - -static gpointer convolve_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); -static void convolve_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - ConvolveType type, - gdouble rate); - - -/* the convolve tool options */ -static ConvolveOptions * convolve_options = NULL; - -/* local variables */ -static gint matrix [25]; -static gint matrix_size; -static gint matrix_divisor; - -static ConvolveType non_gui_type; -static gdouble non_gui_rate; - -static gfloat custom_matrix [25] = -{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -}; - -static gfloat blur_matrix [25] = -{ - 0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 1, MIN_BLUR, 1, 0, - 0, 1, 1, 1, 0, - 0, 0 ,0, 0, 0, -}; - -static gfloat sharpen_matrix [25] = -{ - 0, 0, 0, 0, 0, - 0, 1, 1, 1, 0, - 0, 1, MIN_SHARPEN, 1, 0, - 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, -}; - - -/* functions */ - -static void -convolve_options_reset (void) -{ - ConvolveOptions *options = convolve_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w), options->rate_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE); -} - -static ConvolveOptions * -convolve_options_new (void) -{ - ConvolveOptions *options; - - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *scale; - GtkWidget *frame; - - /* the new convolve tool options structure */ - options = g_new (ConvolveOptions, 1); - paint_options_init ((PaintOptions *) options, - CONVOLVE, - convolve_options_reset); - options->type = options->type_d = DEFAULT_CONVOLVE_TYPE; - options->rate = options->rate_d = DEFAULT_CONVOLVE_RATE; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* the rate scale */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Rate:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - options->rate_w = - gtk_adjustment_new (options->rate_d, 0.0, 100.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w)); - gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->rate); - gtk_widget_show (scale); - gtk_widget_show (hbox); - - frame = gimp_radio_group_new2 (TRUE, _("Convolve Type"), - gimp_radio_button_update, - &options->type, (gpointer) options->type, - - _("Blur"), (gpointer) BLUR_CONVOLVE, - &options->type_w[0], - _("Sharpen"), (gpointer) SHARPEN_CONVOLVE, - &options->type_w[1], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -static gpointer -convolve_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - switch (state) - { - case MOTION_PAINT: - convolve_motion (paint_core, drawable, - convolve_options->paint_options.pressure_options, - convolve_options->type, convolve_options->rate); - break; - - default: - break; - } - - return NULL; -} - -static void -convolve_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: - case GDK_Alt_R: - break; - case GDK_Shift_L: - case GDK_Shift_R: - if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */ - { - switch (convolve_options->type) - { - case BLUR_CONVOLVE: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (convolve_options->type_w[SHARPEN_CONVOLVE]), - TRUE); - break; - case SHARPEN_CONVOLVE: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (convolve_options->type_w[BLUR_CONVOLVE]), - TRUE); - break; - default: - break; - } - } - break; - case GDK_Control_L: - case GDK_Control_R: - if ( !(kevent->state & GDK_SHIFT_MASK) ) /* shift enables line draw mode */ - { - switch (convolve_options->type) - { - case BLUR_CONVOLVE: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (convolve_options->type_w[SHARPEN_CONVOLVE]), - TRUE); - break; - case SHARPEN_CONVOLVE: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (convolve_options->type_w[BLUR_CONVOLVE]), - TRUE); - break; - default: - break; - } - } - break; - } - - tool->toggled = (convolve_options->type == SHARPEN_CONVOLVE); -} - -static void -convolve_cursor_update_func (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - tool->toggled = (convolve_options->type == SHARPEN_CONVOLVE); - - paint_core_cursor_update (tool, mevent, gdisp); -} - -Tool * -tools_new_convolve (void) -{ - Tool *tool; - PaintCore *private; - - /* The tool options */ - if (! convolve_options) - { - convolve_options = convolve_options_new (); - tools_register (CONVOLVE, (ToolOptions *) convolve_options); - - /* press all default buttons */ - convolve_options_reset (); - } - - tool = paint_core_new (CONVOLVE); - tool->modifier_key_func = convolve_modifier_key_func; - tool->cursor_update_func = convolve_cursor_update_func; - - private = (PaintCore *) tool->private; - private->paint_func = convolve_paint_func; - - return tool; -} - -void -tools_free_convolve (Tool *tool) -{ - paint_core_free (tool); -} - -static void -convolve_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - ConvolveType type, - double rate) -{ - TempBuf *area; - guchar *temp_data; - PixelRegion srcPR; - PixelRegion destPR; - gdouble scale; - ConvolveClipType area_hclip = CONVOLVE_NOT_CLIPPED; - ConvolveClipType area_vclip = CONVOLVE_NOT_CLIPPED; - gint marginx = 0; - gint marginy = 0; - - if (! gimp_drawable_gimage (drawable)) - return; - - /* If the image type is indexed, don't convolve */ - if (gimp_drawable_is_indexed (drawable)) - return; - - /* If the brush is smaller than the convolution matrix, don't convolve */ - - if ((paint_core->brush->mask->width < matrix_size) || - (paint_core->brush->mask->height < matrix_size)) - return; - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - /* Get image region around current brush (mask bbox + 1 pixel) */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - /* configure the source pixel region */ - pixel_region_init (&srcPR, gimp_drawable_data (drawable), - area->x, area->y, area->width, area->height, FALSE); - - /* Configure the destination pixel region - a paint_core TempBuf */ - - destPR.bytes = area->bytes; - destPR.tiles = NULL; - destPR.x = 0; - destPR.y = 0; - destPR.w = area->width; - destPR.h = area->height; - destPR.rowstride = area->width * destPR.bytes; - destPR.data = temp_buf_data (area); - - if (pressure_options->rate) - rate = rate * 2.0 * paint_core->curpressure; - - calculate_matrix (type, rate); - - /* Image region near edges? If so, paint area will be clipped */ - /* with respect to brush mask + 1 pixel border (# 19285) */ - - if((marginx = (gint)paint_core->curx - paint_core->brush->mask->width/2 - 1) != area->x) - area_hclip = CONVOLVE_NCLIP; - else - if((marginx = area->width - paint_core->brush->mask->width - 2) != 0) - area_hclip = CONVOLVE_PCLIP; - - if((marginy = (gint)paint_core->cury - paint_core->brush->mask->height/2 - 1) != area->y) - area_vclip = CONVOLVE_NCLIP; - else - if((marginy = area->height - paint_core->brush->mask->height - 2) != 0) - area_vclip = CONVOLVE_PCLIP; - - /* Has the TempBuf been clipped by a canvas edge or two ? */ - if((area_hclip == CONVOLVE_NOT_CLIPPED) && (area_vclip == CONVOLVE_NOT_CLIPPED)) - { - /* No clipping... */ - /* Standard case: copy src to temp. convolve temp to dest. */ - /* Brush defines pipe size and no edge adjustments are needed. */ - - /* If the source has no alpha, then add alpha pixels */ - /* Because paint_core.c is alpha-only code. See below. */ - - PixelRegion tempPR; - - tempPR.x = 0; - tempPR.y = 0; - tempPR.w = area->width; - tempPR.h = area->height; - tempPR.tiles = NULL; - - if (! gimp_drawable_has_alpha (drawable)) - { - /* note: this particular approach needlessly convolves the totally- - opaque alpha channel. A faster approach would be to keep - tempPR the same number of bytes as srcPR, and extend the - paint_core_replace_canvas API to handle non-alpha images. */ - - tempPR.bytes = srcPR.bytes + 1; - tempPR.rowstride = tempPR.bytes * tempPR.w; - temp_data = g_malloc (tempPR.h * tempPR.rowstride); - tempPR.data = temp_data; - add_alpha_region (&srcPR, &tempPR); - } - else - { - tempPR.bytes = srcPR.bytes; - tempPR.rowstride = tempPR.bytes * tempPR.w; - temp_data = g_malloc (tempPR.h * tempPR.rowstride); - tempPR.data = temp_data; - copy_region (&srcPR, &tempPR); - } - - /* Convolve the region */ - - tempPR.x = 0; - tempPR.y = 0; - tempPR.w = area->width; - tempPR.h = area->height; - tempPR.data = temp_data; - convolve_region (&tempPR, &destPR, matrix, matrix_size, - matrix_divisor, NORMAL_CONVOL); - - /* Free the allocated temp space */ - g_free (temp_data); - } - else - { - /* TempBuf clipping has occured on at least one edge... */ - /* Edge case: expand area under brush margin px on near edge(s), convolve */ - /* expanded buffers. copy src -> ovrsz1 convolve ovrsz1 -> ovrsz2 */ - /* copy-with-crop ovrsz2 -> dest */ - - PixelRegion ovrsz1PR; - PixelRegion ovrsz2PR; - guchar *ovrsz1_data = NULL; - guchar *ovrsz2_data = NULL; - guchar *fillcolor = gimp_drawable_get_color_at (drawable, - CLAMP ((gint) paint_core->curx, 0, gimp_drawable_width (drawable) - 1), - CLAMP ((gint) paint_core->cury, 0, gimp_drawable_height (drawable) - 1)); - - marginx *= (marginx < 0) ? -1 : 0; - marginy *= (marginy < 0) ? -1 : 0; - - ovrsz2PR.x = 0; - ovrsz2PR.y = 0; - ovrsz2PR.w = area->width + marginx; - ovrsz2PR.h = area->height + marginy; - ovrsz2PR.bytes = (gimp_drawable_has_alpha (drawable))? srcPR.bytes : srcPR.bytes + 1; - ovrsz2PR.offx = 0; - ovrsz2PR.offy = 0; - ovrsz2PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w; - ovrsz2PR.tiles = NULL; - ovrsz2_data = g_malloc (ovrsz2PR.h * ovrsz2PR.rowstride); - ovrsz2PR.data = ovrsz2_data; - - ovrsz1PR.x = 0; - ovrsz1PR.y = 0; - ovrsz1PR.w = area->width + marginx; - ovrsz1PR.h = area->height + marginy; - ovrsz1PR.bytes = (gimp_drawable_has_alpha (drawable))? srcPR.bytes : srcPR.bytes + 1; - ovrsz1PR.offx = 0; - ovrsz1PR.offy = 0; - ovrsz1PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w; - ovrsz1PR.tiles = NULL; - ovrsz1_data = g_malloc (ovrsz1PR.h * ovrsz1PR.rowstride); - ovrsz1PR.data = ovrsz1_data; - color_region (&ovrsz1PR, (const guchar *)fillcolor); - - ovrsz1PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0; - ovrsz1PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0; - ovrsz1PR.w = area->width; - ovrsz1PR.h = area->height; - ovrsz1PR.data = ovrsz1_data + (ovrsz1PR.rowstride * ovrsz1PR.y) + (ovrsz1PR.bytes * ovrsz1PR.x); - - if (! gimp_drawable_has_alpha (drawable)) - add_alpha_region (&srcPR, &ovrsz1PR); - else - copy_region (&srcPR, &ovrsz1PR); - - /* Convolve the region */ - - ovrsz1PR.x = 0; - ovrsz1PR.y = 0; - ovrsz1PR.w = area->width + marginx; - ovrsz1PR.h = area->height + marginy; - ovrsz1PR.data = ovrsz1_data; - convolve_region (&ovrsz1PR, &ovrsz2PR, matrix, matrix_size, - matrix_divisor, NORMAL_CONVOL); - - /* Crop and copy to destination */ - - ovrsz2PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0; - ovrsz2PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0; - ovrsz2PR.w = area->width; - ovrsz2PR.h = area->height; - ovrsz2PR.data = ovrsz2_data + (ovrsz2PR.rowstride * ovrsz2PR.y) + (ovrsz2PR.bytes * ovrsz2PR.x); - copy_region (&ovrsz2PR, &destPR); - g_free(ovrsz1_data); - g_free(ovrsz2_data); - g_free(fillcolor); - } - - /* paste the newly painted canvas to the gimage which is being worked on */ - paint_core_replace_canvas (paint_core, drawable, OPAQUE_OPACITY, - (int) (gimp_context_get_opacity (NULL) * 255), - pressure_options->pressure ? PRESSURE : SOFT, - scale, INCREMENTAL); -} - -static void -calculate_matrix (ConvolveType type, - double rate) -{ - float percent; - - /* find percent of tool pressure */ - percent = MIN (rate / 100.0, 1.0); - - /* get the appropriate convolution matrix and size and divisor */ - switch (type) - { - case BLUR_CONVOLVE: - matrix_size = 5; - blur_matrix [12] = MIN_BLUR + percent * (MAX_BLUR - MIN_BLUR); - copy_matrix (blur_matrix, custom_matrix, matrix_size); - break; - - case SHARPEN_CONVOLVE: - matrix_size = 5; - sharpen_matrix [12] = MIN_SHARPEN + percent * (MAX_SHARPEN - MIN_SHARPEN); - copy_matrix (sharpen_matrix, custom_matrix, matrix_size); - break; - - case CUSTOM_CONVOLVE: - matrix_size = 5; - break; - } - - integer_matrix (custom_matrix, matrix, matrix_size); - matrix_divisor = sum_matrix (matrix, matrix_size); - - if (!matrix_divisor) - matrix_divisor = 1; -} - -static void -integer_matrix (gfloat *source, - gint *dest, - gint size) -{ - gint i; - -#define PRECISION 10000 - - for (i = 0; i < size*size; i++) - *dest++ = (gint) (*source ++ * PRECISION); -} - -static void -copy_matrix (gfloat *src, - gfloat *dest, - gint size) -{ - gint i; - - for (i = 0; i < size*size; i++) - *dest++ = *src++; -} - -static int -sum_matrix (gint *matrix, - gint size) -{ - gint sum = 0; - - size *= size; - - while (size --) - sum += *matrix++; - - return sum; -} - - -static gpointer -convolve_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - convolve_motion (paint_core, drawable, &non_gui_pressure_options, - non_gui_type, non_gui_rate); - - return NULL; -} - -gboolean -convolve_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array) -{ - gdouble rate = DEFAULT_CONVOLVE_RATE; - ConvolveType type = DEFAULT_CONVOLVE_TYPE; - ConvolveOptions *options = convolve_options; - - if (options) - { - rate = options->rate; - type = options->type; - } - - return convolve_non_gui (drawable, rate, type, num_strokes, stroke_array); -} - -gboolean -convolve_non_gui (GimpDrawable *drawable, - double rate, - ConvolveType type, - gint num_strokes, - gdouble *stroke_array) -{ - gint i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = convolve_non_gui_paint_func; - - non_gui_type = type; - non_gui_rate = rate; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - convolve_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - return TRUE; - } - - return FALSE; -} diff --git a/app/convolve.h b/app/convolve.h deleted file mode 100644 index 1e07c92d36..0000000000 --- a/app/convolve.h +++ /dev/null @@ -1,44 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __CONVOLVE_H__ -#define __CONVOLVE_H__ - - -typedef enum -{ - BLUR_CONVOLVE, - SHARPEN_CONVOLVE, - CUSTOM_CONVOLVE -} ConvolveType; - - -gboolean convolve_non_gui (GimpDrawable *drawable, - gdouble rate, - ConvolveType type, - gint num_strokes, - gdouble *stroke_array); -gboolean convolve_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array); - -Tool * tools_new_convolve (void); -void tools_free_convolve (Tool *tool); - - -#endif /* __CONVOLVE_H__ */ diff --git a/app/core/gimp-edit.c b/app/core/gimp-edit.c index 5a770b28de..7b49b80888 100644 --- a/app/core/gimp-edit.c +++ b/app/core/gimp-edit.c @@ -38,9 +38,10 @@ #include "paint_funcs.h" #include "pixel_region.h" #include "tile_manager.h" -#include "tools.h" #include "undo.h" +#include "tools/tools.h" + #include "libgimp/gimpintl.h" #include "tile_manager_pvt.h" diff --git a/app/core/gimpbrush-load.c b/app/core/gimpbrush-load.c index b0878d201b..15ab618adc 100644 --- a/app/core/gimpbrush-load.c +++ b/app/core/gimpbrush-load.c @@ -50,9 +50,11 @@ #include "gimprc.h" #include "patterns.h" #include "pattern_header.h" -#include "paint_core.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpintl.h" diff --git a/app/core/gimpbrush.c b/app/core/gimpbrush.c index b0878d201b..15ab618adc 100644 --- a/app/core/gimpbrush.c +++ b/app/core/gimpbrush.c @@ -50,9 +50,11 @@ #include "gimprc.h" #include "patterns.h" #include "pattern_header.h" -#include "paint_core.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpintl.h" diff --git a/app/core/gimpbrushgenerated-load.c b/app/core/gimpbrushgenerated-load.c index b58855cebb..649018e539 100644 --- a/app/core/gimpbrushgenerated-load.c +++ b/app/core/gimpbrushgenerated-load.c @@ -33,11 +33,13 @@ #include "appenv.h" #include "gimpbrushgenerated.h" -#include "paint_core.h" #include "gimprc.h" #include "gimpbrush.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" diff --git a/app/core/gimpbrushgenerated-save.c b/app/core/gimpbrushgenerated-save.c index b58855cebb..649018e539 100644 --- a/app/core/gimpbrushgenerated-save.c +++ b/app/core/gimpbrushgenerated-save.c @@ -33,11 +33,13 @@ #include "appenv.h" #include "gimpbrushgenerated.h" -#include "paint_core.h" #include "gimprc.h" #include "gimpbrush.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" diff --git a/app/core/gimpbrushgenerated.c b/app/core/gimpbrushgenerated.c index b58855cebb..649018e539 100644 --- a/app/core/gimpbrushgenerated.c +++ b/app/core/gimpbrushgenerated.c @@ -33,11 +33,13 @@ #include "appenv.h" #include "gimpbrushgenerated.h" -#include "paint_core.h" #include "gimprc.h" #include "gimpbrush.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" diff --git a/app/core/gimpbrushpipe-load.c b/app/core/gimpbrushpipe-load.c index 1eea53e299..1467025d56 100644 --- a/app/core/gimpbrushpipe-load.c +++ b/app/core/gimpbrushpipe-load.c @@ -48,9 +48,11 @@ #include "patterns.h" #include "gimpbrush.h" #include "gimpbrushpipe.h" -#include "paint_core.h" #include "gimprc.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpparasiteio.h" diff --git a/app/core/gimpbrushpipe.c b/app/core/gimpbrushpipe.c index 1eea53e299..1467025d56 100644 --- a/app/core/gimpbrushpipe.c +++ b/app/core/gimpbrushpipe.c @@ -48,9 +48,11 @@ #include "patterns.h" #include "gimpbrush.h" #include "gimpbrushpipe.h" -#include "paint_core.h" #include "gimprc.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpparasiteio.h" diff --git a/app/core/gimpedit.c b/app/core/gimpedit.c index 5a770b28de..7b49b80888 100644 --- a/app/core/gimpedit.c +++ b/app/core/gimpedit.c @@ -38,9 +38,10 @@ #include "paint_funcs.h" #include "pixel_region.h" #include "tile_manager.h" -#include "tools.h" #include "undo.h" +#include "tools/tools.h" + #include "libgimp/gimpintl.h" #include "tile_manager_pvt.h" diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c index 7d29b2adbc..b5d85d628e 100644 --- a/app/core/gimpimage-convert.c +++ b/app/core/gimpimage-convert.c @@ -94,30 +94,31 @@ #include "apptypes.h" #include "appenv.h" -#include "brightness_contrast.h" -#include "color_balance.h" #include "convert.h" #include "cursorutil.h" -#include "curves.h" #include "drawable.h" #include "floating_sel.h" #include "fsdither.h" #include "gdisplay.h" #include "gimpimage.h" #include "gimpui.h" -#include "hue_saturation.h" #include "layer.h" -#include "levels.h" #include "undo.h" #include "palette.h" #include "gimppalette.h" #include "palette_select.h" #include "pixel_region.h" -#include "posterize.h" -#include "threshold.h" #include "tile_manager.h" #include "tile_manager_pvt.h" /* ick ick ick. */ +#include "tools/brightness_contrast.h" +#include "tools/color_balance.h" +#include "tools/curves.h" +#include "tools/hue_saturation.h" +#include "tools/levels.h" +#include "tools/posterize.h" +#include "tools/threshold.h" + #include "libgimp/gimpcolorspace.h" #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/core/gimpimage-mask.c b/app/core/gimpimage-mask.c index 0237af2cb1..e716b75e99 100644 --- a/app/core/gimpimage-mask.c +++ b/app/core/gimpimage-mask.c @@ -31,14 +31,16 @@ #include "gimage_mask.h" #include "gimprc.h" #include "layer.h" -#include "paint_core.h" #include "paint_funcs.h" -#include "paint_options.h" #include "pixel_region.h" #include "tile_manager.h" #include "tile_manager_pvt.h" #include "undo.h" +#include "tools/paint_core.h" +#include "tools/paint_options.h" +#include "tools/tools.h" + #include "pdb/procedural_db.h" #include "libgimp/gimpintl.h" diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index 2a356a4f87..6a8d757166 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -26,7 +26,6 @@ #include "apptypes.h" #include "appenv.h" -#include "by_color_select.h" #include "channel.h" #include "draw_core.h" #include "drawable.h" @@ -38,7 +37,6 @@ #include "gimpparasite.h" #include "gimprc.h" #include "layer.h" -#include "paint_core.h" #include "paint_funcs.h" #include "parasitelist.h" #include "path_transform.h" @@ -46,10 +44,13 @@ #include "tile_manager.h" #include "tile_manager_pvt.h" #include "tile.h" -#include "tools.h" -#include "transform_core.h" #include "undo.h" +#include "tools/by_color_select.h" +#include "tools/paint_core.h" +#include "tools/tools.h" +#include "tools/transform_core.h" + #include "libgimp/gimpparasite.h" #include "libgimp/gimpintl.h" diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c index 0cc5dca17d..651d77360d 100644 --- a/app/core/gimpprojection.c +++ b/app/core/gimpprojection.c @@ -51,7 +51,6 @@ #include "scale.h" #include "scroll.h" #include "selection.h" -#include "tools.h" #include "undo.h" @@ -59,7 +58,8 @@ #include "gdisplay_color.h" #endif /* DISPLAY_FILTERS */ -#include "bezier_selectP.h" +#include "tools/bezier_selectP.h" +#include "tools/tools.h" #include "libgimp/gimpmath.h" diff --git a/app/crop.c b/app/crop.c deleted file mode 100644 index 76c62c4764..0000000000 --- a/app/crop.c +++ /dev/null @@ -1,1598 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "channel.h" -#include "crop.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "drawable.h" -#include "floating_sel.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimage_mask.h" -#include "gimphelp.h" -#include "gimpui.h" -#include "info_dialog.h" -#include "layer.h" -#include "pixel_region.h" -#include "tools.h" -#include "tool_options.h" -#include "undo.h" - -#include "libgimp/gimpsizeentry.h" -#include "libgimp/gimpmath.h" -#include "libgimp/gimpintl.h" - - -#define STATUSBAR_SIZE 128 - -/* possible crop functions */ -#define CREATING 0 -#define MOVING 1 -#define RESIZING_LEFT 2 -#define RESIZING_RIGHT 3 -#define CROPPING 4 - -/* speed of key movement */ -#define ARROW_VELOCITY 25 - -/* the crop structures */ - -typedef struct _Crop Crop; - -struct _Crop -{ - DrawCore *core; /* Core select object */ - - gint startx; /* starting x coord */ - gint starty; /* starting y coord */ - - gint lastx; /* previous x coord */ - gint lasty; /* previous y coord */ - - gint x1, y1; /* upper left hand coordinate */ - gint x2, y2; /* lower right hand coords */ - - gint srw, srh; /* width and height of corners */ - - gint tx1, ty1; /* transformed coords */ - gint tx2, ty2; /* */ - - gint function; /* moving or resizing */ - guint context_id; /* for the statusbar */ -}; - -typedef struct _CropOptions CropOptions; - -struct _CropOptions -{ - ToolOptions tool_options; - - gboolean layer_only; - gboolean layer_only_d; - GtkWidget *layer_only_w; - - gboolean allow_enlarge; - gboolean allow_enlarge_d; - GtkWidget *allow_enlarge_w; - - CropType type; - CropType type_d; - GtkWidget *type_w[2]; -}; - - -/* the crop tool options */ -static CropOptions *crop_options = NULL; - -/* the crop tool info dialog */ -static InfoDialog *crop_info = NULL; - -static gdouble orig_vals[2]; -static gdouble size_vals[2]; - -static GtkWidget *origin_sizeentry; -static GtkWidget *size_sizeentry; - - -/* Crop type functions */ -static void crop_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void crop_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void crop_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void crop_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void crop_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); -static void crop_arrow_keys_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -static void crop_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); - -/* Crop helper functions */ -static void crop_recalc (Tool *tool, - Crop *crop); -static void crop_start (Tool *tool, - Crop *crop); -static void crop_adjust_guides (GImage *gimage, - gint x1, - gint y1, - gint x2, - gint y2); - -/* Crop dialog functions */ -static void crop_info_update (Tool *tool); -static void crop_info_create (Tool *tool); -static void crop_crop_callback (GtkWidget *widget, - gpointer data); -static void crop_resize_callback (GtkWidget *widget, - gpointer data); -static void crop_close_callback (GtkWidget *widget, - gpointer data); - - -/* Crop area-select functions */ -typedef enum -{ - AUTO_CROP_NOTHING = 0, - AUTO_CROP_ALPHA = 1, - AUTO_CROP_COLOR = 2 -} AutoCropType; - - -typedef guchar * (* GetColorFunc) (GtkObject *, - gint , - gint ); -typedef AutoCropType (* ColorsEqualFunc) (guchar *, - guchar *, - gint ); - -static void crop_selection_callback (GtkWidget *widget, - gpointer data); -static void crop_automatic_callback (GtkWidget *widget, - gpointer data); -static AutoCropType crop_guess_bgcolor (GtkObject *, - GetColorFunc, - gint , - gint , - guchar *, - gint , - gint , - gint , - gint ); -static gint crop_colors_equal (guchar *, - guchar *, - gint ); -static gint crop_colors_alpha (guchar *, - guchar *, - gint ); - - -/* Crop dialog callback funtions */ -static void crop_orig_changed (GtkWidget *widget, - gpointer data); -static void crop_size_changed (GtkWidget *widget, - gpointer data); - - -/* Functions */ - -static void -crop_options_reset (void) -{ - CropOptions *options = crop_options; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->layer_only_w), - options->layer_only_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(options->allow_enlarge_w), - options->allow_enlarge_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE); -} - -static CropOptions * -crop_options_new (void) -{ - CropOptions *options; - GtkWidget *vbox; - GtkWidget *frame; - - /* the new crop tool options structure */ - options = g_new (CropOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Crop & Resize"), - crop_options_reset); - options->layer_only = options->layer_only_d = FALSE; - options->allow_enlarge = options->allow_enlarge_d = FALSE; - options->type = options->type_d = CROP_CROP; - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* layer toggle */ - options->layer_only_w = - gtk_check_button_new_with_label(_("Current Layer only")); - gtk_box_pack_start (GTK_BOX (vbox), options->layer_only_w, - FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->layer_only_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->layer_only); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->layer_only_w), - options->layer_only_d); - gtk_widget_show (options->layer_only_w); - - /* enlarge toggle */ - options->allow_enlarge_w = gtk_check_button_new_with_label (_("Allow Enlarging")); - gtk_box_pack_start (GTK_BOX (vbox), options->allow_enlarge_w, - FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->allow_enlarge_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->allow_enlarge); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->allow_enlarge_w), - options->allow_enlarge_d); - gtk_widget_show (options->allow_enlarge_w); - - /* tool toggle */ - frame = gimp_radio_group_new2 (TRUE, _("Tool Toggle"), - gimp_radio_button_update, - &options->type, (gpointer) options->type, - - _("Crop"), (gpointer) CROP_CROP, - &options->type_w[0], - _("Resize"), (gpointer) RESIZE_CROP, - &options->type_w[1], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -static void -crop_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - Crop *crop; - - crop = (Crop *) tool->private; - - if (tool->state == INACTIVE || - gdisp != tool->gdisp) - { - crop->function = CREATING; - } - else - { - /* If the cursor is in either the upper left or lower right boxes, - The new function will be to resize the current crop area */ - if (bevent->x == CLAMP (bevent->x, crop->x1, crop->x1 + crop->srw) && - bevent->y == CLAMP (bevent->y, crop->y1, crop->y1 + crop->srh)) - crop->function = RESIZING_LEFT; - else if (bevent->x == CLAMP (bevent->x, crop->x2 - crop->srw, crop->x2) && - bevent->y == CLAMP (bevent->y, crop->y2 - crop->srh, crop->y2)) - crop->function = RESIZING_RIGHT; - - /* If the cursor is in either the upper right or lower left boxes, - The new function will be to translate the current crop area */ - else if ((bevent->x == CLAMP (bevent->x, - crop->x1, crop->x1 + crop->srw) && - bevent->y == CLAMP (bevent->y, - crop->y2 - crop->srh, crop->y2)) || - (bevent->x == CLAMP (bevent->x, - crop->x2 - crop->srw, crop->x2) && - bevent->y == CLAMP (bevent->y, - crop->y1, crop->y1 + crop->srh))) - crop->function = MOVING; - - /* If the pointer is in the rectangular region, crop or resize it! */ - else if (bevent->x > crop->x1 && bevent->x < crop->x2 && - bevent->y > crop->y1 && bevent->y < crop->y2) - crop->function = CROPPING; - /* otherwise, the new function will be creating, since we want to start anew */ - else - crop->function = CREATING; - } - - if (crop->function == CREATING) - { - if (tool->state == ACTIVE) - draw_core_stop (crop->core, tool); - - tool->gdisp = gdisp; - tool->drawable = gimp_image_active_drawable (gdisp->gimage); - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &crop->tx1, &crop->ty1, TRUE, FALSE); - crop->tx2 = crop->tx1; - crop->ty2 = crop->ty1; - - crop_start (tool, crop); - } - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &crop->startx, &crop->starty, TRUE, FALSE); - crop->lastx = crop->startx; - crop->lasty = crop->starty; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; -} - -static void -crop_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - Crop *crop; - - crop = (Crop *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), crop->context_id); - - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - if (crop->function == CROPPING) - { - if (crop_options->type == CROP_CROP) - crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2, - crop_options->layer_only, TRUE); - else - crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2, - crop_options->layer_only, FALSE); - - /* Finish the tool */ - crop_close_callback (NULL, NULL); - } - else - crop_info_update (tool); - } -} - -static void -crop_adjust_guides (GImage *gimage, - gint x1, - gint y1, - gint x2, - gint y2) - -{ - GList *glist; - Guide *guide; - gboolean remove_guide; - - for (glist = gimage->guides; glist; glist = g_list_next (glist)) - { - guide = (Guide *) glist->data; - remove_guide = FALSE; - - switch (guide->orientation) - { - case ORIENTATION_HORIZONTAL: - if ((guide->position < y1) || (guide->position > y2)) - remove_guide = TRUE; - break; - - case ORIENTATION_VERTICAL: - if ((guide->position < x1) || (guide->position > x2)) - remove_guide = TRUE; - break; - - default: - break; - } - - /* edit the guide */ - gdisplays_expose_guide (gimage, guide); - gdisplays_flush(); - - if (remove_guide) - { - guide->position = -1; - guide = NULL; - } - else - { - if (guide->orientation == ORIENTATION_HORIZONTAL) - { - guide->position -= y1 ; - } - else - { - guide->position -= x1; - } - } - } -} - -static void -crop_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Crop *crop; - Layer *layer; - gint x1, y1, x2, y2; - gint curx, cury; - gint inc_x, inc_y; - gchar size[STATUSBAR_SIZE]; - gint min_x, min_y, max_x, max_y; - - crop = (Crop *) tool->private; - - /* This is the only case when the motion events should be ignored-- - we're just waiting for the button release event to crop the image */ - if (crop->function == CROPPING) - return; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE); - x1 = crop->startx; - y1 = crop->starty; - x2 = curx; - y2 = cury; - - inc_x = (x2 - x1); - inc_y = (y2 - y1); - - /* If there have been no changes... return */ - if (crop->lastx == curx && crop->lasty == cury) - return; - - draw_core_pause (crop->core, tool); - - if (crop_options->layer_only) - { - layer = (gdisp->gimage)->active_layer; - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &min_x, &min_y); - max_x = gimp_drawable_width (GIMP_DRAWABLE (layer)) + min_x; - max_y = gimp_drawable_height (GIMP_DRAWABLE (layer)) + min_y; - } - else - { - min_x = min_y = 0; - max_x = gdisp->gimage->width; - max_y = gdisp->gimage->height; - } - - switch (crop->function) - { - case CREATING : - if (!crop_options->allow_enlarge) - { - x1 = CLAMP (x1, min_x, max_x); - y1 = CLAMP (y1, min_y, max_y); - x2 = CLAMP (x2, min_x, max_x); - y2 = CLAMP (y2, min_y, max_y); - } - break; - - case RESIZING_LEFT : - x1 = crop->tx1 + inc_x; - y1 = crop->ty1 + inc_y; - if (!crop_options->allow_enlarge) - { - x1 = CLAMP (x1, min_x, max_x); - y1 = CLAMP (y1, min_y, max_y); - } - x2 = MAX (x1, crop->tx2); - y2 = MAX (y1, crop->ty2); - crop->startx = curx; - crop->starty = cury; - break; - - case RESIZING_RIGHT : - x2 = crop->tx2 + inc_x; - y2 = crop->ty2 + inc_y; - if (!crop_options->allow_enlarge) - { - x2 = CLAMP (x2, min_x, max_x); - y2 = CLAMP (y2, min_y, max_y); - } - x1 = MIN (crop->tx1, x2); - y1 = MIN (crop->ty1, y2); - crop->startx = curx; - crop->starty = cury; - break; - - case MOVING : - if (!crop_options->allow_enlarge) - { - inc_x = CLAMP (inc_x, min_x - crop->tx1, max_x - crop->tx2); - inc_y = CLAMP (inc_y, min_y - crop->ty1, max_y - crop->ty2); - } - x1 = crop->tx1 + inc_x; - x2 = crop->tx2 + inc_x; - y1 = crop->ty1 + inc_y; - y2 = crop->ty2 + inc_y; - crop->startx = curx; - crop->starty = cury; - break; - } - - /* make sure that the coords are in bounds */ - crop->tx1 = MIN (x1, x2); - crop->ty1 = MIN (y1, y2); - crop->tx2 = MAX (x1, x2); - crop->ty2 = MAX (y1, y2); - - crop->lastx = curx; - crop->lasty = cury; - - /* recalculate the coordinates for crop_draw based on the new values */ - crop_recalc (tool, crop); - - if (crop->function == CREATING || - crop->function == RESIZING_LEFT || crop->function == RESIZING_RIGHT) - { - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), crop->context_id); - if (gdisp->dot_for_dot) - { - g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str, - _("Crop: "), - (crop->tx2 - crop->tx1), " x ", (crop->ty2 - crop->ty1)); - } - else /* show real world units */ - { - gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit); - - g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str, - _("Crop: "), - (gdouble) (crop->tx2 - crop->tx1) * unit_factor / - gdisp->gimage->xresolution, - " x ", - (gdouble) (crop->ty2 - crop->ty1) * unit_factor / - gdisp->gimage->yresolution); - } - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), crop->context_id, - size); - } - - draw_core_resume (crop->core, tool); -} - -static void -crop_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Crop *crop; - - GdkCursorType ctype = GIMP_MOUSE_CURSOR; - CursorModifier cmodifier = CURSOR_MODIFIER_NONE; - - crop = (Crop *) tool->private; - - if (tool->state == INACTIVE || - (tool->state == ACTIVE && tool->gdisp != gdisp)) - { - ctype = GIMP_CROSSHAIR_SMALL_CURSOR; - } - else if (mevent->x == CLAMP (mevent->x, crop->x1, crop->x1 + crop->srw) && - mevent->y == CLAMP (mevent->y, crop->y1, crop->y1 + crop->srh)) - { - cmodifier = CURSOR_MODIFIER_RESIZE; - } - else if (mevent->x == CLAMP (mevent->x, crop->x2 - crop->srw, crop->x2) && - mevent->y == CLAMP (mevent->y, crop->y2 - crop->srh, crop->y2)) - { - cmodifier = CURSOR_MODIFIER_RESIZE; - } - else if (mevent->x == CLAMP (mevent->x, crop->x1, crop->x1 + crop->srw) && - mevent->y == CLAMP (mevent->y, crop->y2 - crop->srh, crop->y2)) - { - cmodifier = CURSOR_MODIFIER_MOVE; - } - else if (mevent->x == CLAMP (mevent->x, crop->x2 - crop->srw, crop->x2) && - mevent->y == CLAMP (mevent->y, crop->y1, crop->y1 + crop->srh)) - { - cmodifier = CURSOR_MODIFIER_MOVE; - } - else if (! (mevent->x > crop->x1 && mevent->x < crop->x2 && - mevent->y > crop->y1 && mevent->y < crop->y2)) - { - ctype = GIMP_CROSSHAIR_SMALL_CURSOR; - } - - gdisplay_install_tool_cursor (gdisp, ctype, - CROP, - cmodifier, - crop_options->type != CROP_CROP); -} - -static void -crop_arrow_keys_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - Layer *layer; - Crop *crop; - gint inc_x, inc_y; - gint min_x, min_y; - gint max_x, max_y; - - if (tool->state == ACTIVE) - { - crop = (Crop *) tool->private; - inc_x = inc_y = 0; - - switch (kevent->keyval) - { - case GDK_Up : inc_y = -1; break; - case GDK_Left : inc_x = -1; break; - case GDK_Right : inc_x = 1; break; - case GDK_Down : inc_y = 1; break; - } - - /* If the shift key is down, move by an accelerated increment */ - if (kevent->state & GDK_SHIFT_MASK) - { - inc_y *= ARROW_VELOCITY; - inc_x *= ARROW_VELOCITY; - } - - draw_core_pause (crop->core, tool); - - if (crop_options->layer_only) - { - layer = (gdisp->gimage)->active_layer; - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &min_x, &min_y); - max_x = gimp_drawable_width (GIMP_DRAWABLE (layer)) + min_x; - max_y = gimp_drawable_height (GIMP_DRAWABLE (layer)) + min_y; - } - else - { - min_x = min_y = 0; - max_x = gdisp->gimage->width; - max_y = gdisp->gimage->height; - } - - if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */ - { - crop->tx2 = crop->tx2 + inc_x; - crop->ty2 = crop->ty2 + inc_y; - if (!crop_options->allow_enlarge) - { - crop->tx2 = CLAMP (crop->tx2, min_x, max_x); - crop->ty2 = CLAMP (crop->ty2, min_y, max_y); - } - crop->tx1 = MIN (crop->tx1, crop->tx2); - crop->ty1 = MIN (crop->ty1, crop->ty2); - } - else - { - if (!crop_options->allow_enlarge) - { - inc_x = CLAMP (inc_x, - -crop->tx1, gdisp->gimage->width - crop->tx2); - inc_y = CLAMP (inc_y, - -crop->ty1, gdisp->gimage->height - crop->ty2); - } - crop->tx1 += inc_x; - crop->tx2 += inc_x; - crop->ty1 += inc_y; - crop->ty2 += inc_y; - } - - crop_recalc (tool, crop); - draw_core_resume (crop->core, tool); - } -} - -static void -crop_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: case GDK_Alt_R: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (crop_options->allow_enlarge_w), - !crop_options->allow_enlarge); - break; - case GDK_Shift_L: case GDK_Shift_R: - break; - case GDK_Control_L: case GDK_Control_R: - if (crop_options->type == CROP_CROP) - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (crop_options->type_w[RESIZE_CROP]), TRUE); - else - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (crop_options->type_w[CROP_CROP]), TRUE); - break; - } -} - -static void -crop_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - Crop *crop; - - crop = (Crop *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (crop->core, tool); - break; - - case RESUME: - crop_recalc (tool, crop); - draw_core_resume (crop->core, tool); - break; - - case HALT: - crop_close_callback (NULL, NULL); - break; - - default: - break; - } -} - -void -crop_draw (Tool *tool) -{ - Crop *crop; - - crop = (Crop *) tool->private; - -#define SRW 10 -#define SRH 10 - - gdk_draw_line (crop->core->win, crop->core->gc, - crop->x1, crop->y1, tool->gdisp->disp_width, crop->y1); - gdk_draw_line (crop->core->win, crop->core->gc, - crop->x1, crop->y1, crop->x1, tool->gdisp->disp_height); - gdk_draw_line (crop->core->win, crop->core->gc, - crop->x2, crop->y2, 0, crop->y2); - gdk_draw_line (crop->core->win, crop->core->gc, - crop->x2, crop->y2, crop->x2, 0); - - crop->srw = ((crop->x2 - crop->x1) < SRW) ? (crop->x2 - crop->x1) : SRW; - crop->srh = ((crop->y2 - crop->y1) < SRH) ? (crop->y2 - crop->y1) : SRH; - - gdk_draw_rectangle (crop->core->win, crop->core->gc, 1, - crop->x1, crop->y1, crop->srw, crop->srh); - gdk_draw_rectangle (crop->core->win, crop->core->gc, 1, - crop->x2 - crop->srw, crop->y2-crop->srh, crop->srw, crop->srh); - gdk_draw_rectangle (crop->core->win, crop->core->gc, 1, - crop->x2 - crop->srw, crop->y1, crop->srw, crop->srh); - gdk_draw_rectangle (crop->core->win, crop->core->gc, 1, - crop->x1, crop->y2-crop->srh, crop->srw, crop->srh); - -#undef SRW -#undef SRH - - crop_info_update (tool); -} - -Tool * -tools_new_crop (void) -{ - Tool *tool; - Crop *private; - - /* The tool options */ - if (! crop_options) - { - crop_options = crop_options_new (); - tools_register (CROP, (ToolOptions *) crop_options); - } - - tool = tools_new_tool (CROP); - private = g_new0 (Crop, 1); - - private->core = draw_core_new (crop_draw); - private->startx = private->starty = 0; - private->function = CREATING; - - tool->private = (void *) private; - - tool->preserve = FALSE; /* XXX Check me */ - - tool->button_press_func = crop_button_press; - tool->button_release_func = crop_button_release; - tool->motion_func = crop_motion; - tool->arrow_keys_func = crop_arrow_keys_func; - tool->modifier_key_func = crop_modifier_key_func; - tool->cursor_update_func = crop_cursor_update; - tool->control_func = crop_control; - - return tool; -} - -void -tools_free_crop (Tool *tool) -{ - Crop *crop; - - crop = (Crop *) tool->private; - - if (tool->state == ACTIVE) - draw_core_stop (crop->core, tool); - - if (crop_info) - crop_close_callback (NULL, NULL); - - draw_core_free (crop->core); - g_free (crop); -} - -void -crop_image (GImage *gimage, - gint x1, - gint y1, - gint x2, - gint y2, - gboolean layer_only, - gboolean crop_layers) -{ - Layer *layer; - Layer *floating_layer; - Channel *channel; - GList *guide_list_ptr; - GSList *list; - gint width, height; - gint lx1, ly1, lx2, ly2; - gint off_x, off_y; - gint doff_x, doff_y; - - width = x2 - x1; - height = y2 - y1; - - /* Make sure new width and height are non-zero */ - if (width && height) - { - gimp_add_busy_cursors (); - - if (layer_only) - { - undo_push_group_start (gimage, LAYER_RESIZE_UNDO); - - layer = gimage->active_layer; - - if (layer_is_floating_sel (layer)) - floating_sel_relax (layer, TRUE); - - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &doff_x, &doff_y); - - off_x = (doff_x - x1); - off_y = (doff_y - y1); - - layer_resize (layer, width, height, off_x, off_y); - - if (layer_is_floating_sel (layer)) - floating_sel_rigor (layer, TRUE); - - undo_push_group_end (gimage); - } - else - { - floating_layer = gimp_image_floating_sel (gimage); - - undo_push_group_start (gimage, CROP_UNDO); - - /* relax the floating layer */ - if (floating_layer) - floating_sel_relax (floating_layer, TRUE); - - /* Push the image size to the stack */ - undo_push_gimage_mod (gimage); - - /* Set the new width and height */ - gimage->width = width; - gimage->height = height; - - /* Resize all channels */ - list = gimage->channels; - while (list) - { - channel = (Channel *) list->data; - channel_resize (channel, width, height, -x1, -y1); - list = g_slist_next (list); - } - - /* Don't forget the selection mask! */ - channel_resize (gimage->selection_mask, width, height, -x1, -y1); - gimage_mask_invalidate (gimage); - - /* crop all layers */ - list = gimage->layers; - while (list) - { - GSList *next; - - layer = (Layer *) list->data; - next = g_slist_next (list); - - layer_translate (layer, -x1, -y1); - - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); - - if (crop_layers) - { - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); - - lx1 = CLAMP (off_x, 0, gimage->width); - ly1 = CLAMP (off_y, 0, gimage->height); - lx2 = CLAMP ((gimp_drawable_width (GIMP_DRAWABLE (layer)) + off_x), - 0, gimage->width); - ly2 = CLAMP ((gimp_drawable_height (GIMP_DRAWABLE (layer)) + off_y), - 0, gimage->height); - width = lx2 - lx1; - height = ly2 - ly1; - - if (width && height) - layer_resize (layer, width, height, - -(lx1 - off_x), - -(ly1 - off_y)); - else - gimp_image_remove_layer (gimage, layer); - } - - list = next; - } - - /* Make sure the projection matches the gimage size */ - gimp_image_projection_realloc (gimage); - - /* rigor the floating layer */ - if (floating_layer) - floating_sel_rigor (floating_layer, TRUE); - - guide_list_ptr = gimage->guides; - while ( guide_list_ptr != NULL) - { - undo_push_guide (gimage, (Guide *)guide_list_ptr->data); - guide_list_ptr = guide_list_ptr->next; - } - undo_push_group_end (gimage); - - /* Adjust any guides we might have laying about */ - crop_adjust_guides (gimage, x1, y1, x2, y2); - - /* shrink wrap and update all views */ - channel_invalidate_previews (gimage); - layer_invalidate_previews (gimage); - gimp_image_invalidate_preview (gimage); - gdisplays_update_full (gimage); - gdisplays_shrink_wrap (gimage); - } - gimp_remove_busy_cursors (NULL); - gdisplays_flush (); - } -} - -static void -crop_recalc (Tool *tool, - Crop *crop) -{ - gdisplay_transform_coords (tool->gdisp, crop->tx1, crop->ty1, - &crop->x1, &crop->y1, FALSE); - gdisplay_transform_coords (tool->gdisp, crop->tx2, crop->ty2, - &crop->x2, &crop->y2, FALSE); -} - -static void -crop_start (Tool *tool, - Crop *crop) -{ - static GDisplay *old_gdisp = NULL; - - crop_recalc (tool, crop); - - if (! crop_info) - crop_info_create (tool); - - gtk_signal_handler_block_by_data (GTK_OBJECT (origin_sizeentry), crop_info); - gtk_signal_handler_block_by_data (GTK_OBJECT (size_sizeentry), crop_info); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (origin_sizeentry), 0, - tool->gdisp->gimage->xresolution, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (origin_sizeentry), 1, - tool->gdisp->gimage->yresolution, FALSE); - - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (origin_sizeentry), 0, - 0, tool->gdisp->gimage->width); - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (origin_sizeentry), 1, - 0, tool->gdisp->gimage->height); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (size_sizeentry), 0, - tool->gdisp->gimage->xresolution, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (size_sizeentry), 1, - tool->gdisp->gimage->yresolution, FALSE); - - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (size_sizeentry), 0, - 0, tool->gdisp->gimage->width); - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (size_sizeentry), 1, - 0, tool->gdisp->gimage->height); - - if (old_gdisp != tool->gdisp) - { - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (origin_sizeentry), - tool->gdisp->gimage->unit) ; - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (size_sizeentry), - tool->gdisp->gimage->unit); - - if (tool->gdisp->dot_for_dot) - { - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (origin_sizeentry), - GIMP_UNIT_PIXEL); - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (size_sizeentry), - GIMP_UNIT_PIXEL); - } - } - - gtk_signal_handler_unblock_by_data (GTK_OBJECT (size_sizeentry), crop_info); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (origin_sizeentry), crop_info); - - old_gdisp = tool->gdisp; - - /* initialize the statusbar display */ - crop->context_id = - gtk_statusbar_get_context_id (GTK_STATUSBAR (tool->gdisp->statusbar), - "crop"); - gtk_statusbar_push (GTK_STATUSBAR (tool->gdisp->statusbar), - crop->context_id, _("Crop: 0 x 0")); - - draw_core_start (crop->core, tool->gdisp->canvas->window, tool); -} - - -/***************************/ -/* Crop dialog functions */ -/***************************/ - -static void -crop_info_create (Tool *tool) -{ - GDisplay *gdisp; - GtkWidget *spinbutton; - GtkWidget *bbox; - GtkWidget *button; - - gdisp = (GDisplay *) tool->gdisp; - - /* create the info dialog */ - crop_info = info_dialog_new (_("Crop & Resize Information"), - tools_help_func, NULL); - - /* create the action area */ - gimp_dialog_create_action_area (GTK_DIALOG (crop_info->shell), - - _("Crop"), crop_crop_callback, - NULL, NULL, NULL, TRUE, FALSE, - _("Resize"), crop_resize_callback, - NULL, NULL, NULL, FALSE, FALSE, - _("Close"), crop_close_callback, - NULL, NULL, NULL, FALSE, FALSE, - - NULL); - - /* add the information fields */ - spinbutton = info_dialog_add_spinbutton (crop_info, _("Origin X:"), NULL, - -1, 1, 1, 10, 1, 1, 2, NULL, NULL); - origin_sizeentry = - info_dialog_add_sizeentry (crop_info, _("Y:"), orig_vals, 1, - gdisp->dot_for_dot ? - GIMP_UNIT_PIXEL : gdisp->gimage->unit, "%a", - TRUE, TRUE, FALSE, GIMP_SIZE_ENTRY_UPDATE_SIZE, - crop_orig_changed, crop_info); - gimp_size_entry_add_field (GIMP_SIZE_ENTRY (origin_sizeentry), - GTK_SPIN_BUTTON (spinbutton), NULL); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (origin_sizeentry), 0, - -65536, 65536); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (origin_sizeentry), 1, - -65536, 65536); - - spinbutton = info_dialog_add_spinbutton (crop_info, _("Width:"), NULL, - -1, 1, 1, 10, 1, 1, 2, NULL, NULL); - size_sizeentry = - info_dialog_add_sizeentry (crop_info, _("Height:"), size_vals, 1, - gdisp->dot_for_dot ? - GIMP_UNIT_PIXEL : gdisp->gimage->unit, "%a", - TRUE, TRUE, FALSE, GIMP_SIZE_ENTRY_UPDATE_SIZE, - crop_size_changed, crop_info); - gimp_size_entry_add_field (GIMP_SIZE_ENTRY (size_sizeentry), - GTK_SPIN_BUTTON (spinbutton), NULL); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (size_sizeentry), 0, - -65536, 65536); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (size_sizeentry), 1, - -65536, 65536); - - gtk_table_set_row_spacing (GTK_TABLE (crop_info->info_table), 0, 0); - gtk_table_set_row_spacing (GTK_TABLE (crop_info->info_table), 1, 6); - gtk_table_set_row_spacing (GTK_TABLE (crop_info->info_table), 2, 0); - - /* Create the area selection buttons */ - bbox = gtk_hbutton_box_new (); - gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD); - gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 4); - - button = gtk_button_new_with_label (_("From Selection")); - gtk_container_add( GTK_CONTAINER(bbox), button); - gtk_signal_connect(GTK_OBJECT (button) , "clicked", - (GtkSignalFunc) crop_selection_callback, NULL); - gtk_widget_show (button); - - button = gtk_button_new_with_label (_("Auto Shrink")); - gtk_container_add(GTK_CONTAINER (bbox), button); - gtk_signal_connect(GTK_OBJECT (button) , "clicked", - (GtkSignalFunc) crop_automatic_callback, NULL); - gtk_widget_show (button); - - gtk_box_pack_start (GTK_BOX (crop_info->vbox), bbox, FALSE, FALSE, 2); - gtk_widget_show (bbox); -} - -static void -crop_info_update (Tool *tool) -{ - Crop *crop; - - crop = (Crop *) tool->private; - - orig_vals[0] = crop->tx1; - orig_vals[1] = crop->ty1; - size_vals[0] = crop->tx2 - crop->tx1; - size_vals[1] = crop->ty2 - crop->ty1; - - info_dialog_update (crop_info); - info_dialog_popup (crop_info); -} - -static void -crop_crop_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - - tool = active_tool; - crop = (Crop *) tool->private; - - crop_image (tool->gdisp->gimage, - crop->tx1, crop->ty1, - crop->tx2, crop->ty2, - crop_options->layer_only, - TRUE); - - /* Finish the tool */ - crop_close_callback (NULL, NULL); -} - -static void -crop_resize_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - - tool = active_tool; - crop = (Crop *) tool->private; - - crop_image (tool->gdisp->gimage, - crop->tx1, crop->ty1, - crop->tx2, crop->ty2, - crop_options->layer_only, - FALSE); - - /* Finish the tool */ - crop_close_callback (NULL, NULL); -} - -static void -crop_close_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - - tool = active_tool; - crop = (Crop *) tool->private; - - if (tool->state == ACTIVE) - draw_core_stop (crop->core, tool); - - info_dialog_popdown (crop_info); - - tool->gdisp = NULL; - tool->drawable = NULL; - tool->state = INACTIVE; -} - -static void -crop_selection_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - Layer *layer; - GDisplay *gdisp; - - tool = active_tool; - crop = (Crop *) tool->private; - gdisp = tool->gdisp; - - draw_core_pause (crop->core, tool); - if (! gimage_mask_bounds (gdisp->gimage, - &crop->tx1, &crop->ty1, &crop->tx2, &crop->ty2)) - { - if (crop_options->layer_only) - { - layer = (gdisp->gimage)->active_layer; - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &crop->tx1, &crop->ty1); - crop->tx2 = gimp_drawable_width (GIMP_DRAWABLE (layer)) + crop->tx1; - crop->ty2 = gimp_drawable_height (GIMP_DRAWABLE (layer)) + crop->ty1; - } - else - { - crop->tx1 = crop->ty1 = 0; - crop->tx2 = gdisp->gimage->width; - crop->ty2 = gdisp->gimage->height; - } - } - crop_recalc (tool, crop); - draw_core_resume (crop->core, tool); -} - - -static void -crop_automatic_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - GDisplay *gdisp; - GimpDrawable *active_drawable = NULL; - GetColorFunc get_color_func; - ColorsEqualFunc colors_equal_func; - GtkObject *get_color_obj; - guchar bgcolor[4] = {0, 0, 0, 0}; - gboolean has_alpha = FALSE; - PixelRegion PR; - guchar *buffer = NULL; - gint offset_x, offset_y, width, height, bytes; - gint x, y, abort; - gint x1, y1, x2, y2; - - tool = active_tool; - crop = (Crop *) tool->private; - gdisp = tool->gdisp; - - draw_core_pause (crop->core, tool); - gimp_add_busy_cursors (); - - /* You should always keep in mind that crop->tx2 and crop->ty2 are the NOT the - coordinates of the bottomright corner of the area to be cropped. They point - at the pixel located one to the right and one to the bottom. - */ - - if (crop_options->layer_only) - { - if (!(active_drawable = gimp_image_active_drawable (gdisp->gimage))) - return; - width = gimp_drawable_width (GIMP_DRAWABLE (active_drawable)); - height = gimp_drawable_height (GIMP_DRAWABLE (active_drawable)); - bytes = gimp_drawable_bytes (GIMP_DRAWABLE (active_drawable)); - if (gimp_drawable_has_alpha (GIMP_DRAWABLE (active_drawable))) - has_alpha = TRUE; - get_color_obj = GTK_OBJECT (active_drawable); - get_color_func = (GetColorFunc) gimp_drawable_get_color_at; - gimp_drawable_offsets (GIMP_DRAWABLE (active_drawable), - &offset_x, &offset_y); - } - else - { - width = gdisp->gimage->width; - height = gdisp->gimage->height; - has_alpha = TRUE; - bytes = gimp_image_composite_bytes (gdisp->gimage); - get_color_obj = GTK_OBJECT (gdisp->gimage); - get_color_func = (GetColorFunc) gimp_image_get_color_at; - offset_x = offset_y = 0; - } - - x1 = crop->tx1 - offset_x > 0 ? crop->tx1 - offset_x : 0; - x2 = crop->tx2 - offset_x < width ? crop->tx2 - offset_x : width; - y1 = crop->ty1 - offset_y > 0 ? crop->ty1 - offset_y : 0; - y2 = crop->ty2 - offset_y < height ? crop->ty2 - offset_y : height; - - switch (crop_guess_bgcolor (get_color_obj, get_color_func, bytes, has_alpha, - bgcolor, x1, x2-1, y1, y2-1)) - { - case AUTO_CROP_ALPHA: - colors_equal_func = (ColorsEqualFunc) crop_colors_alpha; - break; - case AUTO_CROP_COLOR: - colors_equal_func = (ColorsEqualFunc) crop_colors_equal; - break; - default: - goto FINISH; - } - - width = x2 - x1; - height = y2 - y1; - - if (crop_options->layer_only) - pixel_region_init (&PR, gimp_drawable_data (active_drawable), - x1, y1, width, height, FALSE); - else - pixel_region_init (&PR, gimp_image_composite (gdisp->gimage), - x1, y1, width, height, FALSE); - - /* The following could be optimized further by processing the smaller side first - instead of defaulting to width --Sven - */ - - buffer = g_malloc ((width > height ? width : height) * bytes); - - /* Check how many of the top lines are uniform/transparent. */ - abort = FALSE; - for (y = y1; y < y2 && !abort; y++) - { - pixel_region_get_row (&PR, x1, y, width, buffer, 1); - for (x = 0; x < width && !abort; x++) - abort = !(colors_equal_func) (bgcolor, buffer + x * bytes, bytes); - } - if (y == y2 && !abort) - goto FINISH; - y1 = y - 1; - - /* Check how many of the bottom lines are uniform/transparent. */ - abort = FALSE; - for (y = y2; y > y1 && !abort; y--) - { - pixel_region_get_row (&PR, x1, y-1 , width, buffer, 1); - for (x = 0; x < width && !abort; x++) - abort = !(colors_equal_func) (bgcolor, buffer + x * bytes, bytes); - } - y2 = y + 1; - - /* compute a new height for the next operations */ - height = y2 - y1; - - /* Check how many of the left lines are uniform/transparent. */ - abort = FALSE; - for (x = x1; x < x2 && !abort; x++) - { - pixel_region_get_col (&PR, x, y1, height, buffer, 1); - for (y = 0; y < height && !abort; y++) - abort = !(colors_equal_func) (bgcolor, buffer + y * bytes, bytes); - } - x1 = x - 1; - - /* Check how many of the right lines are uniform/transparent. */ - abort = FALSE; - for (x = x2; x > x1 && !abort; x--) - { - pixel_region_get_col (&PR, x-1, y1, height, buffer, 1); - for (y = 0; y < height && !abort; y++) - abort = !(colors_equal_func) (bgcolor, buffer + y * bytes, bytes); - } - x2 = x + 1; - - crop->tx1 = offset_x + x1; - crop->tx2 = offset_x + x2; - crop->ty1 = offset_y + y1; - crop->ty2 = offset_y + y2; - - crop_recalc (tool, crop); - - FINISH: - g_free (buffer); - gimp_remove_busy_cursors (NULL); - draw_core_resume (crop->core, tool); - - return; -} - -static AutoCropType -crop_guess_bgcolor (GtkObject *get_color_obj, - GetColorFunc get_color_func, - gint bytes, - gboolean has_alpha, - guchar *color, - gint x1, - gint x2, - gint y1, - gint y2) -{ - guchar *tl = NULL; - guchar *tr = NULL; - guchar *bl = NULL; - guchar *br = NULL; - gint i, alpha; - - for (i = 0; i < bytes; i++) - color[i] = 0; - - /* First check if there's transparency to crop. If not, guess the - * background-color to see if at least 2 corners are equal. - */ - - if (!(tl = (*get_color_func) (get_color_obj, x1, y1))) - goto ERROR; - if (!(tr = (*get_color_func) (get_color_obj, x1, y2))) - goto ERROR; - if (!(bl = (*get_color_func) (get_color_obj, x2, y1))) - goto ERROR; - if (!(br = (*get_color_func) (get_color_obj, x2, y2))) - goto ERROR; - - if (has_alpha) - { - alpha = bytes - 1; - if ((tl[alpha] == 0 && tr[alpha] == 0) || - (tl[alpha] == 0 && bl[alpha] == 0) || - (tr[alpha] == 0 && br[alpha] == 0) || - (bl[alpha] == 0 && br[alpha] == 0)) - { - g_free (tl); - g_free (tr); - g_free (bl); - g_free (br); - return AUTO_CROP_ALPHA; - } - } - - if (crop_colors_equal (tl, tr, bytes) || crop_colors_equal (tl, bl, bytes)) - memcpy (color, tl, bytes); - else if (crop_colors_equal (br, bl, bytes) || crop_colors_equal (br, tr, bytes)) - memcpy (color, br, bytes); - else - goto ERROR; - - g_free (tl); - g_free (tr); - g_free (bl); - g_free (br); - return AUTO_CROP_COLOR; - - ERROR: - g_free (tl); - g_free (tr); - g_free (bl); - g_free (br); - return AUTO_CROP_NOTHING; -} - -static int -crop_colors_equal (guchar *col1, - guchar *col2, - gint bytes) -{ - gboolean equal = TRUE; - gint b; - - for (b = 0; b < bytes; b++) - { - if (col1[b] != col2[b]) - { - equal = FALSE; - break; - } - } - - return equal; -} - -static gboolean -crop_colors_alpha (guchar *dummy, - guchar *col, - gint bytes) -{ - if (col[bytes-1] == 0) - return TRUE; - else - return FALSE; -} - -static void -crop_orig_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - gint ox; - gint oy; - - tool = active_tool; - - if (tool && active_tool->type == CROP) - { - crop = (Crop *) tool->private; - - ox = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0)); - oy = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1)); - - if ((ox != crop->tx1) || - (oy != crop->ty1)) - { - draw_core_pause (crop->core, tool); - crop->tx2 = crop->tx2 + (ox - crop->tx1); - crop->tx1 = ox; - crop->ty2 = crop->ty2 + (oy - crop->ty1); - crop->ty1 = oy; - crop_recalc (tool, crop); - draw_core_resume (crop->core, tool); - } - } -} - -static void -crop_size_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - Crop *crop; - gint sx; - gint sy; - - tool = active_tool; - - if (tool && active_tool->type == CROP) - { - crop = (Crop *) tool->private; - - sx = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0); - sy = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1); - - if ((sx != (crop->tx2 - crop->tx1)) || - (sy != (crop->ty2 - crop->ty1))) - { - draw_core_pause (crop->core, tool); - crop->tx2 = sx + crop->tx1; - crop->ty2 = sy + crop->ty1; - crop_recalc (tool, crop); - draw_core_resume (crop->core, tool); - } - } -} diff --git a/app/crop.h b/app/crop.h deleted file mode 100644 index fe7d35d34d..0000000000 --- a/app/crop.h +++ /dev/null @@ -1,43 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __CROP_H__ -#define __CROP_H__ - - -typedef enum -{ - CROP_CROP, - RESIZE_CROP -} CropType; - - -void crop_draw (Tool *tool); -void crop_image (GimpImage *gimage, - gint x1, - gint y1, - gint x2, - gint y2, - gboolean layer_only, - gboolean crop_layers); - -Tool * tools_new_crop (void); -void tools_free_crop (Tool *tool); - - -#endif /* __CROP_H__ */ diff --git a/app/cursorutil.c b/app/cursorutil.c index 881ac32cc2..8bcdb218a4 100644 --- a/app/cursorutil.c +++ b/app/cursorutil.c @@ -26,7 +26,8 @@ #include "cursorutil.h" #include "dialog_handler.h" #include "gdisplay.h" /* for gdisplay_*_override_cursor() */ -#include "tools.h" + +#include "tools/tools.h" #include "cursors/mouse.xbm" #include "cursors/mouse_mask.xbm" diff --git a/app/curves.c b/app/curves.c deleted file mode 100644 index 93950ffe09..0000000000 --- a/app/curves.c +++ /dev/null @@ -1,1821 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "cursorutil.h" -#include "curves.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimphistogram.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "gimplut.h" -#include "image_map.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpenv.h" -#include "libgimp/gimphelpui.h" -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -#define GRAPH 0x1 -#define XRANGE_TOP 0x2 -#define XRANGE_BOTTOM 0x4 -#define YRANGE 0x8 -#define DRAW 0x10 -#define ALL 0xFF - -/* NB: take care when changing these values: make sure the curve[] array in - * curves.h is large enough. - */ -#define GRAPH_WIDTH 256 -#define GRAPH_HEIGHT 256 -#define XRANGE_WIDTH 256 -#define XRANGE_HEIGHT 16 -#define YRANGE_WIDTH 16 -#define YRANGE_HEIGHT 256 -#define RADIUS 3 -#define MIN_DISTANCE 8 - -#define RANGE_MASK GDK_EXPOSURE_MASK | \ - GDK_ENTER_NOTIFY_MASK - -#define GRAPH_MASK GDK_EXPOSURE_MASK | \ - GDK_POINTER_MOTION_MASK | \ - GDK_POINTER_MOTION_HINT_MASK | \ - GDK_ENTER_NOTIFY_MASK | \ - GDK_BUTTON_PRESS_MASK | \ - GDK_BUTTON_RELEASE_MASK | \ - GDK_BUTTON1_MOTION_MASK - -/* the curves structures */ - -typedef struct _Curves Curves; - -struct _Curves -{ - gint x, y; /* coords for last mouse click */ -}; - -typedef gdouble CRMatrix[4][4]; - -/* the curves tool options */ -static ToolOptions * curves_options = NULL; - -/* the curves dialog */ -static CurvesDialog * curves_dialog = NULL; - -/* the curves file dialog */ -static GtkWidget *file_dlg = NULL; -static gboolean load_save; - -static GtkWidget *channel_items[5]; - -static CRMatrix CR_basis = -{ - { -0.5, 1.5, -1.5, 0.5 }, - { 1.0, -2.5, 2.0, -0.5 }, - { -0.5, 0.0, 0.5, 0.0 }, - { 0.0, 1.0, 0.0, 0.0 }, -}; - - -/* curves action functions */ - -static void curves_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void curves_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void curves_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void curves_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static CurvesDialog * curves_dialog_new (void); - -static void curves_update (CurvesDialog *cd, - gint ); -static void curves_plot_curve (CurvesDialog *cd, - gint , - gint , - gint , - gint ); -static void curves_preview (CurvesDialog *cd); - -static void curves_channel_callback (GtkWidget *widget, - gpointer data); - -static void curves_smooth_callback (GtkWidget *widget, - gpointer data); -static void curves_free_callback (GtkWidget *widget, - gpointer data); - -static void curves_channel_reset (gint ); -static void curves_reset_callback (GtkWidget *widget, - gpointer data); -static void curves_ok_callback (GtkWidget *widget, - gpointer data); -static void curves_cancel_callback (GtkWidget *widget, - gpointer data); -static void curves_load_callback (GtkWidget *widget, - gpointer data); -static void curves_save_callback (GtkWidget *widget, - gpointer data); -static void curves_preview_update (GtkWidget *widget, - gpointer data); -static gint curves_xrange_events (GtkWidget *widget, - GdkEvent *event, - CurvesDialog *cd); -static gint curves_yrange_events (GtkWidget *widget, - GdkEvent *event, - CurvesDialog *cd); -static gint curves_graph_events (GtkWidget *widget, - GdkEvent *event, - CurvesDialog *cd); -static void curves_CR_compose (CRMatrix , - CRMatrix , - CRMatrix ); - -static void file_dialog_create (GtkWidget *widget); -static void file_dialog_ok_callback (GtkWidget *widget, - gpointer data); -static void file_dialog_cancel_callback (GtkWidget *widget, - gpointer data); - -static gboolean curves_read_from_file (FILE *f); -static void curves_write_to_file (FILE *f); - - -/* curves machinery */ - -gfloat -curves_lut_func (CurvesDialog *cd, - gint nchannels, - gint channel, - gfloat value) -{ - gfloat f; - gint index; - gdouble inten; - gint j; - - if (nchannels == 1) - j = 0; - else - j = channel + 1; - - inten = value; - - /* For color images this runs through the loop with j = channel +1 - the first time and j = 0 the second time */ - /* For bw images this runs through the loop with j = 0 the first and - only time */ - for (; j >= 0; j -= (channel + 1)) - { - /* don't apply the overall curve to the alpha channel */ - if (j == 0 && (nchannels == 2 || nchannels == 4) - && channel == nchannels -1) - return inten; - - if (inten < 0.0) - inten = cd->curve[j][0]/255.0; - else if (inten >= 1.0) - inten = cd->curve[j][255]/255.0; - else /* interpolate the curve */ - { - index = floor(inten * 255.0); - f = inten*255.0 - index; - inten = ((1.0 - f) * cd->curve[j][index ] + - ( f) * cd->curve[j][index + 1] ) / 255.0; - } - } - return inten; -} - -static void -curves_colour_update (Tool *tool, - GDisplay *gdisp, - GimpDrawable *drawable, - gint x, - gint y) -{ - guchar *color; - gint offx; - gint offy; - gint maxval; - gboolean has_alpha; - gboolean is_indexed; - GimpImageType sample_type; - - if (!tool || tool->state != ACTIVE) - return; - - gimp_drawable_offsets (drawable, &offx, &offy); - - x -= offx; - y -= offy; - - if (!(color = image_map_get_color_at (curves_dialog->image_map, x, y))) - return; - - sample_type = gimp_drawable_type (drawable); - is_indexed = gimp_drawable_is_indexed (drawable); - has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (sample_type); - - curves_dialog->col_value[GIMP_HISTOGRAM_RED] = color[RED_PIX]; - curves_dialog->col_value[GIMP_HISTOGRAM_GREEN] = color[GREEN_PIX]; - curves_dialog->col_value[GIMP_HISTOGRAM_BLUE] = color[BLUE_PIX]; - - if (has_alpha) - { - curves_dialog->col_value [GIMP_HISTOGRAM_ALPHA] = color[3]; - } - - if (is_indexed) - curves_dialog->col_value [GIMP_HISTOGRAM_ALPHA] = color[4]; - - maxval = MAX (color[RED_PIX], color[GREEN_PIX]); - curves_dialog->col_value[GIMP_HISTOGRAM_VALUE] = MAX (maxval, color[BLUE_PIX]); - - g_free (color); -} - -static void -curves_add_point (GimpDrawable *drawable, - gint x, - gint y, - gint cchan) -{ - /* Add point onto the curve */ - gint closest_point = 0; - gint distance; - gint curvex; - gint i; - - switch (curves_dialog->curve_type[cchan]) - { - case SMOOTH: - curvex = curves_dialog->col_value[cchan]; - distance = G_MAXINT; - for (i = 0; i < 17; i++) - { - if (curves_dialog->points[cchan][i][0] != -1) - if (abs (curvex - curves_dialog->points[cchan][i][0]) < distance) - { - distance = abs (curvex - curves_dialog->points[cchan][i][0]); - closest_point = i; - } - } - - if (distance > MIN_DISTANCE) - closest_point = (curvex + 8) / 16; - - curves_dialog->points[cchan][closest_point][0] = curvex; - curves_dialog->points[cchan][closest_point][1] = curves_dialog->curve[cchan][curvex]; - break; - - case GFREE: - curves_dialog->curve[cchan][x] = 255 - y; - break; - } -} - -/* curves action functions */ - -static void -curves_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - gint x, y; - GimpDrawable *drawable; - - drawable = gimp_image_active_drawable (gdisp->gimage); - - tool->gdisp = gdisp; - - if (drawable != tool->drawable) - { - active_tool->preserve = TRUE; - image_map_abort (curves_dialog->image_map); - active_tool->preserve = FALSE; - - tool->drawable = drawable; - - curves_dialog->drawable = drawable; - curves_dialog->color = gimp_drawable_is_rgb (drawable); - curves_dialog->image_map = image_map_create (gdisp, drawable); - } - - tool->state = ACTIVE; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, - FALSE, FALSE); - curves_colour_update (tool, gdisp, drawable, x, y); - curves_update (curves_dialog, GRAPH | DRAW); -} - -static void -curves_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - gint x, y; - GimpDrawable *drawable; - - if (! curves_dialog || - ! gdisp || - ! (drawable = gimp_image_active_drawable (gdisp->gimage))) - return; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, - FALSE, FALSE); - curves_colour_update (tool, gdisp, drawable, x, y); - - if (bevent->state & GDK_SHIFT_MASK) - { - curves_add_point (drawable, x, y, curves_dialog->channel); - curves_calculate_curve (curves_dialog); - } - else if (bevent->state & GDK_CONTROL_MASK) - { - curves_add_point (drawable, x, y, GIMP_HISTOGRAM_VALUE); - curves_add_point (drawable, x, y, GIMP_HISTOGRAM_RED); - curves_add_point (drawable, x, y, GIMP_HISTOGRAM_GREEN); - curves_add_point (drawable, x, y, GIMP_HISTOGRAM_BLUE); - curves_add_point (drawable, x, y, GIMP_HISTOGRAM_ALPHA); - curves_calculate_curve (curves_dialog); - } - - curves_update (curves_dialog, GRAPH | DRAW); -} - -static void -curves_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - gint x, y; - GimpDrawable *drawable; - - if (! curves_dialog || - ! gdisp || - ! (drawable = gimp_image_active_drawable (gdisp->gimage))) - return; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, FALSE, FALSE); - curves_colour_update (tool, gdisp, drawable, x, y); - curves_update (curves_dialog, GRAPH | DRAW); -} - -static void -curves_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - curves_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_curves (void) -{ - Tool *tool; - Curves *private; - - /* The tool options */ - if (!curves_options) - { - curves_options = tool_options_new (_("Curves")); - tools_register (CURVES, curves_options); - } - - tool = tools_new_tool (CURVES); - private = g_new0 (Curves, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->button_press_func = curves_button_press; - tool->button_release_func = curves_button_release; - tool->motion_func = curves_motion; - tool->control_func = curves_control; - - return tool; -} - -void -curves_dialog_hide (void) -{ - if (curves_dialog) - curves_cancel_callback (NULL, (gpointer) curves_dialog); -} - -void -tools_free_curves (Tool *tool) -{ - Curves *private; - - private = (Curves *) tool->private; - - /* Close the color select dialog */ - curves_dialog_hide (); - - g_free (private); -} - -void -curves_initialize (GDisplay *gdisp) -{ - gint i, j; - - if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Curves for indexed drawables cannot be adjusted.")); - return; - } - - /* The curves dialog */ - if (!curves_dialog) - { - curves_dialog = curves_dialog_new (); - } - - /* Initialize the values */ - curves_dialog->channel = GIMP_HISTOGRAM_VALUE; - for (i = 0; i < 5; i++) - for (j = 0; j < 256; j++) - curves_dialog->curve[i][j] = j; - - for (i = 0; i < 5; i++) - { - curves_channel_reset (i); - } - - curves_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - curves_dialog->color = gimp_drawable_is_rgb (curves_dialog->drawable); - curves_dialog->image_map = image_map_create (gdisp, curves_dialog->drawable); - - /* check for alpha channel */ - if (gimp_drawable_has_alpha (curves_dialog->drawable)) - gtk_widget_set_sensitive (channel_items[4], TRUE); - else - gtk_widget_set_sensitive (channel_items[4], FALSE); - - /* hide or show the channel menu based on image type */ - if (curves_dialog->color) - for (i = 0; i < 4; i++) - gtk_widget_set_sensitive (channel_items[i], TRUE); - else - for (i = 1; i < 4; i++) - gtk_widget_set_sensitive (channel_items[i], FALSE); - - /* set the current selection */ - gtk_option_menu_set_history (GTK_OPTION_MENU (curves_dialog->channel_menu), - curves_dialog->channel); - - gimp_lut_setup (curves_dialog->lut, - (GimpLutFunc) curves_lut_func, - (void *) curves_dialog, - gimp_drawable_bytes (curves_dialog->drawable)); - - if (!GTK_WIDGET_VISIBLE (curves_dialog->shell)) - gtk_widget_show (curves_dialog->shell); - - curves_update (curves_dialog, GRAPH | DRAW); -} - -void -curves_free (void) -{ - if (curves_dialog) - { - if (curves_dialog->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (curves_dialog->image_map); - active_tool->preserve = FALSE; - - curves_dialog->image_map = NULL; - } - - if (curves_dialog->pixmap) - gdk_pixmap_unref (curves_dialog->pixmap); - - gtk_widget_destroy (curves_dialog->shell); - } -} - -/*******************/ -/* Curves dialog */ -/*******************/ - -static CurvesDialog * -curves_dialog_new (void) -{ - CurvesDialog *cd; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *hbbox; - GtkWidget *label; - GtkWidget *frame; - GtkWidget *toggle; - GtkWidget *channel_hbox; - GtkWidget *table; - GtkWidget *button; - gint i, j; - - cd = g_new (CurvesDialog, 1); - cd->cursor_ind_height = -1; - cd->cursor_ind_width = -1; - cd->preview = TRUE; - cd->pixmap = NULL; - cd->channel = GIMP_HISTOGRAM_VALUE; - - for (i = 0; i < 5; i++) - cd->curve_type[i] = SMOOTH; - - for (i = 0; i < 5; i++) - for (j = 0; j < 256; j++) - cd->curve[i][j] = j; - - for (i = 0; i < (sizeof (cd->col_value) / sizeof (cd->col_value[0])); i++) - cd->col_value[i] = 0; - - cd->lut = gimp_lut_new (); - - /* The shell and main vbox */ - cd->shell = gimp_dialog_new (_("Curves"), "curves", - tools_help_func, tool_info[CURVES].private_tip, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), curves_ok_callback, - cd, NULL, NULL, TRUE, FALSE, - _("Reset"), curves_reset_callback, - cd, NULL, NULL, FALSE, FALSE, - _("Cancel"), curves_cancel_callback, - cd, NULL, NULL, FALSE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (cd->shell)->vbox), vbox); - - /* The option menu for selecting channels */ - channel_hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), channel_hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Modify Curves for Channel:")); - gtk_box_pack_start (GTK_BOX (channel_hbox), label, FALSE, FALSE, 0); - - cd->channel_menu = gimp_option_menu_new2 - (FALSE, curves_channel_callback, - cd, (gpointer) cd->channel, - - _("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, &channel_items[0], - _("Red"), (gpointer) GIMP_HISTOGRAM_RED, &channel_items[1], - _("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, &channel_items[2], - _("Blue"), (gpointer) GIMP_HISTOGRAM_BLUE, &channel_items[3], - _("Alpha"), (gpointer) GIMP_HISTOGRAM_ALPHA, &channel_items[4], - - NULL); - - gtk_box_pack_start (GTK_BOX (channel_hbox), cd->channel_menu, FALSE, FALSE, 2); - - gtk_widget_show (label); - gtk_widget_show (cd->channel_menu); - gtk_widget_show (channel_hbox); - - /* The table for the yrange and the graph */ - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 2); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - /* The range drawing area */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_table_attach (GTK_TABLE (table), frame, 0, 1, 0, 1, - GTK_EXPAND, GTK_EXPAND, 0, 0); - - cd->yrange = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (cd->yrange), YRANGE_WIDTH, YRANGE_HEIGHT); - gtk_widget_set_events (cd->yrange, RANGE_MASK); - gtk_container_add (GTK_CONTAINER (frame), cd->yrange); - - gtk_signal_connect (GTK_OBJECT (cd->yrange), "event", - GTK_SIGNAL_FUNC (curves_yrange_events), - cd); - - gtk_widget_show (cd->yrange); - gtk_widget_show (frame); - - /* The curves graph */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 0, 1, - GTK_SHRINK | GTK_FILL, - GTK_SHRINK | GTK_FILL, 0, 0); - - cd->graph = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (cd->graph), - GRAPH_WIDTH + RADIUS * 2, - GRAPH_HEIGHT + RADIUS * 2); - gtk_widget_set_events (cd->graph, GRAPH_MASK); - gtk_container_add (GTK_CONTAINER (frame), cd->graph); - - gtk_signal_connect (GTK_OBJECT (cd->graph), "event", - GTK_SIGNAL_FUNC (curves_graph_events), - cd); - - gtk_widget_show (cd->graph); - gtk_widget_show (frame); - - /* The range drawing area */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 1, 2, - GTK_EXPAND, GTK_EXPAND, 0, 0); - - cd->xrange = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (cd->xrange), XRANGE_WIDTH, XRANGE_HEIGHT); - gtk_widget_set_events (cd->xrange, RANGE_MASK); - gtk_container_add (GTK_CONTAINER (frame), cd->xrange); - - gtk_signal_connect (GTK_OBJECT (cd->xrange), "event", - GTK_SIGNAL_FUNC (curves_xrange_events), - cd); - - gtk_widget_show (cd->xrange); - gtk_widget_show (frame); - gtk_widget_show (table); - - /* Horizontal box for preview */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* The option menu for selecting the drawing method */ - label = gtk_label_new (_("Curve Type:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - cd->curve_type_menu = gimp_option_menu_new - (FALSE, - - _("Smooth"), curves_smooth_callback, cd, NULL, NULL, TRUE, - _("Free"), curves_free_callback, cd, NULL, NULL, FALSE, - - NULL); - gtk_box_pack_start (GTK_BOX (hbox), cd->curve_type_menu, FALSE, FALSE, 2); - gtk_widget_show (cd->curve_type_menu); - - gtk_widget_show (hbox); - - /* The preview toggle */ - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (curves_preview_update), - cd); - - gtk_widget_show (toggle); - gtk_widget_show (hbox); - - /* Horizontal button box for load / save */ - hbbox = gtk_hbutton_box_new (); - gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4); - gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD); - gtk_box_pack_end (GTK_BOX (vbox), hbbox, FALSE, FALSE, 0); - - button = gtk_button_new_with_label (_("Load")); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (curves_load_callback), - cd->shell); - gtk_widget_show (button); - - button = gtk_button_new_with_label (_("Save")); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (curves_save_callback), - cd->shell); - gtk_widget_show (button); - - gtk_widget_show (hbbox); - gtk_widget_show (vbox); - - return cd; -} - -static void -curve_print_loc (CurvesDialog *cd, - gint xpos, - gint ypos) -{ - gchar buf[32]; - gint width; - gint ascent; - gint descent; - - if (cd->cursor_ind_width < 0) - { - /* Calc max extents */ - gdk_string_extents (cd->graph->style->font, - "x:888 y:888", - NULL, - NULL, - &width, - &ascent, - &descent); - - cd->cursor_ind_width = width; - cd->cursor_ind_height = ascent + descent; - cd->cursor_ind_ascent = ascent; - } - - if (xpos >= 0 && xpos <= 255 && ypos >=0 && ypos <= 255) - { - g_snprintf (buf, sizeof (buf), "x:%d y:%d",xpos,ypos); - - gdk_draw_rectangle (cd->graph->window, - cd->graph->style->bg_gc[GTK_STATE_ACTIVE], - TRUE, RADIUS*2 + 2 , RADIUS*2 + 2, - cd->cursor_ind_width+4, - cd->cursor_ind_height+5); - - gdk_draw_rectangle (cd->graph->window, - cd->graph->style->black_gc, - FALSE, RADIUS*2 + 2 , RADIUS*2 + 2, - cd->cursor_ind_width+3, - cd->cursor_ind_height+4); - - gdk_draw_string (cd->graph->window, - cd->graph->style->font, - cd->graph->style->black_gc, - RADIUS*2 + 4, - RADIUS*2 + 5 + cd->cursor_ind_ascent, - buf); - } -} - -/* TODO: preview alpha channel stuff correctly. -- austin, 20/May/99 */ -static void -curves_update (CurvesDialog *cd, - gint update) -{ - GdkRectangle area; - gint i, j; - gchar buf[32]; - gint offset; - gint sel_channel; - - if(cd->color) { - sel_channel = cd->channel; - } else { - if(cd->channel == 2) - sel_channel = GIMP_HISTOGRAM_ALPHA; - else - sel_channel = GIMP_HISTOGRAM_VALUE; - } - - - if (update & XRANGE_TOP) - { - guchar buf[XRANGE_WIDTH * 3]; - - switch (sel_channel) - { - case GIMP_HISTOGRAM_VALUE: - case GIMP_HISTOGRAM_ALPHA: - for (i = 0; i < XRANGE_HEIGHT / 2; i++) - { - for (j = 0; j < XRANGE_WIDTH ; j++) - { - buf[j*3+0] = cd->curve[sel_channel][j]; - buf[j*3+1] = cd->curve[sel_channel][j]; - buf[j*3+2] = cd->curve[sel_channel][j]; - } - gtk_preview_draw_row (GTK_PREVIEW (cd->xrange), - buf, 0, i, XRANGE_WIDTH); - } - break; - - case GIMP_HISTOGRAM_RED: - case GIMP_HISTOGRAM_GREEN: - case GIMP_HISTOGRAM_BLUE: - { - for (i = 0; i < XRANGE_HEIGHT / 2; i++) - { - for (j = 0; j < XRANGE_WIDTH; j++) - { - buf[j*3+0] = cd->curve[GIMP_HISTOGRAM_RED][j]; - buf[j*3+1] = cd->curve[GIMP_HISTOGRAM_GREEN][j]; - buf[j*3+2] = cd->curve[GIMP_HISTOGRAM_BLUE][j]; - } - gtk_preview_draw_row (GTK_PREVIEW (cd->xrange), - buf, 0, i, XRANGE_WIDTH); - } - break; - } - - default: - g_warning ("unknown channel type %d, can't happen!?!?", - cd->channel); - break; - } - - if (update & DRAW) - { - area.x = 0; - area.y = 0; - area.width = XRANGE_WIDTH; - area.height = XRANGE_HEIGHT / 2; - gtk_widget_draw (cd->xrange, &area); - } - } - if (update & XRANGE_BOTTOM) - { - guchar buf[XRANGE_WIDTH * 3]; - - for (i = 0; i < XRANGE_WIDTH; i++) - { - buf[i*3+0] = i; - buf[i*3+1] = i; - buf[i*3+2] = i; - } - - for (i = XRANGE_HEIGHT / 2; i < XRANGE_HEIGHT; i++) - gtk_preview_draw_row (GTK_PREVIEW (cd->xrange), buf, 0, i, XRANGE_WIDTH); - - if (update & DRAW) - { - area.x = 0; - area.y = XRANGE_HEIGHT / 2; - area.width = XRANGE_WIDTH; - area.height = XRANGE_HEIGHT / 2; - gtk_widget_draw (cd->xrange, &area); - } - } - if (update & YRANGE) - { - guchar buf[YRANGE_WIDTH * 3]; - guchar pix[3]; - - for (i = 0; i < YRANGE_HEIGHT; i++) - { - switch (sel_channel) - { - case GIMP_HISTOGRAM_VALUE: - case GIMP_HISTOGRAM_ALPHA: - pix[0] = pix[1] = pix[2] = (255 - i); - break; - - case GIMP_HISTOGRAM_RED: - case GIMP_HISTOGRAM_GREEN: - case GIMP_HISTOGRAM_BLUE: - pix[0] = pix[1] = pix[2] = 0; - pix[sel_channel - 1] = (255 - i); - break; - - default: - g_warning ("unknown channel type %d, can't happen!?!?", - cd->channel); - break; - } - - for (j = 0; j < YRANGE_WIDTH * 3; j++) - buf[j] = pix[j%3]; - - gtk_preview_draw_row (GTK_PREVIEW (cd->yrange), - buf, 0, i, YRANGE_WIDTH); - } - - if (update & DRAW) - gtk_widget_draw (cd->yrange, NULL); - } - if ((update & GRAPH) && (update & DRAW) && cd->pixmap != NULL) - { - GdkPoint points[256]; - - /* Clear the pixmap */ - gdk_draw_rectangle (cd->pixmap, cd->graph->style->bg_gc[GTK_STATE_NORMAL], - TRUE, 0, 0, - GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2); - - /* Draw the grid lines */ - for (i = 0; i < 5; i++) - { - gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL], - RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS, - GRAPH_WIDTH + RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS); - gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL], - i * (GRAPH_WIDTH / 4) + RADIUS, RADIUS, - i * (GRAPH_WIDTH / 4) + RADIUS, GRAPH_HEIGHT + RADIUS); - } - - /* Draw the curve */ - for (i = 0; i < 256; i++) - { - points[i].x = i + RADIUS; - points[i].y = 255 - cd->curve[cd->channel][i] + RADIUS; - } - gdk_draw_points (cd->pixmap, cd->graph->style->black_gc, points, 256); - - /* Draw the points */ - if (cd->curve_type[cd->channel] == SMOOTH) - for (i = 0; i < 17; i++) - { - if (cd->points[cd->channel][i][0] != -1) - gdk_draw_arc (cd->pixmap, cd->graph->style->black_gc, TRUE, - cd->points[cd->channel][i][0], - 255 - cd->points[cd->channel][i][1], - RADIUS * 2, RADIUS * 2, 0, 23040); - } - - /* draw the colour line */ - gdk_draw_line (cd->pixmap, cd->graph->style->black_gc, - cd->col_value[sel_channel]+RADIUS,RADIUS, - cd->col_value[sel_channel]+RADIUS,GRAPH_HEIGHT + RADIUS); - - /* and xpos indicator */ - g_snprintf (buf, sizeof (buf), "x:%d",cd->col_value[sel_channel]); - - if ((cd->col_value[sel_channel]+RADIUS) < 127) - { - offset = RADIUS + 4; - } - else - { - offset = - gdk_string_width (cd->graph->style->font,buf) - 2; - } - - gdk_draw_string (cd->pixmap, - cd->graph->style->font, - cd->graph->style->black_gc, - cd->col_value[sel_channel]+offset, - GRAPH_HEIGHT, - buf); - - gdk_draw_pixmap (cd->graph->window, cd->graph->style->black_gc, cd->pixmap, - 0, 0, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2); - - } -} - -static void -curves_plot_curve (CurvesDialog *cd, - gint p1, - gint p2, - gint p3, - gint p4) -{ - CRMatrix geometry; - CRMatrix tmp1, tmp2; - CRMatrix deltas; - gdouble x, dx, dx2, dx3; - gdouble y, dy, dy2, dy3; - gdouble d, d2, d3; - gint lastx, lasty; - gint32 newx, newy; - gint i; - - /* construct the geometry matrix from the segment */ - for (i = 0; i < 4; i++) - { - geometry[i][2] = 0; - geometry[i][3] = 0; - } - - for (i = 0; i < 2; i++) - { - geometry[0][i] = cd->points[cd->channel][p1][i]; - geometry[1][i] = cd->points[cd->channel][p2][i]; - geometry[2][i] = cd->points[cd->channel][p3][i]; - geometry[3][i] = cd->points[cd->channel][p4][i]; - } - - /* subdivide the curve 1000 times */ - /* n can be adjusted to give a finer or coarser curve */ - d = 1.0 / 1000; - d2 = d * d; - d3 = d * d * d; - - /* construct a temporary matrix for determining the forward differencing deltas */ - tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; - tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; - tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; - tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; - - /* compose the basis and geometry matrices */ - curves_CR_compose (CR_basis, geometry, tmp1); - - /* compose the above results to get the deltas matrix */ - curves_CR_compose (tmp2, tmp1, deltas); - - /* extract the x deltas */ - x = deltas[0][0]; - dx = deltas[1][0]; - dx2 = deltas[2][0]; - dx3 = deltas[3][0]; - - /* extract the y deltas */ - y = deltas[0][1]; - dy = deltas[1][1]; - dy2 = deltas[2][1]; - dy3 = deltas[3][1]; - - lastx = CLAMP (x, 0, 255); - lasty = CLAMP (y, 0, 255); - - cd->curve[cd->channel][lastx] = lasty; - - /* loop over the curve */ - for (i = 0; i < 1000; i++) - { - /* increment the x values */ - x += dx; - dx += dx2; - dx2 += dx3; - - /* increment the y values */ - y += dy; - dy += dy2; - dy2 += dy3; - - newx = CLAMP0255 (ROUND (x)); - newy = CLAMP0255 (ROUND (y)); - - /* if this point is different than the last one...then draw it */ - if ((lastx != newx) || (lasty != newy)) - cd->curve[cd->channel][newx] = newy; - - lastx = newx; - lasty = newy; - } -} - -void -curves_calculate_curve (CurvesDialog *cd) -{ - gint i; - gint points[17]; - gint num_pts; - gint p1, p2, p3, p4; - - switch (cd->curve_type[cd->channel]) - { - case GFREE: - break; - case SMOOTH: - /* cycle through the curves */ - num_pts = 0; - for (i = 0; i < 17; i++) - if (cd->points[cd->channel][i][0] != -1) - points[num_pts++] = i; - - /* Initialize boundary curve points */ - if (num_pts != 0) - { - for (i = 0; i < cd->points[cd->channel][points[0]][0]; i++) - cd->curve[cd->channel][i] = cd->points[cd->channel][points[0]][1]; - for (i = cd->points[cd->channel][points[num_pts - 1]][0]; i < 256; i++) - cd->curve[cd->channel][i] = cd->points[cd->channel][points[num_pts - 1]][1]; - } - - for (i = 0; i < num_pts - 1; i++) - { - p1 = (i == 0) ? points[i] : points[(i - 1)]; - p2 = points[i]; - p3 = points[(i + 1)]; - p4 = (i == (num_pts - 2)) ? points[(num_pts - 1)] : points[(i + 2)]; - - curves_plot_curve (cd, p1, p2, p3, p4); - } - break; - } - gimp_lut_setup (cd->lut, (GimpLutFunc) curves_lut_func, - (void *) cd, gimp_drawable_bytes (cd->drawable)); - -} - -static void -curves_preview (CurvesDialog *cd) -{ - if (!cd->image_map) - { - g_message ("curves_preview(): No image map"); - return; - } - - active_tool->preserve = TRUE; - image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, - (void *) cd->lut); - active_tool->preserve = FALSE; -} - -static void -curves_channel_callback (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - - cd = (CurvesDialog *) data; - - gimp_menu_item_update (widget, &cd->channel); - - if(!cd->color) { - if(cd->channel > 1) - { - cd->channel = 2; - } - else - { - cd->channel = 1; - } - } - - gtk_option_menu_set_history (GTK_OPTION_MENU (cd->curve_type_menu), - cd->curve_type[cd->channel]); - - curves_update (cd, XRANGE_TOP | YRANGE | GRAPH | DRAW); -} - -static void -curves_smooth_callback (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - gint i; - gint32 index; - - cd = (CurvesDialog *) data; - - if (cd->curve_type[cd->channel] != SMOOTH) - { - cd->curve_type[cd->channel] = SMOOTH; - - /* pick representative points from the curve and make them control points */ - for (i = 0; i <= 8; i++) - { - index = CLAMP0255 (i * 32); - cd->points[cd->channel][i * 2][0] = index; - cd->points[cd->channel][i * 2][1] = cd->curve[cd->channel][index]; - } - - curves_calculate_curve (cd); - curves_update (cd, GRAPH | DRAW); - - if (cd->preview) - curves_preview (cd); - } -} - -static void -curves_free_callback (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - - cd = (CurvesDialog *) data; - - if (cd->curve_type[cd->channel] != GFREE) - { - cd->curve_type[cd->channel] = GFREE; - curves_calculate_curve (cd); - curves_update (cd, GRAPH | DRAW); - - if (cd->preview) - curves_preview (cd); - } -} - -static void -curves_channel_reset (int i) -{ - gint j; - - curves_dialog->grab_point = -1; - - for (j = 0; j < 17; j++) - { - curves_dialog->points[i][j][0] = -1; - curves_dialog->points[i][j][1] = -1; - } - curves_dialog->points[i][0][0] = 0; - curves_dialog->points[i][0][1] = 0; - curves_dialog->points[i][16][0] = 255; - curves_dialog->points[i][16][1] = 255; -} - - -static void -curves_reset_callback (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - gint i; - - cd = (CurvesDialog *) data; - - /* Initialize the values */ - for (i = 0; i < 256; i++) - cd->curve[cd->channel][i] = i; - - curves_channel_reset (cd->channel); - - curves_calculate_curve (cd); - curves_update (cd, GRAPH | XRANGE_TOP | DRAW); - - if (cd->preview) - curves_preview (cd); -} - -static void -curves_ok_callback (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - - cd = (CurvesDialog *) data; - - gimp_dialog_hide (cd->shell); - - active_tool->preserve = TRUE; /* We're about to dirty... */ - - if (!cd->preview) - image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, - (void *) cd->lut); - - if (cd->image_map) - image_map_commit (cd->image_map); - - active_tool->preserve = FALSE; - - cd->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -curves_cancel_callback (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - - cd = (CurvesDialog *) data; - - gimp_dialog_hide (cd->shell); - - if (cd->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (cd->image_map); - active_tool->preserve = FALSE; - - gdisplays_flush (); - cd->image_map = NULL; - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -curves_load_callback (GtkWidget *widget, - gpointer data) -{ - if (!file_dlg) - file_dialog_create (GTK_WIDGET (data)); - else if (GTK_WIDGET_VISIBLE (file_dlg)) - return; - - load_save = TRUE; - - gtk_window_set_title (GTK_WINDOW (file_dlg), _("Load Curves")); - gtk_widget_show (file_dlg); -} - -static void -curves_save_callback (GtkWidget *widget, - gpointer data) -{ - if (!file_dlg) - file_dialog_create (GTK_WIDGET (data)); - else if (GTK_WIDGET_VISIBLE (file_dlg)) - return; - - load_save = FALSE; - - gtk_window_set_title (GTK_WINDOW (file_dlg), _("Save Curves")); - gtk_widget_show (file_dlg); -} - -static void -curves_preview_update (GtkWidget *widget, - gpointer data) -{ - CurvesDialog *cd; - - cd = (CurvesDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - cd->preview = TRUE; - curves_preview (cd); - } - else - { - cd->preview = FALSE; - if (cd->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (cd->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } -} - -static gint -curves_graph_events (GtkWidget *widget, - GdkEvent *event, - CurvesDialog *cd) -{ - static GdkCursorType cursor_type = GDK_TOP_LEFT_ARROW; - GdkCursorType new_type; - GdkEventButton *bevent; - GdkEventMotion *mevent; - gint i; - gint tx, ty; - gint x, y; - gint closest_point; - gint distance; - gint x1, x2, y1, y2; - - new_type = GDK_X_CURSOR; - closest_point = 0; - - /* get the pointer position */ - gdk_window_get_pointer (cd->graph->window, &tx, &ty, NULL); - x = CLAMP ((tx - RADIUS), 0, 255); - y = CLAMP ((ty - RADIUS), 0, 255); - - distance = G_MAXINT; - for (i = 0; i < 17; i++) - { - if (cd->points[cd->channel][i][0] != -1) - if (abs (x - cd->points[cd->channel][i][0]) < distance) - { - distance = abs (x - cd->points[cd->channel][i][0]); - closest_point = i; - } - } - if (distance > MIN_DISTANCE) - closest_point = (x + 8) / 16; - - switch (event->type) - { - case GDK_EXPOSE: - if (cd->pixmap == NULL) - cd->pixmap = gdk_pixmap_new (cd->graph->window, - GRAPH_WIDTH + RADIUS * 2, - GRAPH_HEIGHT + RADIUS * 2, -1); - - curves_update (cd, GRAPH | DRAW); - break; - - case GDK_BUTTON_PRESS: - bevent = (GdkEventButton *) event; - new_type = GDK_TCROSS; - - switch (cd->curve_type[cd->channel]) - { - case SMOOTH: - /* determine the leftmost and rightmost points */ - cd->leftmost = -1; - for (i = closest_point - 1; i >= 0; i--) - if (cd->points[cd->channel][i][0] != -1) - { - cd->leftmost = cd->points[cd->channel][i][0]; - break; - } - cd->rightmost = 256; - for (i = closest_point + 1; i < 17; i++) - if (cd->points[cd->channel][i][0] != -1) - { - cd->rightmost = cd->points[cd->channel][i][0]; - break; - } - - cd->grab_point = closest_point; - cd->points[cd->channel][cd->grab_point][0] = x; - cd->points[cd->channel][cd->grab_point][1] = 255 - y; - - break; - - case GFREE: - cd->curve[cd->channel][x] = 255 - y; - cd->grab_point = x; - cd->last = y; - break; - } - - curves_calculate_curve (cd); - curves_update (cd, GRAPH | XRANGE_TOP | DRAW); - gtk_grab_add (widget); - - break; - - case GDK_BUTTON_RELEASE: - new_type = GDK_FLEUR; - cd->grab_point = -1; - - if (cd->preview) - curves_preview (cd); - - gtk_grab_remove (widget); - - break; - - case GDK_MOTION_NOTIFY: - mevent = (GdkEventMotion *) event; - - if (mevent->is_hint) - { - mevent->x = tx; - mevent->y = ty; - } - - switch (cd->curve_type[cd->channel]) - { - case SMOOTH: - /* If no point is grabbed... */ - if (cd->grab_point == -1) - { - if (cd->points[cd->channel][closest_point][0] != -1) - new_type = GDK_FLEUR; - else - new_type = GDK_TCROSS; - } - /* Else, drag the grabbed point */ - else - { - new_type = GDK_TCROSS; - - cd->points[cd->channel][cd->grab_point][0] = -1; - - if (x > cd->leftmost && x < cd->rightmost) - { - closest_point = (x + 8) / 16; - if (cd->points[cd->channel][closest_point][0] == -1) - cd->grab_point = closest_point; - cd->points[cd->channel][cd->grab_point][0] = x; - cd->points[cd->channel][cd->grab_point][1] = 255 - y; - } - - curves_calculate_curve (cd); - curves_update (cd, GRAPH | XRANGE_TOP | DRAW); - } - break; - - case GFREE: - if (cd->grab_point != -1) - { - if (cd->grab_point > x) - { - x1 = x; - x2 = cd->grab_point; - y1 = y; - y2 = cd->last; - } - else - { - x1 = cd->grab_point; - x2 = x; - y1 = cd->last; - y2 = y; - } - - if (x2 != x1) - for (i = x1; i <= x2; i++) - cd->curve[cd->channel][i] = 255 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1)); - else - cd->curve[cd->channel][x] = 255 - y; - - cd->grab_point = x; - cd->last = y; - - curves_update (cd, GRAPH | XRANGE_TOP | DRAW); - } - - if (mevent->state & GDK_BUTTON1_MASK) - new_type = GDK_TCROSS; - else - new_type = GDK_PENCIL; - break; - } - - if (new_type != cursor_type) - { - cursor_type = new_type; - change_win_cursor (cd->graph->window, cursor_type, - TOOL_TYPE_NONE, CURSOR_MODIFIER_NONE, FALSE); - } - - curve_print_loc (cd, x, 255 - y); - - break; - - default: - break; - } - - return FALSE; -} - -static gint -curves_xrange_events (GtkWidget *widget, - GdkEvent *event, - CurvesDialog *cd) -{ - switch (event->type) - { - case GDK_EXPOSE: - curves_update (cd, XRANGE_TOP | XRANGE_BOTTOM); - break; - - case GDK_DELETE: - break; - - default: - break; - } - - return FALSE; -} - -static gint -curves_yrange_events (GtkWidget *widget, - GdkEvent *event, - CurvesDialog *cd) -{ - switch (event->type) - { - case GDK_EXPOSE: - curves_update (cd, YRANGE); - break; - - default: - break; - } - - return FALSE; -} - -static void -curves_CR_compose (CRMatrix a, - CRMatrix b, - CRMatrix ab) -{ - gint i, j; - - for (i = 0; i < 4; i++) - { - for (j = 0; j < 4; j++) - { - ab[i][j] = (a[i][0] * b[0][j] + - a[i][1] * b[1][j] + - a[i][2] * b[2][j] + - a[i][3] * b[3][j]); - } - } -} - - -static void -file_dialog_create (GtkWidget *parent) -{ - gchar *temp; - - file_dlg = gtk_file_selection_new (_("Load/Save Curves")); - gtk_window_set_wmclass (GTK_WINDOW (file_dlg), "load_save_curves", "Gimp"); - gtk_window_set_position (GTK_WINDOW (file_dlg), GTK_WIN_POS_MOUSE); - - gtk_container_set_border_width (GTK_CONTAINER (file_dlg), 2); - gtk_container_set_border_width (GTK_CONTAINER (GTK_FILE_SELECTION (file_dlg)->button_area), 2); - - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->cancel_button), - "clicked", GTK_SIGNAL_FUNC (file_dialog_cancel_callback), - NULL); - gtk_signal_connect (GTK_OBJECT (file_dlg), "delete_event", - GTK_SIGNAL_FUNC (file_dialog_cancel_callback), - NULL); - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->ok_button), - "clicked", GTK_SIGNAL_FUNC (file_dialog_ok_callback), - NULL); - - gtk_signal_connect (GTK_OBJECT (parent), "unmap", - GTK_SIGNAL_FUNC (file_dialog_cancel_callback), - NULL); - - temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "curves" G_DIR_SEPARATOR_S, - gimp_directory ()); - gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_dlg), temp); - g_free (temp); - - gimp_help_connect_help_accel (file_dlg, tools_help_func, - tool_info[CURVES].private_tip); -} - -static void -file_dialog_ok_callback (GtkWidget *widget, - gpointer data) -{ - FILE *f; - gchar *filename; - - filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_dlg)); - - if (load_save) - { - f = fopen (filename, "rt"); - - if (!f) - { - g_message (_("Unable to open file %s"), filename); - return; - } - - if (!curves_read_from_file (f)) - { - g_message (("Error in reading file %s"), filename); - return; - } - - fclose (f); - } - else - { - f = fopen (filename, "wt"); - - if (!f) - { - g_message (_("Unable to open file %s"), filename); - return; - } - - curves_write_to_file (f); - - fclose (f); - } - - file_dialog_cancel_callback (file_dlg, NULL); -} - -static void -file_dialog_cancel_callback (GtkWidget *widget, - gpointer data) -{ - gimp_dialog_hide (file_dlg); -} - -static gboolean -curves_read_from_file (FILE *f) -{ - gint i, j; - gint fields; - gchar buf[50]; - gint index[5][17]; - gint value[5][17]; - gint current_channel; - - if (!fgets (buf, 50, f)) - return FALSE; - - if (strcmp (buf, "# GIMP Curves File\n") != 0) - return FALSE; - - for (i = 0; i < 5; i++) - { - for (j = 0; j < 17; j++) - { - fields = fscanf (f, "%d %d ", &index[i][j], &value[i][j]); - if (fields != 2) - { - g_print ("fields != 2"); - return FALSE; - } - } - } - - for (i = 0; i < 5; i++) - { - curves_dialog->curve_type[i] = SMOOTH; - for (j = 0; j < 17; j++) - { - curves_dialog->points[i][j][0] = index[i][j]; - curves_dialog->points[i][j][1] = value[i][j]; - } - } - - /* this is ugly, but works ... */ - current_channel = curves_dialog->channel; - for (i = 0; i < 5; i++) - { - curves_dialog->channel = i; - curves_calculate_curve (curves_dialog); - } - curves_dialog->channel = current_channel; - - curves_update (curves_dialog, ALL); - gtk_option_menu_set_history (GTK_OPTION_MENU (curves_dialog->curve_type_menu), - SMOOTH); - - if (curves_dialog->preview) - curves_preview (curves_dialog); - - return TRUE; -} - -static void -curves_write_to_file (FILE *f) -{ - gint i, j; - gint32 index; - - for (i = 0; i < 5; i++) - if (curves_dialog->curve_type[i] == GFREE) - { - /* pick representative points from the curve and make them control points */ - for (j = 0; j <= 8; j++) - { - index = CLAMP0255 (j * 32); - curves_dialog->points[i][j * 2][0] = index; - curves_dialog->points[i][j * 2][1] = curves_dialog->curve[i][index]; - } - } - - fprintf (f, "# GIMP Curves File\n"); - - for (i = 0; i < 5; i++) - { - for (j = 0; j < 17; j++) - fprintf (f, "%d %d ", curves_dialog->points[i][j][0], - curves_dialog->points[i][j][1]); - - fprintf (f, "\n"); - } -} - diff --git a/app/curves.h b/app/curves.h deleted file mode 100644 index d209de2d82..0000000000 --- a/app/curves.h +++ /dev/null @@ -1,76 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __CURVES_H__ -#define __CURVES_H__ - - -#define SMOOTH 0 -#define GFREE 1 - - -typedef struct _CurvesDialog CurvesDialog; - -struct _CurvesDialog -{ - GtkWidget *shell; - - GtkWidget *channel_menu; - GtkWidget *xrange; - GtkWidget *yrange; - GtkWidget *graph; - GdkPixmap *pixmap; - GtkWidget *curve_type_menu; - - GimpDrawable *drawable; - ImageMap image_map; - - gint color; - gint channel; - gboolean preview; - - gint grab_point; - gint last; - gint leftmost; - gint rightmost; - gint curve_type[5]; - gint points[5][17][2]; - guchar curve[5][256]; - gint col_value[5]; - - gint cursor_ind_height; - gint cursor_ind_width; - gint cursor_ind_ascent; - - GimpLut *lut; -}; - -Tool * tools_new_curves (void); -void tools_free_curves (Tool *tool); - -void curves_dialog_hide (void); -void curves_initialize (GDisplay *gdisp); -void curves_free (void); -gfloat curves_lut_func (CurvesDialog *cd, - gint nchannels, - gint channel, - gfloat value); -void curves_calculate_curve (CurvesDialog *cd); - - -#endif /* __CURVES_H__ */ diff --git a/app/devices.c b/app/devices.c index 86d07ec8d9..3f7f2e91f6 100644 --- a/app/devices.c +++ b/app/devices.c @@ -39,7 +39,8 @@ #include "gradient_header.h" #include "patterns.h" #include "session.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/dialogs/info-window.c b/app/dialogs/info-window.c index a5179d9ca7..478fe313bb 100644 --- a/app/dialogs/info-window.c +++ b/app/dialogs/info-window.c @@ -34,7 +34,8 @@ #include "info_dialog.h" #include "info_window.h" #include "scroll.h" -#include "tools.h" + +#include "tools/tools.h" #include "pdb/procedural_db.h" diff --git a/app/disp_callbacks.c b/app/disp_callbacks.c index 577c80f91b..0ae09082c8 100644 --- a/app/disp_callbacks.c +++ b/app/disp_callbacks.c @@ -26,7 +26,6 @@ #include "apptypes.h" #include "appenv.h" -#include "bucket_fill.h" #include "cursorutil.h" #include "devices.h" #include "dialog_handler.h" @@ -39,7 +38,6 @@ #include "info_window.h" #include "layer.h" #include "layer_select.h" -#include "move.h" #include "paint_funcs.h" #include "patterns.h" #include "pixel_region.h" @@ -48,9 +46,12 @@ #include "selection.h" #include "temp_buf.h" #include "tile_manager.h" -#include "tools.h" #include "undo.h" +#include "tools/bucket_fill.h" +#include "tools/move.h" +#include "tools/tools.h" + #include "libgimp/gimpintl.h" diff --git a/app/display/gimpdisplay-callbacks.c b/app/display/gimpdisplay-callbacks.c index 577c80f91b..0ae09082c8 100644 --- a/app/display/gimpdisplay-callbacks.c +++ b/app/display/gimpdisplay-callbacks.c @@ -26,7 +26,6 @@ #include "apptypes.h" #include "appenv.h" -#include "bucket_fill.h" #include "cursorutil.h" #include "devices.h" #include "dialog_handler.h" @@ -39,7 +38,6 @@ #include "info_window.h" #include "layer.h" #include "layer_select.h" -#include "move.h" #include "paint_funcs.h" #include "patterns.h" #include "pixel_region.h" @@ -48,9 +46,12 @@ #include "selection.h" #include "temp_buf.h" #include "tile_manager.h" -#include "tools.h" #include "undo.h" +#include "tools/bucket_fill.h" +#include "tools/move.h" +#include "tools/tools.h" + #include "libgimp/gimpintl.h" diff --git a/app/display/gimpdisplay-scale.c b/app/display/gimpdisplay-scale.c index f1d8c5763c..a88a56fc53 100644 --- a/app/display/gimpdisplay-scale.c +++ b/app/display/gimpdisplay-scale.c @@ -31,7 +31,8 @@ #include "gimprc.h" #include "nav_window.h" #include "scale.h" -#include "tools.h" + +#include "tools/tools.h" void diff --git a/app/display/gimpdisplay-scroll.c b/app/display/gimpdisplay-scroll.c index 9f9526beb9..7b753ffaa0 100644 --- a/app/display/gimpdisplay-scroll.c +++ b/app/display/gimpdisplay-scroll.c @@ -30,7 +30,8 @@ #include "scale.h" #include "scroll.h" #include "nav_window.h" -#include "tools.h" + +#include "tools/tools.h" /* This is the delay before dithering begins diff --git a/app/display/gimpdisplay.c b/app/display/gimpdisplay.c index 0cc5dca17d..651d77360d 100644 --- a/app/display/gimpdisplay.c +++ b/app/display/gimpdisplay.c @@ -51,7 +51,6 @@ #include "scale.h" #include "scroll.h" #include "selection.h" -#include "tools.h" #include "undo.h" @@ -59,7 +58,8 @@ #include "gdisplay_color.h" #endif /* DISPLAY_FILTERS */ -#include "bezier_selectP.h" +#include "tools/bezier_selectP.h" +#include "tools/tools.h" #include "libgimp/gimpmath.h" diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c index 577c80f91b..0ae09082c8 100644 --- a/app/display/gimpdisplayshell-callbacks.c +++ b/app/display/gimpdisplayshell-callbacks.c @@ -26,7 +26,6 @@ #include "apptypes.h" #include "appenv.h" -#include "bucket_fill.h" #include "cursorutil.h" #include "devices.h" #include "dialog_handler.h" @@ -39,7 +38,6 @@ #include "info_window.h" #include "layer.h" #include "layer_select.h" -#include "move.h" #include "paint_funcs.h" #include "patterns.h" #include "pixel_region.h" @@ -48,9 +46,12 @@ #include "selection.h" #include "temp_buf.h" #include "tile_manager.h" -#include "tools.h" #include "undo.h" +#include "tools/bucket_fill.h" +#include "tools/move.h" +#include "tools/tools.h" + #include "libgimp/gimpintl.h" diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 40c5dab1fe..89eb1d20dc 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -54,7 +54,8 @@ #include "session.h" #include "pixel_region.h" #include "tile_manager.h" -#include "tools.h" + +#include "tools/tools.h" #include "pixmaps.h" #include "pixmaps/qmasksel.xpm" diff --git a/app/display/gimpdisplayshell-scale.c b/app/display/gimpdisplayshell-scale.c index f1d8c5763c..a88a56fc53 100644 --- a/app/display/gimpdisplayshell-scale.c +++ b/app/display/gimpdisplayshell-scale.c @@ -31,7 +31,8 @@ #include "gimprc.h" #include "nav_window.h" #include "scale.h" -#include "tools.h" + +#include "tools/tools.h" void diff --git a/app/display/gimpdisplayshell-scroll.c b/app/display/gimpdisplayshell-scroll.c index 9f9526beb9..7b753ffaa0 100644 --- a/app/display/gimpdisplayshell-scroll.c +++ b/app/display/gimpdisplayshell-scroll.c @@ -30,7 +30,8 @@ #include "scale.h" #include "scroll.h" #include "nav_window.h" -#include "tools.h" + +#include "tools/tools.h" /* This is the delay before dithering begins diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 40c5dab1fe..89eb1d20dc 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -54,7 +54,8 @@ #include "session.h" #include "pixel_region.h" #include "tile_manager.h" -#include "tools.h" + +#include "tools/tools.h" #include "pixmaps.h" #include "pixmaps/qmasksel.xpm" diff --git a/app/dodgeburn.c b/app/dodgeburn.c deleted file mode 100644 index 70afb35281..0000000000 --- a/app/dodgeburn.c +++ /dev/null @@ -1,667 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "dodgeburn.h" -#include "gdisplay.h" -#include "gimplut.h" -#include "gimpcontext.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "pixel_region.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" -#include "gimage.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* Default values */ - -#define DODGEBURN_DEFAULT_TYPE DODGE -#define DODGEBURN_DEFAULT_EXPOSURE 50.0 -#define DODGEBURN_DEFAULT_MODE DODGEBURN_HIGHLIGHTS - -/* the dodgeburn structures */ - -typedef struct _DodgeBurnOptions DodgeBurnOptions; - -struct _DodgeBurnOptions -{ - PaintOptions paint_options; - - DodgeBurnType type; - DodgeBurnType type_d; - GtkWidget *type_w[2]; - - DodgeBurnMode mode; /*highlights, midtones, shadows*/ - DodgeBurnMode mode_d; - GtkWidget *mode_w[3]; - - gdouble exposure; - gdouble exposure_d; - GtkObject *exposure_w; - - GimpLut *lut; -}; - - -static gpointer dodgeburn_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); - -static void dodgeburn_make_luts (PaintCore *paint_cure, - gdouble db_exposure, - DodgeBurnType type, - DodgeBurnMode mode, - GimpLut *lut, - GimpDrawable *drawable); - -static gfloat dodgeburn_highlights_lut_func (gpointer user_data, - gint nchannels, - gint channel, - gfloat value); -static gfloat dodgeburn_midtones_lut_func (gpointer user_data, - gint nchannels, - gint channel, - gfloat value); -static gfloat dodgeburn_shadows_lut_func (gpointer user_data, - gint nchannels, - gint channel, - gfloat value); - -static void dodgeburn_motion (PaintCore *paint_core, - PaintPressureOptions *pressure_options, - gdouble dodgeburn_exposure, - GimpLut *lut, - GimpDrawable *drawable); -static void dodgeburn_init (PaintCore *paint_cure, - GimpDrawable *drawable); -static void dodgeburn_finish (PaintCore *paint_core, - GimpDrawable *drawable); - - -/* the dodgeburn tool options */ -static DodgeBurnOptions * dodgeburn_options = NULL; - -/* Non gui function */ -static gdouble non_gui_exposure; -static GimpLut *non_gui_lut; - - -/* functions */ - -static void -dodgeburn_options_reset (void) -{ - DodgeBurnOptions *options = dodgeburn_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->exposure_w), - options->exposure_d); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->mode_w[options->mode_d]), TRUE); -} - -static DodgeBurnOptions * -dodgeburn_options_new (void) -{ - DodgeBurnOptions *options; - - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *scale; - GtkWidget *frame; - - /* the new dodgeburn tool options structure */ - options = g_new (DodgeBurnOptions, 1); - paint_options_init ((PaintOptions *) options, - DODGEBURN, - dodgeburn_options_reset); - - options->type = options->type_d = DODGEBURN_DEFAULT_TYPE; - options->exposure = options->exposure_d = DODGEBURN_DEFAULT_EXPOSURE; - options->mode = options->mode_d = DODGEBURN_DEFAULT_MODE; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* the exposure scale */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Exposure:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - options->exposure_w = - gtk_adjustment_new (options->exposure_d, 0.0, 100.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->exposure_w)); - gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - - gtk_signal_connect (GTK_OBJECT (options->exposure_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->exposure); - - gtk_widget_show (scale); - gtk_widget_show (hbox); - - /* the type (dodge or burn) */ - frame = gimp_radio_group_new2 (TRUE, _("Type"), - gimp_radio_button_update, - &options->type, (gpointer) options->type, - - _("Dodge"), (gpointer) DODGE, - &options->type_w[0], - _("Burn"), (gpointer) BURN, - &options->type_w[1], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - /* mode (highlights, midtones, or shadows) */ - frame = - gimp_radio_group_new2 (TRUE, _("Mode"), - gimp_radio_button_update, - &options->mode, (gpointer) options->mode, - - _("Highlights"), (gpointer) DODGEBURN_HIGHLIGHTS, - &options->mode_w[0], - _("Midtones"), (gpointer) DODGEBURN_MIDTONES, - &options->mode_w[1], - _("Shadows"), (gpointer) DODGEBURN_SHADOWS, - &options->mode_w[2], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -static gpointer -dodgeburn_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - switch (state) - { - case INIT_PAINT: - dodgeburn_init (paint_core, drawable); - break; - - case MOTION_PAINT: - dodgeburn_motion (paint_core, - dodgeburn_options->paint_options.pressure_options, - dodgeburn_options->exposure, dodgeburn_options->lut, drawable); - break; - - case FINISH_PAINT: - dodgeburn_finish (paint_core, drawable); - break; - - default: - break; - } - - return NULL; -} - -static void -dodgeburn_finish (PaintCore *paint_core, - GimpDrawable *drawable) -{ - /* Here we destroy the luts to do the painting with.*/ - if (dodgeburn_options->lut) - { - gimp_lut_free (dodgeburn_options->lut); - dodgeburn_options->lut = NULL; - } -} - -static void -dodgeburn_init (PaintCore *paint_core, - GimpDrawable *drawable) -{ - /* Here we create the luts to do the painting with.*/ - dodgeburn_options->lut = gimp_lut_new (); - - dodgeburn_make_luts (paint_core, - dodgeburn_options->exposure, - dodgeburn_options->type, - dodgeburn_options->mode, - dodgeburn_options->lut, - drawable); -} - -static void -dodgeburn_make_luts (PaintCore *paint_core, - gdouble db_exposure, - DodgeBurnType type, - DodgeBurnMode mode, - GimpLut *lut, - GimpDrawable *drawable) -{ - GimpLutFunc lut_func; - gint nchannels = gimp_drawable_bytes (drawable); - static gfloat exposure; - - exposure = db_exposure / 100.0; - - /* make the exposure negative if burn for luts*/ - if (type == BURN) - exposure = -exposure; - - switch (mode) - { - case DODGEBURN_HIGHLIGHTS: - lut_func = dodgeburn_highlights_lut_func; - break; - case DODGEBURN_MIDTONES: - lut_func = dodgeburn_midtones_lut_func; - break; - case DODGEBURN_SHADOWS: - lut_func = dodgeburn_shadows_lut_func; - break; - default: - lut_func = NULL; - break; - } - - gimp_lut_setup_exact (lut, - lut_func, (gpointer) &exposure, - nchannels); -} - -static void -dodgeburn_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: - case GDK_Alt_R: - break; - case GDK_Shift_L: - case GDK_Shift_R: - if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */ - { - switch (dodgeburn_options->type) - { - case BURN: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[DODGE]), TRUE); - break; - case DODGE: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[BURN]), TRUE); - break; - default: - break; - } - } - break; - case GDK_Control_L: - case GDK_Control_R: - if (! (kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */ - { - switch (dodgeburn_options->type) - { - case BURN: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[DODGE]), TRUE); - break; - case DODGE: - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[BURN]), TRUE); - break; - default: - break; - } - } - break; - } - - tool->toggled = (dodgeburn_options->type == BURN); -} - -static void -dodgeburn_cursor_update_func (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - tool->toggled = (dodgeburn_options->type == BURN); - - paint_core_cursor_update (tool, mevent, gdisp); -} - -Tool * -tools_new_dodgeburn (void) -{ - Tool *tool; - PaintCore *private; - - /* The tool options */ - if (! dodgeburn_options) - { - dodgeburn_options = dodgeburn_options_new (); - tools_register (DODGEBURN, (ToolOptions *) dodgeburn_options); - - /* press all default buttons */ - dodgeburn_options_reset (); - } - - tool = paint_core_new (DODGEBURN); - tool->modifier_key_func = dodgeburn_modifier_key_func; - tool->cursor_update_func = dodgeburn_cursor_update_func; - - private = (PaintCore *) tool->private; - private->paint_func = dodgeburn_paint_func; - private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - - return tool; -} - -void -tools_free_dodgeburn (Tool *tool) -{ - /* delete any luts here */ - paint_core_free (tool); -} - -static void -dodgeburn_motion (PaintCore *paint_core, - PaintPressureOptions *pressure_options, - double dodgeburn_exposure, - GimpLut *lut, - GimpDrawable *drawable) -{ - GImage *gimage; - TempBuf * area; - TempBuf * orig; - PixelRegion srcPR, destPR, tempPR; - guchar *temp_data; - gint opacity; - gdouble scale; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - /* If the image type is indexed, don't dodgeburn */ - if ((gimp_drawable_type (drawable) == INDEXED_GIMAGE) || - (gimp_drawable_type (drawable) == INDEXEDA_GIMAGE)) - return; - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - /* Get a region which can be used to paint to */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - /* Constant painting --get a copy of the orig drawable (with - no paint from this stroke yet) */ - - { - gint x1, y1, x2, y2; - - x1 = CLAMP (area->x, 0, gimp_drawable_width (drawable)); - y1 = CLAMP (area->y, 0, gimp_drawable_height (drawable)); - x2 = CLAMP (area->x + area->width, 0, gimp_drawable_width (drawable)); - y2 = CLAMP (area->y + area->height, 0, gimp_drawable_height (drawable)); - - if (!(x2 - x1) || !(y2 - y1)) - return; - - /* get the original untouched image */ - orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2); - srcPR.bytes = orig->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = x2 - x1; - srcPR.h = y2 - y1; - srcPR.rowstride = srcPR.bytes * orig->width; - srcPR.data = temp_buf_data (orig); - } - - /* tempPR will hold the dodgeburned region*/ - tempPR.bytes = srcPR.bytes; - tempPR.x = srcPR.x; - tempPR.y = srcPR.y; - tempPR.w = srcPR.w; - tempPR.h = srcPR.h; - tempPR.rowstride = tempPR.bytes * tempPR.w; - temp_data = g_malloc (tempPR.h * tempPR.rowstride); - tempPR.data = temp_data; - - /* DodgeBurn the region */ - gimp_lut_process (lut, &srcPR, &tempPR); - - /* The dest is the paint area we got above (= canvas_buf) */ - destPR.bytes = area->bytes; - destPR.x = 0; destPR.y = 0; - destPR.w = area->width; - destPR.h = area->height; - destPR.rowstride = area->width * destPR.bytes; - destPR.data = temp_buf_data (area); - - /* Now add an alpha to the dodgeburned region - and put this in area = canvas_buf */ - if (! gimp_drawable_has_alpha (drawable)) - add_alpha_region (&tempPR, &destPR); - else - copy_region (&tempPR, &destPR); - - opacity = 255 * gimp_context_get_opacity (NULL); - if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; - - /* Replace the newly dodgedburned area (canvas_buf) to the gimage*/ - paint_core_replace_canvas (paint_core, drawable, - MIN (opacity, 255), - OPAQUE_OPACITY, - pressure_options->pressure ? PRESSURE : SOFT, - scale, CONSTANT); - - g_free (temp_data); -} - -static gpointer -dodgeburn_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - dodgeburn_motion (paint_core, &non_gui_pressure_options, - non_gui_exposure, non_gui_lut, drawable); - - return NULL; -} - -gboolean -dodgeburn_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array) -{ - gdouble exposure = DODGEBURN_DEFAULT_TYPE; - DodgeBurnType type = DODGEBURN_DEFAULT_TYPE; - DodgeBurnMode mode = DODGEBURN_DEFAULT_MODE; - DodgeBurnOptions *options = dodgeburn_options; - - if (options) - { - exposure = dodgeburn_options->exposure; - type = dodgeburn_options->type; - mode = dodgeburn_options->mode; - } - - return dodgeburn_non_gui (drawable, exposure, type, mode, - num_strokes, stroke_array); -} - -gboolean -dodgeburn_non_gui (GimpDrawable *drawable, - gdouble exposure, - DodgeBurnType type, - DodgeBurnMode mode, - gint num_strokes, - gdouble *stroke_array) -{ - gint i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = dodgeburn_non_gui_paint_func; - - non_gui_exposure = exposure; - non_gui_lut = gimp_lut_new(); - dodgeburn_make_luts (&non_gui_paint_core, - exposure, - type, - mode, - non_gui_lut, - drawable); - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - dodgeburn_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - - gimp_lut_free (non_gui_lut); - - return TRUE; - } - else - return FALSE; -} - -static gfloat -dodgeburn_highlights_lut_func (gpointer user_data, - gint nchannels, - gint channel, - gfloat value) -{ - gfloat *exposure_ptr = (gfloat *) user_data; - gfloat exposure = *exposure_ptr; - gfloat factor = 1.0 + exposure * (.333333); - - if ((nchannels == 2 && channel == 1) || - (nchannels == 4 && channel == 3)) - return value; - - return factor * value; -} - -static gfloat -dodgeburn_midtones_lut_func (gpointer user_data, - gint nchannels, - gint channel, - gfloat value) -{ - gfloat *exposure_ptr = (gfloat *) user_data; - gfloat exposure = *exposure_ptr; - gfloat factor; - - if ((nchannels == 2 && channel == 1) || - (nchannels == 4 && channel == 3)) - return value; - - if (exposure < 0) - factor = 1.0 - exposure * (.333333); - else - factor = 1/(1.0 + exposure); - - return pow (value, factor); -} - -static gfloat -dodgeburn_shadows_lut_func (gpointer user_data, - gint nchannels, - gint channel, - gfloat value) -{ - gfloat *exposure_ptr = (gfloat *) user_data; - gfloat exposure = *exposure_ptr; - gfloat new_value; - gfloat factor; - - if ( (nchannels == 2 && channel == 1) || - (nchannels == 4 && channel == 3)) - return value; - - if (exposure >= 0) - { - factor = 0.333333 * exposure; - new_value = factor + value - factor * value; - } - else /* exposure < 0 */ - { - factor = -0.333333 * exposure; - if (value < factor) - new_value = 0; - else /*factor <= value <=1*/ - new_value = (value - factor)/(1 - factor); - } - - return new_value; -} diff --git a/app/dodgeburn.h b/app/dodgeburn.h deleted file mode 100644 index edd02ba64d..0000000000 --- a/app/dodgeburn.h +++ /dev/null @@ -1,51 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __DODGEBURN_H__ -#define __DODGEBURN_H__ - - -typedef enum -{ - DODGE, - BURN -} DodgeBurnType; - -typedef enum -{ - DODGEBURN_HIGHLIGHTS, - DODGEBURN_MIDTONES, - DODGEBURN_SHADOWS -} DodgeBurnMode; - - -gboolean dodgeburn_non_gui (GimpDrawable *drawable, - gdouble exposure, - DodgeBurnType type, - DodgeBurnMode mode, - gint num_strokes, - gdouble *stroke_array); -gboolean dodgeburn_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array); - -Tool * tools_new_dodgeburn (void); -void tools_free_dodgeburn (Tool *tool); - - -#endif /* __DODGEBURN_H__ */ diff --git a/app/edit_selection.c b/app/edit_selection.c index e7c25486cb..ee6be297fc 100644 --- a/app/edit_selection.c +++ b/app/edit_selection.c @@ -31,7 +31,6 @@ #include "cursorutil.h" #include "draw_core.h" #include "drawable.h" -#include "tools.h" #include "edit_selection.h" #include "floating_sel.h" #include "gimpimage.h" @@ -43,6 +42,8 @@ #include "selection.h" #include "undo.h" +#include "tools/tools.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpintl.h" diff --git a/app/ellipse_select.c b/app/ellipse_select.c deleted file mode 100644 index a4235d237a..0000000000 --- a/app/ellipse_select.c +++ /dev/null @@ -1,165 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "channel.h" -#include "draw_core.h" -#include "edit_selection.h" -#include "ellipse_select.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "rect_select.h" -#include "rect_selectP.h" -#include "selection_options.h" -#include "tools.h" -#include "tool_options.h" - - -/* the ellipse selection tool options */ -SelectionOptions * ellipse_options = NULL; - - -/*************************************/ -/* Ellipsoidal selection apparatus */ - -void -ellipse_select (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius) -{ - Channel *new_mask; - - /* if applicable, replace the current selection */ - if (op == SELECTION_REPLACE) - gimage_mask_clear (gimage); - else - gimage_mask_undo (gimage); - - /* if feathering for rect, make a new mask with the - * rectangle and feather that with the old mask - */ - if (feather) - { - new_mask = channel_new_mask (gimage, gimage->width, gimage->height); - channel_combine_ellipse (new_mask, CHANNEL_OP_ADD, x, y, w, h, antialias); - channel_feather (new_mask, gimp_image_get_mask (gimage), - feather_radius, - feather_radius, - op, 0, 0); - channel_delete (new_mask); - } - else if (op == SELECTION_INTERSECT) - { - new_mask = channel_new_mask (gimage, gimage->width, gimage->height); - channel_combine_ellipse (new_mask, CHANNEL_OP_ADD, x, y, w, h, antialias); - channel_combine_mask (gimp_image_get_mask (gimage), new_mask, op, 0, 0); - channel_delete (new_mask); - } - else - channel_combine_ellipse (gimp_image_get_mask (gimage), op, - x, y, w, h, antialias); -} - -void -ellipse_select_draw (Tool *tool) -{ - EllipseSelect *ellipse_sel; - gint x1, y1; - gint x2, y2; - - ellipse_sel = (EllipseSelect *) tool->private; - - x1 = MIN (ellipse_sel->x, ellipse_sel->x + ellipse_sel->w); - y1 = MIN (ellipse_sel->y, ellipse_sel->y + ellipse_sel->h); - x2 = MAX (ellipse_sel->x, ellipse_sel->x + ellipse_sel->w); - y2 = MAX (ellipse_sel->y, ellipse_sel->y + ellipse_sel->h); - - gdisplay_transform_coords (tool->gdisp, x1, y1, &x1, &y1, 0); - gdisplay_transform_coords (tool->gdisp, x2, y2, &x2, &y2, 0); - - gdk_draw_arc (ellipse_sel->core->win, - ellipse_sel->core->gc, 0, - x1, y1, (x2 - x1), (y2 - y1), 0, 23040); -} - -static void -ellipse_select_options_reset (void) -{ - selection_options_reset (ellipse_options); -} - -Tool * -tools_new_ellipse_select (void) -{ - Tool *tool; - EllipseSelect *private; - - /* The tool options */ - if (!ellipse_options) - { - ellipse_options = - selection_options_new (ELLIPSE_SELECT, ellipse_select_options_reset); - tools_register (ELLIPSE_SELECT, (ToolOptions *) ellipse_options); - } - - tool = tools_new_tool (ELLIPSE_SELECT); - private = g_new0 (EllipseSelect, 1); - - private->core = draw_core_new (ellipse_select_draw); - /* Make the selection static, not blinking */ - private->x = private->y = 0; - private->w = private->h = 0; - - tool->private = (void *) private; - - tool->button_press_func = rect_select_button_press; - tool->button_release_func = rect_select_button_release; - tool->motion_func = rect_select_motion; - tool->modifier_key_func = rect_select_modifier_update; - tool->cursor_update_func = rect_select_cursor_update; - tool->oper_update_func = rect_select_oper_update; - tool->control_func = rect_select_control; - - return tool; -} - -void -tools_free_ellipse_select (Tool *tool) -{ - EllipseSelect *ellipse_sel; - - ellipse_sel = (EllipseSelect *) tool->private; - - draw_core_free (ellipse_sel->core); - g_free (ellipse_sel); -} diff --git a/app/ellipse_select.h b/app/ellipse_select.h deleted file mode 100644 index cce7e01273..0000000000 --- a/app/ellipse_select.h +++ /dev/null @@ -1,38 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __ELLIPSE_SELECT_H__ -#define __ELLIPSE_SELECT_H__ - - -void ellipse_select (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius); -void ellipse_select_draw (Tool *tool); - -Tool * tools_new_ellipse_select (void); -void tools_free_ellipse_select (Tool *tool); - - -#endif /* __ELLIPSE_SELECT_H__ */ diff --git a/app/eraser.c b/app/eraser.c deleted file mode 100644 index cf4b2477ec..0000000000 --- a/app/eraser.c +++ /dev/null @@ -1,364 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "cursorutil.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpcontext.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "eraser.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" - -#include "libgimp/gimpintl.h" - - -/* Defaults */ -#define ERASER_DEFAULT_HARD FALSE -#define ERASER_DEFAULT_INCREMENTAL FALSE -#define ERASER_DEFAULT_ANTI_ERASE FALSE - -/* the eraser structures */ - -typedef struct _EraserOptions EraserOptions; - -struct _EraserOptions -{ - PaintOptions paint_options; - - gboolean hard; - gboolean hard_d; - GtkWidget *hard_w; - - gboolean anti_erase; - gboolean anti_erase_d; - GtkWidget *anti_erase_w; -}; - - -/* forward function declarations */ -static gpointer eraser_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); -static void eraser_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - gboolean hard, - gboolean incremental, - gboolean anti_erase); - - -/* the eraser tool options */ -static EraserOptions *eraser_options = NULL; - -/* local variables */ -static gboolean non_gui_hard; -static gboolean non_gui_incremental; -static gboolean non_gui_anti_erase; - - -/* functions */ - -static void -eraser_options_reset (void) -{ - EraserOptions *options = eraser_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w), - options->hard_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w), - options->anti_erase_d); -} - -static EraserOptions * -eraser_options_new (void) -{ - EraserOptions *options; - - GtkWidget *vbox; - - /* the new eraser tool options structure */ - options = g_new (EraserOptions, 1); - paint_options_init ((PaintOptions *) options, - ERASER, - eraser_options_reset); - options->hard = options->hard_d = ERASER_DEFAULT_HARD; - options->anti_erase = options->anti_erase_d = ERASER_DEFAULT_ANTI_ERASE; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* the hard toggle */ - options->hard_w = gtk_check_button_new_with_label (_("Hard Edge")); - gtk_box_pack_start (GTK_BOX (vbox), options->hard_w, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->hard_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->hard); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w), - options->hard_d); - gtk_widget_show (options->hard_w); - - /* the anti_erase toggle */ - options->anti_erase_w = gtk_check_button_new_with_label (_("Anti Erase")); - gtk_box_pack_start (GTK_BOX (vbox), options->anti_erase_w, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->anti_erase_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->anti_erase); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w), - options->anti_erase_d); - gtk_widget_show (options->anti_erase_w); - - return options; -} - -static void -eraser_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: - case GDK_Alt_R: - break; - case GDK_Shift_L: - case GDK_Shift_R: - if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */ - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w), - ! eraser_options->anti_erase); - break; - case GDK_Control_L: - case GDK_Control_R: - if (!(kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */ - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w), - ! eraser_options->anti_erase); - break; - } - - tool->toggled = eraser_options->anti_erase; -} - - -static gpointer -eraser_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - switch (state) - { - case INIT_PAINT: - break; - - case MOTION_PAINT: - eraser_motion (paint_core, - drawable, - eraser_options->paint_options.pressure_options, - eraser_options->hard, - eraser_options->paint_options.incremental, - eraser_options->anti_erase); - break; - - case FINISH_PAINT: - break; - - default: - break; - } - - return NULL; -} - -Tool * -tools_new_eraser (void) -{ - Tool *tool; - PaintCore *private; - - /* The tool options */ - if (! eraser_options) - { - eraser_options = eraser_options_new (); - tools_register (ERASER, (ToolOptions *) eraser_options); - } - - tool = paint_core_new (ERASER); - - private = (PaintCore *) tool->private; - private->paint_func = eraser_paint_func; - private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - tool->modifier_key_func = eraser_modifier_key_func; - - return tool; -} - - -void -tools_free_eraser (Tool *tool) -{ - paint_core_free (tool); -} - - -static void -eraser_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - gboolean hard, - gboolean incremental, - gboolean anti_erase) -{ - GImage *gimage; - gint opacity; - TempBuf *area; - guchar col[MAX_CHANNELS]; - gdouble scale; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - gimp_image_get_background (gimage, drawable, col); - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - /* Get a region which can be used to paint to */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - /* set the alpha channel */ - col[area->bytes - 1] = OPAQUE_OPACITY; - - /* color the pixels */ - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - - opacity = 255 * gimp_context_get_opacity (NULL); - if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; - - /* paste the newly painted canvas to the gimage which is being worked on */ - paint_core_paste_canvas (paint_core, drawable, - MIN (opacity, 255), - (int) (gimp_context_get_opacity (NULL) * 255), - anti_erase ? ANTI_ERASE_MODE : ERASE_MODE, - hard ? HARD : (pressure_options->pressure ? PRESSURE : SOFT), - scale, - incremental ? INCREMENTAL : CONSTANT); -} - - -static gpointer -eraser_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - eraser_motion (paint_core, drawable, - &non_gui_pressure_options, - non_gui_hard, non_gui_incremental, non_gui_anti_erase); - - return NULL; -} - -gboolean -eraser_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array) -{ - gboolean hardness = ERASER_DEFAULT_HARD; - gboolean method = ERASER_DEFAULT_INCREMENTAL; - gboolean anti_erase = ERASER_DEFAULT_ANTI_ERASE; - - EraserOptions *options = eraser_options; - - if (options) - { - hardness = options->hard; - method = options->paint_options.incremental; - anti_erase = options->anti_erase; - } - - return eraser_non_gui (drawable, num_strokes, stroke_array, - hardness, method, anti_erase); -} - -gboolean -eraser_non_gui (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array, - gint hardness, - gint method, - gboolean anti_erase) -{ - gint i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - non_gui_hard = hardness; - non_gui_incremental = method; - non_gui_anti_erase = anti_erase; - - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = eraser_non_gui_paint_func; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - eraser_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - return TRUE; - } - - return FALSE; -} diff --git a/app/eraser.h b/app/eraser.h deleted file mode 100644 index 35eb35d4e2..0000000000 --- a/app/eraser.h +++ /dev/null @@ -1,37 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __ERASER_H__ -#define __ERASER_H__ - - -gboolean eraser_non_gui (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array, - gint hardness, - gint method, - gboolean anti_erase); -gboolean eraser_non_gui_default (GimpDrawable *paint_core, - gint num_strokes, - gdouble *stroke_array); - -Tool * tools_new_eraser (void); -void tools_free_eraser (Tool *tool); - - -#endif /* __ERASER_H__ */ diff --git a/app/flip_tool.c b/app/flip_tool.c deleted file mode 100644 index c706265f88..0000000000 --- a/app/flip_tool.c +++ /dev/null @@ -1,324 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "cursorutil.h" -#include "drawable.h" -#include "flip_tool.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "path_transform.h" -#include "pixel_region.h" -#include "temp_buf.h" -#include "tile_manager.h" -#include "tile_manager_pvt.h" -#include "tools.h" -#include "tool_options.h" -#include "transform_core.h" - -#include "libgimp/gimpintl.h" - - -#define FLIP_INFO 0 - -/* the flip structures */ - -typedef struct _FlipOptions FlipOptions; - -struct _FlipOptions -{ - ToolOptions tool_options; - - InternalOrientationType type; - InternalOrientationType type_d; - GtkWidget *type_w[2]; -}; - - -/* local function prototypes */ - -static TileManager * flip_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state); - - -/* private variables */ - -static FlipOptions *flip_options = NULL; - -/* functions */ - -/* FIXME: Lame - 1 hacks abound since the code assumes certain values for - * the ORIENTATION_FOO constants. - */ - -static void -flip_options_reset (void) -{ - FlipOptions *options = flip_options; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d - 1]), TRUE); -} - -static FlipOptions * -flip_options_new (void) -{ - FlipOptions *options; - - GtkWidget *vbox; - GtkWidget *frame; - - /* the new flip tool options structure */ - options = g_new (FlipOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Flip Tool"), - flip_options_reset); - options->type = options->type_d = ORIENTATION_HORIZONTAL; - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* tool toggle */ - frame = - gimp_radio_group_new2 (TRUE, _("Tool Toggle"), - gimp_radio_button_update, - &options->type, (gpointer) options->type, - - _("Horizontal"), (gpointer) ORIENTATION_HORIZONTAL, - &options->type_w[0], - _("Vertical"), (gpointer) ORIENTATION_VERTICAL, - &options->type_w[1], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -static void -flip_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: case GDK_Alt_R: - break; - case GDK_Shift_L: case GDK_Shift_R: - break; - case GDK_Control_L: case GDK_Control_R: - if (flip_options->type == ORIENTATION_HORIZONTAL) - { - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_VERTICAL - 1]), TRUE); - } - else - { - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_HORIZONTAL - 1]), TRUE); - } - break; - } -} - -static TileManager * -flip_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - switch (state) - { - case TRANSFORM_INIT: - transform_info = NULL; - break; - - case TRANSFORM_MOTION: - break; - - case TRANSFORM_RECALC: - break; - - case TRANSFORM_FINISH: - /* transform_core->trans_info[FLIP] *= -1.0;*/ - return flip_tool_flip (gdisp->gimage, - gimp_image_active_drawable (gdisp->gimage), - transform_core->original, - (int) transform_core->trans_info[FLIP_INFO], - flip_options->type); - break; - } - - return NULL; -} - -static void -flip_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - GimpDrawable *drawable; - GdkCursorType ctype = GIMP_BAD_CURSOR; - - if ((drawable = gimp_image_active_drawable (gdisp->gimage))) - { - gint x, y; - gint off_x, off_y; - - gimp_drawable_offsets (drawable, &off_x, &off_y); - gdisplay_untransform_coords (gdisp, - (double) mevent->x, (double) mevent->y, - &x, &y, TRUE, FALSE); - - if (x >= off_x && y >= off_y && - x < (off_x + gimp_drawable_width (drawable)) && - y < (off_y + gimp_drawable_height (drawable))) - { - /* Is there a selected region? If so, is cursor inside? */ - if (gimage_mask_is_empty (gdisp->gimage) || - gimage_mask_value (gdisp->gimage, x, y)) - { - if (flip_options->type == ORIENTATION_HORIZONTAL) - ctype = GDK_SB_H_DOUBLE_ARROW; - else - ctype = GDK_SB_V_DOUBLE_ARROW; - } - } - } - gdisplay_install_tool_cursor (gdisp, ctype, - FLIP, - CURSOR_MODIFIER_NONE, - ctype == GDK_SB_V_DOUBLE_ARROW); -} - -Tool * -tools_new_flip (void) -{ - Tool *tool; - TransformCore *private; - - /* The tool options */ - if (! flip_options) - { - flip_options = flip_options_new (); - tools_register (FLIP, (ToolOptions *) flip_options); - } - - tool = transform_core_new (FLIP, FALSE); - private = tool->private; - - private->trans_func = flip_tool_transform; - private->trans_info[FLIP_INFO] = -1.0; - - tool->modifier_key_func = flip_modifier_key_func; - tool->cursor_update_func = flip_cursor_update; - - return tool; -} - -void -tools_free_flip_tool (Tool *tool) -{ - transform_core_free (tool); -} - -TileManager * -flip_tool_flip (GimpImage *gimage, - GimpDrawable *drawable, - TileManager *orig, - gint flip, - InternalOrientationType type) -{ - TileManager *new; - PixelRegion srcPR, destPR; - gint orig_width; - gint orig_height; - gint orig_bpp; - gint i; - - if (! orig) - return NULL; - - orig_width = tile_manager_level_width (orig); - orig_height = tile_manager_level_height (orig); - orig_bpp = tile_manager_level_bpp (orig); - - if (flip > 0) - { - new = tile_manager_new (orig_width, orig_height, orig_bpp); - pixel_region_init (&srcPR, orig, - 0, 0, orig_width, orig_height, FALSE); - pixel_region_init (&destPR, new, - 0, 0, orig_width, orig_height, TRUE); - - copy_region (&srcPR, &destPR); - new->x = orig->x; - new->y = orig->y; - } - else - { - new = tile_manager_new (orig_width, orig_height, orig_bpp); - new->x = orig->x; - new->y = orig->y; - - if (type == ORIENTATION_HORIZONTAL) - for (i = 0; i < orig->width; i++) - { - pixel_region_init (&srcPR, orig, i, 0, 1, orig_height, FALSE); - pixel_region_init (&destPR, new, - (orig_width - i - 1), 0, 1, orig_height, TRUE); - copy_region (&srcPR, &destPR); - } - else - for (i = 0; i < orig->height; i++) - { - pixel_region_init (&srcPR, orig, 0, i, orig_width, 1, FALSE); - pixel_region_init (&destPR, new, - 0, (orig_height - i - 1), orig_width, 1, TRUE); - copy_region (&srcPR, &destPR); - } - - /* flip locked paths */ - /* Note that the undo structures etc are setup before we enter this - * function. - */ - if (type == ORIENTATION_HORIZONTAL) - path_transform_flip_horz (gimage); - else - path_transform_flip_vert (gimage); - } - - return new; -} diff --git a/app/flip_tool.h b/app/flip_tool.h deleted file mode 100644 index b0d3fe71c0..0000000000 --- a/app/flip_tool.h +++ /dev/null @@ -1,33 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __FLIP_TOOL_H__ -#define __FLIP_TOOL_H__ - - -TileManager * flip_tool_flip (GimpImage *gimage, - GimpDrawable *drawable, - TileManager *orig, - gint flip, - InternalOrientationType type); - -Tool * tools_new_flip (void); -void tools_free_flip_tool (Tool *tool); - - -#endif /* __FLIP_TOOL_H__ */ diff --git a/app/free_select.c b/app/free_select.c deleted file mode 100644 index 911826a8b6..0000000000 --- a/app/free_select.c +++ /dev/null @@ -1,391 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "channel.h" -#include "draw_core.h" -#include "edit_selection.h" -#include "errors.h" -#include "floating_sel.h" -#include "free_select.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gdisplay.h" -#include "rect_select.h" -#include "selection_options.h" -#include "scan_convert.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpmath.h" - - -#define DEFAULT_MAX_INC 1024 -#define SUPERSAMPLE 3 -#define SUPERSAMPLE2 9 - -/* the free selection structures */ - -typedef struct _FreeSelect FreeSelect; - -struct _FreeSelect -{ - DrawCore *core; /* Core select object */ - - SelectOps op; /* selection operation (ADD, SUB, etc) */ - - gint current_x; /* these values are updated on every motion event */ - gint current_y; /* (enables immediate cursor updating on modifier - * key events). */ - - gint num_pts; /* Number of points in the polygon */ -}; - - -/* local function prototypes */ - -static void free_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void free_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void free_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); - - -/* the free selection tool options */ -static SelectionOptions * free_options = NULL; - -/* The global array of XPoints for drawing the polygon... */ -static GdkPoint *global_pts = NULL; -static gint max_segs = 0; - - -/* functions */ - -static gint -add_point (gint num_pts, - gint x, - gint y) -{ - if (num_pts >= max_segs) - { - max_segs += DEFAULT_MAX_INC; - - global_pts = (GdkPoint *) g_realloc ((void *) global_pts, sizeof (GdkPoint) * max_segs); - - if (!global_pts) - gimp_fatal_error ("add_point(): Unable to reallocate points array in free_select."); - } - - global_pts[num_pts].x = x; - global_pts[num_pts].y = y; - - return 1; -} - - -static Channel * -scan_convert (GimpImage *gimage, - gint num_pts, - ScanConvertPoint *pts, - gint width, - gint height, - gboolean antialias) -{ - Channel *mask; - ScanConverter *sc; - - sc = scan_converter_new (width, height, antialias ? SUPERSAMPLE : 1); - scan_converter_add_points (sc, num_pts, pts); - - mask = scan_converter_to_channel (sc, gimage); - scan_converter_free (sc); - - return mask; -} - - -/*************************************/ -/* Polygonal selection apparatus */ - -void -free_select (GImage *gimage, - gint num_pts, - ScanConvertPoint *pts, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius) -{ - Channel *mask; - - /* if applicable, replace the current selection */ - /* or insure that a floating selection is anchored down... */ - if (op == SELECTION_REPLACE) - gimage_mask_clear (gimage); - else - gimage_mask_undo (gimage); - - mask = scan_convert (gimage, num_pts, pts, - gimage->width, gimage->height, antialias); - - if (mask) - { - if (feather) - channel_feather (mask, gimp_image_get_mask (gimage), - feather_radius, - feather_radius, - op, 0, 0); - else - channel_combine_mask (gimp_image_get_mask (gimage), - mask, op, 0, 0); - channel_delete (mask); - } -} - -static void -free_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - FreeSelect *free_sel; - - free_sel = (FreeSelect *) tool->private; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - switch (free_sel->op) - { - case SELECTION_MOVE_MASK: - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE); - return; - case SELECTION_MOVE: - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE); - return; - default: - break; - } - - add_point (0, bevent->x, bevent->y); - free_sel->num_pts = 1; - - draw_core_start (free_sel->core, - gdisp->canvas->window, - tool); -} - -static void -free_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - FreeSelect *free_sel; - ScanConvertPoint *pts; - gint i; - - free_sel = (FreeSelect *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - draw_core_stop (free_sel->core, tool); - - tool->state = INACTIVE; - - /* First take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - if (free_sel->op == SELECTION_ANCHOR) - { - /* If there is a floating selection, anchor it */ - if (gimp_image_floating_sel (gdisp->gimage)) - floating_sel_anchor (gimp_image_floating_sel (gdisp->gimage)); - /* Otherwise, clear the selection mask */ - else - gimage_mask_clear (gdisp->gimage); - - gdisplays_flush (); - return; - } - - pts = g_new (ScanConvertPoint, free_sel->num_pts); - - for (i = 0; i < free_sel->num_pts; i++) - { - gdisplay_untransform_coords_f (gdisp, global_pts[i].x, global_pts[i].y, - &pts[i].x, &pts[i].y, FALSE); - } - - free_select (gdisp->gimage, free_sel->num_pts, pts, free_sel->op, - free_options->antialias, free_options->feather, - free_options->feather_radius); - - g_free (pts); - - gdisplays_flush (); - } -} - -static void -free_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - FreeSelect *free_sel; - - free_sel = (FreeSelect *) tool->private; - - /* needed for immediate cursor update on modifier event */ - free_sel->current_x = mevent->x; - free_sel->current_y = mevent->y; - - if (tool->state != ACTIVE) - return; - - if (free_sel->op == SELECTION_ANCHOR) - { - free_sel->op = SELECTION_REPLACE; - - rect_select_cursor_update (tool, mevent, gdisp); - } - - if (add_point (free_sel->num_pts, mevent->x, mevent->y)) - { - gdk_draw_line (free_sel->core->win, free_sel->core->gc, - global_pts[free_sel->num_pts - 1].x, - global_pts[free_sel->num_pts - 1].y, - global_pts[free_sel->num_pts].x, - global_pts[free_sel->num_pts].y); - - free_sel->num_pts ++; - } -} - -static void -free_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - FreeSelect *free_sel; - - free_sel = (FreeSelect *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (free_sel->core, tool); - break; - - case RESUME: - draw_core_resume (free_sel->core, tool); - break; - - case HALT: - draw_core_stop (free_sel->core, tool); - break; - - default: - break; - } -} - -void -free_select_draw (Tool *tool) -{ - FreeSelect *free_sel; - gint i; - - free_sel = (FreeSelect *) tool->private; - - for (i = 1; i < free_sel->num_pts; i++) - gdk_draw_line (free_sel->core->win, free_sel->core->gc, - global_pts[i - 1].x, global_pts[i - 1].y, - global_pts[i].x, global_pts[i].y); -} - -static void -free_select_options_reset (void) -{ - selection_options_reset (free_options); -} - -Tool * -tools_new_free_select (void) -{ - Tool *tool; - FreeSelect *private; - - /* The tool options */ - if (!free_options) - { - free_options = - selection_options_new (FREE_SELECT, free_select_options_reset); - tools_register (FREE_SELECT, (ToolOptions *) free_options); - } - - tool = tools_new_tool (FREE_SELECT); - private = g_new0 (FreeSelect, 1); - - private->core = draw_core_new (free_select_draw); - private->num_pts = 0; - private->op = SELECTION_REPLACE; - - tool->scroll_lock = TRUE; /* Do not allow scrolling */ - - tool->private = (void *) private; - - tool->button_press_func = free_select_button_press; - tool->button_release_func = free_select_button_release; - tool->motion_func = free_select_motion; - tool->modifier_key_func = rect_select_modifier_update; - tool->cursor_update_func = rect_select_cursor_update; - tool->oper_update_func = rect_select_oper_update; - tool->control_func = free_select_control; - - return tool; -} - -void -tools_free_free_select (Tool *tool) -{ - FreeSelect *free_sel; - - free_sel = (FreeSelect *) tool->private; - - draw_core_free (free_sel->core); - g_free (free_sel); -} diff --git a/app/free_select.h b/app/free_select.h deleted file mode 100644 index 11b148c231..0000000000 --- a/app/free_select.h +++ /dev/null @@ -1,38 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __FREE_SELECT_H__ -#define __FREE_SELECT_H__ - - -/* free select functions */ - -void free_select (GimpImage *gimage, - gint num_pts, - ScanConvertPoint *pts, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius); -void free_select_draw (Tool *tool); - -Tool * tools_new_free_select (void); -void tools_free_free_select (Tool *tool); - - -#endif /* __FREE_SELECT_H__ */ diff --git a/app/fuzzy_select.c b/app/fuzzy_select.c deleted file mode 100644 index d746759ad2..0000000000 --- a/app/fuzzy_select.c +++ /dev/null @@ -1,688 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "boundary.h" -#include "channel.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "drawable.h" -#include "edit_selection.h" -#include "fuzzy_select.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimprc.h" -#include "gimpui.h" -#include "gdisplay.h" -#include "pixel_region.h" -#include "rect_select.h" -#include "selection_options.h" -#include "tile_manager.h" -#include "tile.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* the fuzzy selection structures */ - -typedef struct _FuzzySelect FuzzySelect; - -struct _FuzzySelect -{ - DrawCore *core; /* Core select object */ - - gint op; /* selection operation (ADD, SUB, etc) */ - - gint current_x; /* these values are updated on every motion event */ - gint current_y; /* (enables immediate cursor updating on modifier - * key events). */ - - gint x, y; /* Point from which to execute seed fill */ - gint first_x; /* */ - gint first_y; /* variables to keep track of sensitivity */ - gdouble first_threshold; /* initial value of threshold slider */ -}; - - -/* fuzzy select action functions */ -static void fuzzy_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void fuzzy_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void fuzzy_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void fuzzy_select_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static void fuzzy_select_draw (Tool *tool); - -static GdkSegment * fuzzy_select_calculate (Tool *tool, - GDisplay *gdisp, - gint *nsegs); - - -/* the fuzzy selection tool options */ -static SelectionOptions *fuzzy_options = NULL; - -/* XSegments which make up the fuzzy selection boundary */ -static GdkSegment *segs = NULL; -static gint num_segs = 0; - -Channel * fuzzy_mask = NULL; - - -/*************************************/ -/* Fuzzy selection apparatus */ - -static gint -is_pixel_sufficiently_different (guchar *col1, - guchar *col2, - gboolean antialias, - gint threshold, - gint bytes, - gboolean has_alpha) -{ - gint diff; - gint max; - gint b; - gint alpha; - - max = 0; - alpha = (has_alpha) ? bytes - 1 : bytes; - - /* if there is an alpha channel, never select transparent regions */ - if (has_alpha && col2[alpha] == 0) - return 0; - - for (b = 0; b < bytes; b++) - { - diff = col1[b] - col2[b]; - diff = abs (diff); - if (diff > max) - max = diff; - } - - if (antialias) - { - float aa; - - aa = 1.5 - ((float) max / threshold); - if (aa <= 0) - return 0; - else if (aa < 0.5) - return (unsigned char) (aa * 512); - else - return 255; - } - else - { - if (max > threshold) - return 0; - else - return 255; - } -} - -static void -ref_tiles (TileManager *src, - TileManager *mask, - Tile **s_tile, - Tile **m_tile, - gint x, - gint y, - guchar **s, - guchar **m) -{ - if (*s_tile != NULL) - tile_release (*s_tile, FALSE); - if (*m_tile != NULL) - tile_release (*m_tile, TRUE); - - *s_tile = tile_manager_get_tile (src, x, y, TRUE, FALSE); - *m_tile = tile_manager_get_tile (mask, x, y, TRUE, TRUE); - - *s = tile_data_pointer (*s_tile, x % TILE_WIDTH, y % TILE_HEIGHT); - *m = tile_data_pointer (*m_tile, x % TILE_WIDTH, y % TILE_HEIGHT); -} - -static int -find_contiguous_segment (guchar *col, - PixelRegion *src, - PixelRegion *mask, - gint width, - gint bytes, - gboolean has_alpha, - gboolean antialias, - gint threshold, - gint initial, - gint *start, - gint *end) -{ - guchar *s; - guchar *m; - guchar diff; - Tile *s_tile = NULL; - Tile *m_tile = NULL; - - ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, src->x, src->y, &s, &m); - - /* check the starting pixel */ - if (! (diff = is_pixel_sufficiently_different (col, s, antialias, - threshold, bytes, has_alpha))) - { - tile_release (s_tile, FALSE); - tile_release (m_tile, TRUE); - return FALSE; - } - - *m-- = diff; - s -= bytes; - *start = initial - 1; - - while (*start >= 0 && diff) - { - if (! ((*start + 1) % TILE_WIDTH)) - ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *start, src->y, &s, &m); - - diff = is_pixel_sufficiently_different (col, s, antialias, - threshold, bytes, has_alpha); - if ((*m-- = diff)) - { - s -= bytes; - (*start)--; - } - } - - diff = 1; - *end = initial + 1; - if (*end % TILE_WIDTH && *end < width) - ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *end, src->y, &s, &m); - - while (*end < width && diff) - { - if (! (*end % TILE_WIDTH)) - ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *end, src->y, &s, &m); - - diff = is_pixel_sufficiently_different (col, s, antialias, - threshold, bytes, has_alpha); - if ((*m++ = diff)) - { - s += bytes; - (*end)++; - } - } - - tile_release (s_tile, FALSE); - tile_release (m_tile, TRUE); - return TRUE; -} - -static void -find_contiguous_region_helper (PixelRegion *mask, - PixelRegion *src, - gboolean has_alpha, - gboolean antialias, - gint threshold, - gboolean indexed, - gint x, - gint y, - guchar *col) -{ - gint start, end, i; - gint val; - gint bytes; - - Tile *tile; - - if (threshold == 0) threshold = 1; - if (x < 0 || x >= src->w) return; - if (y < 0 || y >= src->h) return; - - tile = tile_manager_get_tile (mask->tiles, x, y, TRUE, FALSE); - val = *(guchar *)(tile_data_pointer (tile, - x % TILE_WIDTH, y % TILE_HEIGHT)); - tile_release (tile, FALSE); - if (val != 0) - return; - - src->x = x; - src->y = y; - - bytes = src->bytes; - if(indexed) - { - bytes = has_alpha ? 4 : 3; - } - - if (! find_contiguous_segment (col, src, mask, src->w, - src->bytes, has_alpha, - antialias, threshold, x, &start, &end)) - return; - - for (i = start + 1; i < end; i++) - { - find_contiguous_region_helper (mask, src, has_alpha, antialias, - threshold, indexed, i, y - 1, col); - find_contiguous_region_helper (mask, src, has_alpha, antialias, - threshold, indexed, i, y + 1, col); - } -} - -Channel * -find_contiguous_region (GImage *gimage, - GimpDrawable *drawable, - gboolean antialias, - gint threshold, - gint x, - gint y, - gboolean sample_merged) -{ - PixelRegion srcPR, maskPR; - Channel *mask; - guchar *start; - gboolean has_alpha; - gboolean indexed; - gint type; - gint bytes; - Tile *tile; - - if (sample_merged) - { - pixel_region_init (&srcPR, gimp_image_composite (gimage), 0, 0, - gimage->width, gimage->height, FALSE); - type = gimp_image_composite_type (gimage); - has_alpha = (type == RGBA_GIMAGE || - type == GRAYA_GIMAGE || - type == INDEXEDA_GIMAGE); - } - else - { - pixel_region_init (&srcPR, gimp_drawable_data (drawable), - 0, 0, - gimp_drawable_width (drawable), - gimp_drawable_height (drawable), - FALSE); - has_alpha = gimp_drawable_has_alpha (drawable); - } - indexed = gimp_drawable_is_indexed (drawable); - bytes = gimp_drawable_bytes (drawable); - - if (indexed) - { - bytes = has_alpha ? 4 : 3; - } - mask = channel_new_mask (gimage, srcPR.w, srcPR.h); - pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE(mask)), - 0, 0, - gimp_drawable_width (GIMP_DRAWABLE(mask)), - gimp_drawable_height (GIMP_DRAWABLE(mask)), - TRUE); - - tile = tile_manager_get_tile (srcPR.tiles, x, y, TRUE, FALSE); - if (tile) - { - start = tile_data_pointer (tile, x%TILE_WIDTH, y%TILE_HEIGHT); - - find_contiguous_region_helper (&maskPR, &srcPR, has_alpha, antialias, - threshold, bytes, x, y, start); - - tile_release (tile, FALSE); - } - - return mask; -} - -void -fuzzy_select (GImage *gimage, - GimpDrawable *drawable, - gint op, - gboolean feather, - gdouble feather_radius) -{ - gint off_x, off_y; - - /* if applicable, replace the current selection */ - if (op == CHANNEL_OP_REPLACE) - gimage_mask_clear (gimage); - else - gimage_mask_undo (gimage); - - if (drawable) /* NULL if sample_merged is active */ - gimp_drawable_offsets (drawable, &off_x, &off_y); - else - off_x = off_y = 0; - - if (feather) - channel_feather (fuzzy_mask, gimp_image_get_mask (gimage), - feather_radius, - feather_radius, - op, off_x, off_y); - else - channel_combine_mask (gimp_image_get_mask (gimage), - fuzzy_mask, op, off_x, off_y); - - /* free the fuzzy region struct */ - channel_delete (fuzzy_mask); - fuzzy_mask = NULL; -} - -/* fuzzy select action functions */ - -static void -fuzzy_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - FuzzySelect *fuzzy_sel; - - fuzzy_sel = (FuzzySelect *) tool->private; - - fuzzy_sel->x = bevent->x; - fuzzy_sel->y = bevent->y; - fuzzy_sel->first_x = fuzzy_sel->x; - fuzzy_sel->first_y = fuzzy_sel->y; - fuzzy_sel->first_threshold = fuzzy_options->threshold; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - if (fuzzy_sel->op == SELECTION_MOVE_MASK) - { - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE); - return; - } - else if (fuzzy_sel->op == SELECTION_MOVE) - { - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE); - return; - } - - /* calculate the region boundary */ - segs = fuzzy_select_calculate (tool, gdisp, &num_segs); - - draw_core_start (fuzzy_sel->core, - gdisp->canvas->window, - tool); -} - -static void -fuzzy_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - FuzzySelect *fuzzy_sel; - GimpDrawable *drawable; - - fuzzy_sel = (FuzzySelect *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - draw_core_stop (fuzzy_sel->core, tool); - tool->state = INACTIVE; - - /* First take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - drawable = (fuzzy_options->sample_merged ? - NULL : gimp_image_active_drawable (gdisp->gimage)); - - fuzzy_select (gdisp->gimage, drawable, fuzzy_sel->op, - fuzzy_options->feather, - fuzzy_options->feather_radius); - gdisplays_flush (); - } - - /* If the segment array is allocated, free it */ - if (segs) - g_free (segs); - segs = NULL; -} - -static void -fuzzy_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - FuzzySelect *fuzzy_sel; - GdkSegment *new_segs; - gint num_new_segs; - gint diff_x, diff_y; - gdouble diff; - - static guint last_time = 0; - - fuzzy_sel = (FuzzySelect *) tool->private; - - /* needed for immediate cursor update on modifier event */ - fuzzy_sel->current_x = mevent->x; - fuzzy_sel->current_y = mevent->y; - - if (tool->state != ACTIVE) - return; - - /* don't let the events come in too fast, ignore below a delay of 100 ms */ - if (ABS (mevent->time - last_time) < 100) - return; - - last_time = mevent->time; - - diff_x = mevent->x - fuzzy_sel->first_x; - diff_y = mevent->y - fuzzy_sel->first_y; - - diff = ((ABS (diff_x) > ABS (diff_y)) ? diff_x : diff_y) / 2.0; - - gtk_adjustment_set_value (GTK_ADJUSTMENT (fuzzy_options->threshold_w), - fuzzy_sel->first_threshold + diff); - - /* calculate the new fuzzy boundary */ - new_segs = fuzzy_select_calculate (tool, gdisp, &num_new_segs); - - /* stop the current boundary */ - draw_core_pause (fuzzy_sel->core, tool); - - /* make sure the XSegment array is freed before we assign the new one */ - if (segs) - g_free (segs); - segs = new_segs; - num_segs = num_new_segs; - - /* start the new boundary */ - draw_core_resume (fuzzy_sel->core, tool); -} - - -static GdkSegment * -fuzzy_select_calculate (Tool *tool, - GDisplay *gdisp, - gint *nsegs) -{ - PixelRegion maskPR; - FuzzySelect *fuzzy_sel; - Channel *new; - GdkSegment *segs; - BoundSeg *bsegs; - GimpDrawable *drawable; - gint i; - gint x, y; - gboolean use_offsets; - - fuzzy_sel = (FuzzySelect *) tool->private; - drawable = gimp_image_active_drawable (gdisp->gimage); - - gimp_add_busy_cursors (); - - use_offsets = fuzzy_options->sample_merged ? FALSE : TRUE; - - gdisplay_untransform_coords (gdisp, fuzzy_sel->x, - fuzzy_sel->y, &x, &y, FALSE, use_offsets); - - new = find_contiguous_region (gdisp->gimage, drawable, - fuzzy_options->antialias, - fuzzy_options->threshold, x, y, - fuzzy_options->sample_merged); - - if (fuzzy_mask) - gtk_object_unref (GTK_OBJECT (fuzzy_mask)); - - fuzzy_mask = new; - - gtk_object_ref (GTK_OBJECT (fuzzy_mask)); - gtk_object_sink (GTK_OBJECT (fuzzy_mask)); - - /* calculate and allocate a new XSegment array which represents the boundary - * of the color-contiguous region - */ - pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (fuzzy_mask)), - 0, 0, - gimp_drawable_width (GIMP_DRAWABLE (fuzzy_mask)), - gimp_drawable_height (GIMP_DRAWABLE (fuzzy_mask)), - FALSE); - bsegs = find_mask_boundary (&maskPR, nsegs, WithinBounds, - 0, 0, - gimp_drawable_width (GIMP_DRAWABLE (fuzzy_mask)), - gimp_drawable_height (GIMP_DRAWABLE (fuzzy_mask))); - - segs = g_new (GdkSegment, *nsegs); - - for (i = 0; i < *nsegs; i++) - { - gdisplay_transform_coords (gdisp, bsegs[i].x1, bsegs[i].y1, &x, &y, use_offsets); - segs[i].x1 = x; segs[i].y1 = y; - gdisplay_transform_coords (gdisp, bsegs[i].x2, bsegs[i].y2, &x, &y, use_offsets); - segs[i].x2 = x; segs[i].y2 = y; - } - - /* free boundary segments */ - g_free (bsegs); - - gimp_remove_busy_cursors (NULL); - - return segs; -} - -static void -fuzzy_select_draw (Tool *tool) -{ - FuzzySelect *fuzzy_sel; - - fuzzy_sel = (FuzzySelect *) tool->private; - - if (segs) - gdk_draw_segments (fuzzy_sel->core->win, fuzzy_sel->core->gc, segs, num_segs); -} - -static void -fuzzy_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - FuzzySelect *fuzzy_sel; - - fuzzy_sel = (FuzzySelect *) tool->private; - - switch (action) - { - case PAUSE : - draw_core_pause (fuzzy_sel->core, tool); - break; - - case RESUME : - draw_core_resume (fuzzy_sel->core, tool); - break; - - case HALT : - draw_core_stop (fuzzy_sel->core, tool); - break; - - default: - break; - } -} - -static void -fuzzy_select_options_reset (void) -{ - selection_options_reset (fuzzy_options); -} - -Tool * -tools_new_fuzzy_select (void) -{ - Tool *tool; - FuzzySelect *private; - - /* The tool options */ - if (! fuzzy_options) - { - fuzzy_options = selection_options_new (FUZZY_SELECT, - fuzzy_select_options_reset); - tools_register (FUZZY_SELECT, (ToolOptions *) fuzzy_options); - } - - tool = tools_new_tool (FUZZY_SELECT); - private = g_new0 (FuzzySelect, 1); - - private->core = draw_core_new (fuzzy_select_draw); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - - tool->private = (void *) private; - - tool->button_press_func = fuzzy_select_button_press; - tool->button_release_func = fuzzy_select_button_release; - tool->motion_func = fuzzy_select_motion; - tool->modifier_key_func = rect_select_modifier_update; - tool->cursor_update_func = rect_select_cursor_update; - tool->oper_update_func = rect_select_oper_update; - tool->control_func = fuzzy_select_control; - - return tool; -} - -void -tools_free_fuzzy_select (Tool *tool) -{ - FuzzySelect *fuzzy_sel; - - fuzzy_sel = (FuzzySelect *) tool->private; - draw_core_free (fuzzy_sel->core); - g_free (fuzzy_sel); -} diff --git a/app/fuzzy_select.h b/app/fuzzy_select.h deleted file mode 100644 index 42533a19db..0000000000 --- a/app/fuzzy_select.h +++ /dev/null @@ -1,43 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __FUZZY_SELECT_H__ -#define __FUZZY_SELECT_H__ - - -Channel * find_contiguous_region (GimpImage *gimage, - GimpDrawable *drawable, - gboolean antialias, - gint threshold, - gint x, - gint y, - gboolean sample_merged); -void fuzzy_select (GimpImage *gimage, - GimpDrawable *drawable, - gint op, - gboolean feather, - gdouble feather_radius); - -Tool * tools_new_fuzzy_select (void); -void tools_free_fuzzy_select (Tool *tool); - - -extern Channel *fuzzy_mask; - - -#endif /* __FUZZY_SELECT_H__ */ diff --git a/app/gdisplay.c b/app/gdisplay.c index 0cc5dca17d..651d77360d 100644 --- a/app/gdisplay.c +++ b/app/gdisplay.c @@ -51,7 +51,6 @@ #include "scale.h" #include "scroll.h" #include "selection.h" -#include "tools.h" #include "undo.h" @@ -59,7 +58,8 @@ #include "gdisplay_color.h" #endif /* DISPLAY_FILTERS */ -#include "bezier_selectP.h" +#include "tools/bezier_selectP.h" +#include "tools/tools.h" #include "libgimp/gimpmath.h" diff --git a/app/gimage.c b/app/gimage.c index 6e59940aae..86ba5fdc82 100644 --- a/app/gimage.c +++ b/app/gimage.c @@ -34,9 +34,10 @@ #include "gdisplay.h" #include "paint_funcs.h" #include "palette_import.h" -#include "tools.h" #include "undo.h" +#include "tools/tools.h" + /* gimage.c: Junk (ugly dependencies) from gimpimage.c on its way * to proper places. That is, the handlers should be moved to diff --git a/app/gimage_mask.c b/app/gimage_mask.c index 0237af2cb1..e716b75e99 100644 --- a/app/gimage_mask.c +++ b/app/gimage_mask.c @@ -31,14 +31,16 @@ #include "gimage_mask.h" #include "gimprc.h" #include "layer.h" -#include "paint_core.h" #include "paint_funcs.h" -#include "paint_options.h" #include "pixel_region.h" #include "tile_manager.h" #include "tile_manager_pvt.h" #include "undo.h" +#include "tools/paint_core.h" +#include "tools/paint_options.h" +#include "tools/tools.h" + #include "pdb/procedural_db.h" #include "libgimp/gimpintl.h" diff --git a/app/gimpbrush.c b/app/gimpbrush.c index b0878d201b..15ab618adc 100644 --- a/app/gimpbrush.c +++ b/app/gimpbrush.c @@ -50,9 +50,11 @@ #include "gimprc.h" #include "patterns.h" #include "pattern_header.h" -#include "paint_core.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpintl.h" diff --git a/app/gimpbrushgenerated.c b/app/gimpbrushgenerated.c index b58855cebb..649018e539 100644 --- a/app/gimpbrushgenerated.c +++ b/app/gimpbrushgenerated.c @@ -33,11 +33,13 @@ #include "appenv.h" #include "gimpbrushgenerated.h" -#include "paint_core.h" #include "gimprc.h" #include "gimpbrush.h" #include "temp_buf.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" diff --git a/app/gimpbrushpipe.c b/app/gimpbrushpipe.c index 1eea53e299..1467025d56 100644 --- a/app/gimpbrushpipe.c +++ b/app/gimpbrushpipe.c @@ -48,9 +48,11 @@ #include "patterns.h" #include "gimpbrush.h" #include "gimpbrushpipe.h" -#include "paint_core.h" #include "gimprc.h" +/* this needs to go away */ +#include "tools/paint_core.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpparasiteio.h" diff --git a/app/gimpdnd.c b/app/gimpdnd.c index 17967cfd87..0a409d59e6 100644 --- a/app/gimpdnd.c +++ b/app/gimpdnd.c @@ -38,7 +38,8 @@ #include "layer.h" #include "patterns.h" #include "temp_buf.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimplimits.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/gimpimage-convert.c b/app/gimpimage-convert.c index 7d29b2adbc..b5d85d628e 100644 --- a/app/gimpimage-convert.c +++ b/app/gimpimage-convert.c @@ -94,30 +94,31 @@ #include "apptypes.h" #include "appenv.h" -#include "brightness_contrast.h" -#include "color_balance.h" #include "convert.h" #include "cursorutil.h" -#include "curves.h" #include "drawable.h" #include "floating_sel.h" #include "fsdither.h" #include "gdisplay.h" #include "gimpimage.h" #include "gimpui.h" -#include "hue_saturation.h" #include "layer.h" -#include "levels.h" #include "undo.h" #include "palette.h" #include "gimppalette.h" #include "palette_select.h" #include "pixel_region.h" -#include "posterize.h" -#include "threshold.h" #include "tile_manager.h" #include "tile_manager_pvt.h" /* ick ick ick. */ +#include "tools/brightness_contrast.h" +#include "tools/color_balance.h" +#include "tools/curves.h" +#include "tools/hue_saturation.h" +#include "tools/levels.h" +#include "tools/posterize.h" +#include "tools/threshold.h" + #include "libgimp/gimpcolorspace.h" #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/gimprc.c b/app/gimprc.c index e387fd07f6..662acb519a 100644 --- a/app/gimprc.c +++ b/app/gimprc.c @@ -50,7 +50,8 @@ #include "plug_in.h" #include "gimage.h" #include "session.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" #include "libgimp/gimputils.h" diff --git a/app/global_edit.c b/app/global_edit.c index 5a770b28de..7b49b80888 100644 --- a/app/global_edit.c +++ b/app/global_edit.c @@ -38,9 +38,10 @@ #include "paint_funcs.h" #include "pixel_region.h" #include "tile_manager.h" -#include "tools.h" #include "undo.h" +#include "tools/tools.h" + #include "libgimp/gimpintl.h" #include "tile_manager_pvt.h" diff --git a/app/gui/brush-select.c b/app/gui/brush-select.c index d5be3301cc..ff62d1345a 100644 --- a/app/gui/brush-select.c +++ b/app/gui/brush-select.c @@ -37,10 +37,11 @@ #include "gimplist.h" #include "gimprc.h" #include "gimpui.h" -#include "paint_options.h" #include "session.h" #include "temp_buf.h" +#include "tools/paint_options.h" + #include "pdb/procedural_db.h" #include "libgimp/gimphelpui.h" diff --git a/app/gui/commands.c b/app/gui/commands.c index 2b9a4f109e..9763a89629 100644 --- a/app/gui/commands.c +++ b/app/gui/commands.c @@ -68,13 +68,14 @@ #include "scale.h" #include "selection.h" #include "tips_dialog.h" -#include "tools.h" #include "undo.h" #ifdef DISPLAY_FILTERS #include "gdisplay_color_ui.h" #endif /* DISPLAY_FILTERS */ +#include "tools/tools.h" + #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/gui/device-status-dialog.c b/app/gui/device-status-dialog.c index 86d07ec8d9..3f7f2e91f6 100644 --- a/app/gui/device-status-dialog.c +++ b/app/gui/device-status-dialog.c @@ -39,7 +39,8 @@ #include "gradient_header.h" #include "patterns.h" #include "session.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/gui/help-commands.c b/app/gui/help-commands.c index 2b9a4f109e..9763a89629 100644 --- a/app/gui/help-commands.c +++ b/app/gui/help-commands.c @@ -68,13 +68,14 @@ #include "scale.h" #include "selection.h" #include "tips_dialog.h" -#include "tools.h" #include "undo.h" #ifdef DISPLAY_FILTERS #include "gdisplay_color_ui.h" #endif /* DISPLAY_FILTERS */ +#include "tools/tools.h" + #include "libgimp/gimphelpui.h" #include "libgimp/gimpmath.h" diff --git a/app/gui/info-window.c b/app/gui/info-window.c index a5179d9ca7..478fe313bb 100644 --- a/app/gui/info-window.c +++ b/app/gui/info-window.c @@ -34,7 +34,8 @@ #include "info_dialog.h" #include "info_window.h" #include "scroll.h" -#include "tools.h" + +#include "tools/tools.h" #include "pdb/procedural_db.h" diff --git a/app/gui/input-dialog.c b/app/gui/input-dialog.c index 86d07ec8d9..3f7f2e91f6 100644 --- a/app/gui/input-dialog.c +++ b/app/gui/input-dialog.c @@ -39,7 +39,8 @@ #include "gradient_header.h" #include "patterns.h" #include "session.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/gui/menus.c b/app/gui/menus.c index 20b13ec2af..55c0636ff1 100644 --- a/app/gui/menus.c +++ b/app/gui/menus.c @@ -31,6 +31,7 @@ #include "commands.h" #include "dialog_handler.h" #include "fileops.h" +#include "gdisplay.h" #include "gimphelp.h" #include "gimprc.h" #include "gimpui.h" @@ -41,8 +42,8 @@ #include "paint_funcs.h" #include "preferences_dialog.h" #include "scale.h" -#include "tools.h" -#include "gdisplay.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" diff --git a/app/gui/paths-dialog.c b/app/gui/paths-dialog.c index 005e05b006..0f8d019397 100644 --- a/app/gui/paths-dialog.c +++ b/app/gui/paths-dialog.c @@ -45,8 +45,6 @@ #include "lc_dialogP.h" #include "menus.h" #include "ops_buttons.h" -#include "bezier_select.h" -#include "bezier_selectP.h" #include "path.h" #include "pathP.h" #include "path_transform.h" @@ -55,6 +53,9 @@ #include "plug_in.h" #include "undo.h" +#include "tools/bezier_select.h" +#include "tools/bezier_selectP.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpintl.h" diff --git a/app/histogram_tool.c b/app/histogram_tool.c deleted file mode 100644 index 8cdcc20321..0000000000 --- a/app/histogram_tool.c +++ /dev/null @@ -1,470 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimphistogram.h" -#include "gimpui.h" -#include "histogram_tool.h" -#include "histogramwidget.h" -#include "pixel_region.h" -#include "tool_options.h" -#include "tools.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -#define TEXT_WIDTH 45 -#define GRADIENT_HEIGHT 15 - -/* the histogram structures */ - -typedef struct _HistogramTool HistogramTool; - -struct _HistogramTool -{ - gint x, y; /* coords for last mouse click */ -}; - - -/* histogram_tool action functions */ -static void histogram_tool_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static HistogramToolDialog * histogram_tool_dialog_new (void); - -static void histogram_tool_close_callback (GtkWidget *widget, - gpointer data); -static void histogram_tool_channel_callback (GtkWidget *widget, - gpointer data); -static void histogram_tool_gradient_draw (GtkWidget *gdisp, - gint channel); - -static void histogram_tool_dialog_update (HistogramToolDialog *htd, - gint start, - gint end); - - -/* the histogram tool options */ -static ToolOptions * histogram_tool_options = NULL; - -/* the histogram tool dialog */ -static HistogramToolDialog * histogram_tool_dialog = NULL; - - -/* histogram_tool machinery */ - -void -histogram_tool_histogram_range (HistogramWidget *widget, - gint start, - gint end, - gpointer data) -{ - HistogramToolDialog *htd; - gdouble pixels; - gdouble count; - - htd = (HistogramToolDialog *) data; - - if (htd == NULL || htd->hist == NULL || - gimp_histogram_nchannels (htd->hist) <= 0) - return; - - pixels = gimp_histogram_get_count (htd->hist, 0, 255); - count = gimp_histogram_get_count (htd->hist, start, end); - - htd->mean = gimp_histogram_get_mean (htd->hist, htd->channel, - start, end); - htd->std_dev = gimp_histogram_get_std_dev (htd->hist, htd->channel, - start, end); - htd->median = gimp_histogram_get_median (htd->hist, htd->channel, - start, end); - htd->pixels = pixels; - htd->count = count; - htd->percentile = count / pixels; - - if (htd->shell) - histogram_tool_dialog_update (htd, start, end); -} - -static void -histogram_tool_dialog_update (HistogramToolDialog *htd, - gint start, - gint end) -{ - gchar text[12]; - - /* mean */ - g_snprintf (text, sizeof (text), "%3.1f", htd->mean); - gtk_label_set_text (GTK_LABEL (htd->info_labels[0]), text); - - /* std dev */ - g_snprintf (text, sizeof (text), "%3.1f", htd->std_dev); - gtk_label_set_text (GTK_LABEL (htd->info_labels[1]), text); - - /* median */ - g_snprintf (text, sizeof (text), "%3.1f", htd->median); - gtk_label_set_text (GTK_LABEL (htd->info_labels[2]), text); - - /* pixels */ - g_snprintf (text, sizeof (text), "%8.1f", htd->pixels); - gtk_label_set_text (GTK_LABEL (htd->info_labels[3]), text); - - /* intensity */ - if (start == end) - g_snprintf (text, sizeof (text), "%d", start); - else - g_snprintf (text, sizeof (text), "%d..%d", start, end); - gtk_label_set_text (GTK_LABEL (htd->info_labels[4]), text); - - /* count */ - g_snprintf (text, sizeof (text), "%8.1f", htd->count); - gtk_label_set_text (GTK_LABEL (htd->info_labels[5]), text); - - /* percentile */ - g_snprintf (text, sizeof (text), "%2.2f", htd->percentile * 100); - gtk_label_set_text (GTK_LABEL (htd->info_labels[6]), text); -} - -/* histogram_tool action functions */ - -static void -histogram_tool_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - if (histogram_tool_dialog) - histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog); - break; - - default: - break; - } -} - -Tool * -tools_new_histogram_tool (void) -{ - Tool *tool; - HistogramTool *private; - - /* The tool options */ - if (! histogram_tool_options) - { - histogram_tool_options = tool_options_new (_("Histogram")); - tools_register (HISTOGRAM, histogram_tool_options); - } - - tool = tools_new_tool (HISTOGRAM); - private = g_new0 (HistogramTool, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = histogram_tool_control; - - return tool; -} - -void -tools_free_histogram_tool (Tool *tool) -{ - HistogramTool * hist; - - hist = (HistogramTool *) tool->private; - - /* Close the histogram dialog */ - if (histogram_tool_dialog) - histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog); - - g_free (hist); -} - -void -histogram_tool_initialize (GDisplay *gdisp) -{ - PixelRegion PR; - - if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Histogram does not operate on indexed drawables.")); - return; - } - - /* The histogram_tool dialog */ - if (!histogram_tool_dialog) - histogram_tool_dialog = histogram_tool_dialog_new (); - else if (!GTK_WIDGET_VISIBLE (histogram_tool_dialog->shell)) - gtk_widget_show (histogram_tool_dialog->shell); - - histogram_tool_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - histogram_tool_dialog->color = gimp_drawable_is_rgb (histogram_tool_dialog->drawable); - - /* hide or show the channel menu based on image type */ - if (histogram_tool_dialog->color) - gtk_widget_show (histogram_tool_dialog->channel_menu); - else - gtk_widget_hide (histogram_tool_dialog->channel_menu); - - /* calculate the histogram */ - pixel_region_init (&PR, gimp_drawable_data (histogram_tool_dialog->drawable), - 0, 0, - gimp_drawable_width (histogram_tool_dialog->drawable), - gimp_drawable_height (histogram_tool_dialog->drawable), - FALSE); - gimp_histogram_calculate (histogram_tool_dialog->hist, &PR, NULL); - - histogram_widget_update (histogram_tool_dialog->histogram, - histogram_tool_dialog->hist); - histogram_widget_range (histogram_tool_dialog->histogram, 0, 255); -} - -/***************************/ -/* Histogram Tool dialog */ -/***************************/ - -static HistogramToolDialog * -histogram_tool_dialog_new (void) -{ - HistogramToolDialog *htd; - GtkWidget *main_vbox; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *grad_hbox; - GtkWidget *frame; - GtkWidget *table; - GtkWidget *label; - GtkWidget *option_menu; - gint i; - gint x, y; - - static gchar * histogram_info_names[] = - { - N_("Mean:"), - N_("Std Dev:"), - N_("Median:"), - N_("Pixels:"), - N_("Intensity:"), - N_("Count:"), - N_("Percentile:") - }; - - htd = g_new (HistogramToolDialog, 1); - htd->channel = GIMP_HISTOGRAM_VALUE; - htd->hist = gimp_histogram_new (); - - /* The shell and main vbox */ - htd->shell = gimp_dialog_new (_("Histogram"), "histogram", - tools_help_func, - tool_info[HISTOGRAM].private_tip, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("Close"), histogram_tool_close_callback, - htd, NULL, NULL, TRUE, TRUE, - - NULL); - - main_vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (htd->shell)->vbox), main_vbox); - - hbox = gtk_hbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - - /* The option menu for selecting channels */ - htd->channel_menu = gtk_hbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (vbox), htd->channel_menu, FALSE, FALSE, 0); - - label = gtk_label_new (_("Information on Channel:")); - gtk_box_pack_start (GTK_BOX (htd->channel_menu), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - option_menu = gimp_option_menu_new2 - (FALSE, histogram_tool_channel_callback, - htd, (gpointer) htd->channel, - - _("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, NULL, - _("Red"), (gpointer) GIMP_HISTOGRAM_RED, NULL, - _("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, NULL, - _("Blue"), (gpointer) GIMP_HISTOGRAM_BLUE, NULL, - - NULL); - gtk_box_pack_start (GTK_BOX (htd->channel_menu), option_menu, FALSE, FALSE, 0); - gtk_widget_show (option_menu); - - gtk_widget_show (htd->channel_menu); - - /* The histogram tool histogram */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - htd->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT); - gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->histogram)); - - gtk_signal_connect (GTK_OBJECT (htd->histogram), "range_changed", - GTK_SIGNAL_FUNC (histogram_tool_histogram_range), - htd); - - gtk_widget_show (GTK_WIDGET (htd->histogram)); - gtk_widget_show (frame); - - /* The gradient below the histogram */ - grad_hbox = gtk_hbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), grad_hbox, FALSE, FALSE, 0); - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (grad_hbox), frame, FALSE, FALSE, 0); - - htd->gradient = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (htd->gradient), - HISTOGRAM_WIDTH, GRADIENT_HEIGHT); - gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->gradient)); - gtk_widget_show (htd->gradient); - gtk_widget_show (frame); - gtk_widget_show (grad_hbox); - histogram_tool_gradient_draw (htd->gradient, GIMP_HISTOGRAM_VALUE); - - gtk_widget_show (vbox); - gtk_widget_show (hbox); - - /* The table containing histogram information */ - table = gtk_table_new (4, 4, TRUE); - gtk_table_set_col_spacings (GTK_TABLE (table), 6); - gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0); - - /* the labels for histogram information */ - for (i = 0; i < 7; i++) - { - y = (i % 4); - x = (i / 4) * 2; - - label = gtk_label_new (gettext(histogram_info_names[i])); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, x, x + 1, y, y + 1, - GTK_FILL, GTK_FILL, 2, 2); - gtk_widget_show (label); - - htd->info_labels[i] = gtk_label_new ("0"); - gtk_misc_set_alignment (GTK_MISC (htd->info_labels[i]), 0.0, 0.5); - gtk_table_attach (GTK_TABLE (table), htd->info_labels[i], - x + 1, x + 2, y, y + 1, - GTK_FILL, GTK_FILL, 2, 2); - gtk_widget_show (htd->info_labels[i]); - } - - gtk_widget_show (table); - - gtk_widget_show (main_vbox); - gtk_widget_show (htd->shell); - - return htd; -} - -static void -histogram_tool_close_callback (GtkWidget *widget, - gpointer data) -{ - HistogramToolDialog *htd; - - htd = (HistogramToolDialog *) data; - - gimp_dialog_hide (htd->shell); - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -histogram_tool_channel_callback (GtkWidget *widget, - gpointer data) -{ - HistogramToolDialog *htd; - - htd = (HistogramToolDialog *) data; - - gimp_menu_item_update (widget, &htd->channel); - - histogram_widget_channel (htd->histogram, htd->channel); - histogram_tool_gradient_draw (htd->gradient, htd->channel); -} - -static void -histogram_tool_gradient_draw (GtkWidget *gradient, - gint channel) -{ - guchar buf[HISTOGRAM_WIDTH * 3]; - guchar r, g, b; - gint i; - - r = g = b = 0; - switch (channel) - { - case GIMP_HISTOGRAM_VALUE: - case GIMP_HISTOGRAM_ALPHA: r = g = b = 1; - break; - case GIMP_HISTOGRAM_RED: r = 1; - break; - case GIMP_HISTOGRAM_GREEN: g = 1; - break; - case GIMP_HISTOGRAM_BLUE: b = 1; - break; - default: - g_warning ("unknown channel type, can't happen\n"); - break; - } - - for (i = 0; i < HISTOGRAM_WIDTH; i++) - { - buf[3*i+0] = i*r; - buf[3*i+1] = i*g; - buf[3*i+2] = i*b; - } - - for (i = 0; i < GRADIENT_HEIGHT; i++) - gtk_preview_draw_row (GTK_PREVIEW (gradient), - buf, 0, i, HISTOGRAM_WIDTH); - - gtk_widget_queue_draw (gradient); -} diff --git a/app/histogram_tool.h b/app/histogram_tool.h deleted file mode 100644 index ae4076b462..0000000000 --- a/app/histogram_tool.h +++ /dev/null @@ -1,64 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __HISTOGRAM_TOOL_H__ -#define __HISTOGRAM_TOOL_H__ - - -#define HISTOGRAM_WIDTH 256 -#define HISTOGRAM_HEIGHT 150 - -typedef struct _HistogramToolDialog HistogramToolDialog; - -struct _HistogramToolDialog -{ - GtkWidget *shell; - - GtkWidget *info_labels[7]; - GtkWidget *channel_menu; - HistogramWidget *histogram; - GimpHistogram *hist; - GtkWidget *gradient; - - gdouble mean; - gdouble std_dev; - gdouble median; - gdouble pixels; - gdouble count; - gdouble percentile; - - GimpDrawable *drawable; - ImageMap image_map; - gint channel; - gint color; -}; - - -/* histogram_tool functions */ -Tool * tools_new_histogram_tool (void); -void tools_free_histogram_tool (Tool *tool); - -void histogram_tool_initialize (GDisplay *gdisp); -void histogram_tool_free (void); -void histogram_tool_histogram_range (HistogramWidget *hw, - gint start, - gint end, - gpointer data); - - -#endif /* __HISTOGRAM_TOOL_H__ */ diff --git a/app/hue_saturation.c b/app/hue_saturation.c deleted file mode 100644 index a9ff87b362..0000000000 --- a/app/hue_saturation.c +++ /dev/null @@ -1,854 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gimage_mask.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "hue_saturation.h" -#include "image_map.h" -#include "pixel_region.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpcolorspace.h" -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -#define HUE_PARTITION_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK - -#define SLIDER_WIDTH 200 -#define DA_WIDTH 40 -#define DA_HEIGHT 20 - -#define HUE_PARTITION 0x0 -#define HUE_SLIDER 0x1 -#define LIGHTNESS_SLIDER 0x2 -#define SATURATION_SLIDER 0x4 -#define DRAW 0x40 -#define ALL 0xFF - -/* the hue-saturation structures */ - -typedef struct _HueSaturation HueSaturation; - -struct _HueSaturation -{ - gint x, y; /* coords for last mouse click */ -}; - - -/* hue saturation action functions */ -static void hue_saturation_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static HueSaturationDialog * hue_saturation_dialog_new (void); - -static void hue_saturation_update (HueSaturationDialog *hsd, - gint); -static void hue_saturation_preview (HueSaturationDialog *hsd); -static void hue_saturation_reset_callback (GtkWidget *, - gpointer); -static void hue_saturation_ok_callback (GtkWidget *, - gpointer); -static void hue_saturation_cancel_callback (GtkWidget *, - gpointer); -static void hue_saturation_partition_callback (GtkWidget *, - gpointer); -static void hue_saturation_preview_update (GtkWidget *, - gpointer); -static void hue_saturation_hue_adjustment_update (GtkAdjustment *, - gpointer); -static void hue_saturation_lightness_adjustment_update (GtkAdjustment *, - gpointer); -static void hue_saturation_saturation_adjustment_update (GtkAdjustment *, - gpointer); -static gint hue_saturation_hue_partition_events (GtkWidget *, - GdkEvent *, - HueSaturationDialog *hsd); - - -/* the hue-saturation tool options */ -static ToolOptions *hue_saturation_options = NULL; - -/* the hue-saturation tool dialog */ -static HueSaturationDialog *hue_saturation_dialog = NULL; - -/* Local variables */ -static gint hue_transfer[6][256]; -static gint lightness_transfer[6][256]; -static gint saturation_transfer[6][256]; -static gint default_colors[6][3] = -{ - { 255, 0, 0 }, - { 255, 255, 0 }, - { 0, 255, 0 }, - { 0, 255, 255 }, - { 0, 0, 255 }, - { 255, 0, 255 } -}; - - -/* hue saturation machinery */ - -void -hue_saturation_calculate_transfers (HueSaturationDialog *hsd) -{ - gint value; - gint hue; - gint i; - - /* Calculate transfers */ - for (hue = 0; hue < 6; hue++) - for (i = 0; i < 256; i++) - { - value = (hsd->hue[0] + hsd->hue[hue + 1]) * 255.0 / 360.0; - if ((i + value) < 0) - hue_transfer[hue][i] = 255 + (i + value); - else if ((i + value) > 255) - hue_transfer[hue][i] = i + value - 255; - else - hue_transfer[hue][i] = i + value; - - /* Lightness */ - value = (hsd->lightness[0] + hsd->lightness[hue + 1]) * 127.0 / 100.0; - value = CLAMP (value, -255, 255); - if (value < 0) - lightness_transfer[hue][i] = (unsigned char) ((i * (255 + value)) / 255); - else - lightness_transfer[hue][i] = (unsigned char) (i + ((255 - i) * value) / 255); - - /* Saturation */ - value = (hsd->saturation[0] + hsd->saturation[hue + 1]) * 255.0 / 100.0; - value = CLAMP (value, -255, 255); - - /* This change affects the way saturation is computed. With the - old code (different code for value < 0), increasing the - saturation affected muted colors very much, and bright colors - less. With the new code, it affects muted colors and bright - colors more or less evenly. For enhancing the color in photos, - the new behavior is exactly what you want. It's hard for me - to imagine a case in which the old behavior is better. - */ - saturation_transfer[hue][i] = CLAMP ((i * (255 + value)) / 255, 0, 255); - } -} - -void -hue_saturation (PixelRegion *srcPR, - PixelRegion *destPR, - void *user_data) -{ - HueSaturationDialog *hsd; - unsigned char *src, *s; - unsigned char *dest, *d; - int alpha; - int w, h; - int r, g, b; - int hue; - - hsd = (HueSaturationDialog *) user_data; - - /* Set the transfer arrays (for speed) */ - h = srcPR->h; - src = srcPR->data; - dest = destPR->data; - alpha = (srcPR->bytes == 4) ? TRUE : FALSE; - - while (h--) - { - w = srcPR->w; - s = src; - d = dest; - while (w--) - { - r = s[RED_PIX]; - g = s[GREEN_PIX]; - b = s[BLUE_PIX]; - - gimp_rgb_to_hls_int (&r, &g, &b); - - if (r < 43) - hue = 0; - else if (r < 85) - hue = 1; - else if (r < 128) - hue = 2; - else if (r < 171) - hue = 3; - else if (r < 213) - hue = 4; - else - hue = 5; - - r = hue_transfer[hue][r]; - g = lightness_transfer[hue][g]; - b = saturation_transfer[hue][b]; - - gimp_hls_to_rgb_int (&r, &g, &b); - - d[RED_PIX] = r; - d[GREEN_PIX] = g; - d[BLUE_PIX] = b; - - if (alpha) - d[ALPHA_PIX] = s[ALPHA_PIX]; - - s += srcPR->bytes; - d += destPR->bytes; - } - - src += srcPR->rowstride; - dest += destPR->rowstride; - } -} - -/* hue saturation action functions */ - -static void -hue_saturation_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - hue_saturation_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_hue_saturation (void) -{ - Tool * tool; - HueSaturation * private; - - /* The tool options */ - if (!hue_saturation_options) - { - hue_saturation_options = tool_options_new (_("Hue-Saturation")); - tools_register (HUE_SATURATION, hue_saturation_options); - } - - tool = tools_new_tool (HUE_SATURATION); - private = g_new0 (HueSaturation, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = hue_saturation_control; - - return tool; -} - -void -hue_saturation_dialog_hide (void) -{ - if (hue_saturation_dialog) - hue_saturation_cancel_callback (NULL, (gpointer) hue_saturation_dialog); -} - -void -tools_free_hue_saturation (Tool *tool) -{ - HueSaturation * color_bal; - - color_bal = (HueSaturation *) tool->private; - - /* Close the hue saturation dialog */ - hue_saturation_dialog_hide (); - - g_free (color_bal); -} - -void -hue_saturation_initialize (GDisplay *gdisp) -{ - gint i; - - if (! gimp_drawable_is_rgb (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Hue-Saturation operates only on RGB color drawables.")); - return; - } - - /* The "hue-saturation" dialog */ - if (!hue_saturation_dialog) - hue_saturation_dialog = hue_saturation_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (hue_saturation_dialog->shell)) - gtk_widget_show (hue_saturation_dialog->shell); - - for (i = 0; i < 7; i++) - { - hue_saturation_dialog->hue[i] = 0.0; - hue_saturation_dialog->lightness[i] = 0.0; - hue_saturation_dialog->saturation[i] = 0.0; - } - - hue_saturation_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - hue_saturation_dialog->image_map = - image_map_create (gdisp, hue_saturation_dialog->drawable); - - hue_saturation_update (hue_saturation_dialog, ALL); -} - -void -hue_saturation_free (void) -{ - if (hue_saturation_dialog) - { - if (hue_saturation_dialog->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (hue_saturation_dialog->image_map); - active_tool->preserve = FALSE; - - hue_saturation_dialog->image_map = NULL; - } - gtk_widget_destroy (hue_saturation_dialog->shell); - } -} - -/***************************/ -/* Hue-Saturation dialog */ -/***************************/ - -static HueSaturationDialog * -hue_saturation_dialog_new (void) -{ - HueSaturationDialog *hsd; - GtkWidget *main_vbox; - GtkWidget *main_hbox; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *table; - GtkWidget *label; - GtkWidget *slider; - GtkWidget *abox; - GtkWidget *spinbutton; - GtkWidget *toggle; - GtkWidget *radio_button; - GtkWidget *frame; - GtkObject *data; - GSList *group = NULL; - gint i; - - gchar *hue_partition_names[] = - { - N_("Master"), - N_("R"), - N_("Y"), - N_("G"), - N_("C"), - N_("B"), - N_("M") - }; - - hsd = g_new (HueSaturationDialog, 1); - hsd->hue_partition = ALL_HUES; - hsd->preview = TRUE; - - /* The shell and main vbox */ - hsd->shell = gimp_dialog_new (_("Hue-Saturation"), "hue_saturation", - tools_help_func, NULL, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), hue_saturation_ok_callback, - hsd, NULL, NULL, TRUE, FALSE, - _("Reset"), hue_saturation_reset_callback, - hsd, NULL, NULL, FALSE, FALSE, - _("Cancel"), hue_saturation_cancel_callback, - hsd, NULL, NULL, FALSE, TRUE, - - NULL); - - main_vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (hsd->shell)->vbox), main_vbox); - - /* The main hbox containing hue partitions and sliders */ - main_hbox = gtk_hbox_new (FALSE, 12); - gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, FALSE, FALSE, 0); - - /* The table containing hue partitions */ - table = gtk_table_new (7, 2, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - gtk_box_pack_start (GTK_BOX (main_hbox), table, FALSE, FALSE, 0); - - /* the radio buttons for hue partitions */ - for (i = 0; i < 7; i++) - { - radio_button = gtk_radio_button_new_with_label (group, gettext (hue_partition_names[i])); - group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button)); - gtk_object_set_data (GTK_OBJECT (radio_button), "hue_partition", - (gpointer) i); - - if (!i) - { - gtk_table_attach (GTK_TABLE (table), radio_button, 0, 2, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - } - else - { - gtk_table_attach (GTK_TABLE (table), radio_button, 0, 1, i, i + 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_table_attach (GTK_TABLE (table), frame, 1, 2, i, i + 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - hsd->hue_partition_da[i - 1] = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (hsd->hue_partition_da[i - 1]), - DA_WIDTH, DA_HEIGHT); - gtk_widget_set_events (hsd->hue_partition_da[i - 1], - HUE_PARTITION_MASK); - gtk_signal_connect (GTK_OBJECT (hsd->hue_partition_da[i - 1]), "event", - GTK_SIGNAL_FUNC (hue_saturation_hue_partition_events), - hsd); - gtk_container_add (GTK_CONTAINER (frame), hsd->hue_partition_da[i - 1]); - - gtk_widget_show (hsd->hue_partition_da[i - 1]); - gtk_widget_show (frame); - } - - gtk_signal_connect (GTK_OBJECT (radio_button), "toggled", - GTK_SIGNAL_FUNC (hue_saturation_partition_callback), - hsd); - - gtk_widget_show (radio_button); - } - - gtk_widget_show (table); - - /* The vbox for the table and preview toggle */ - vbox = gtk_vbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Hue / Lightness / Saturation Adjustments")); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* The table containing sliders */ - table = gtk_table_new (3, 3, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - /* Create the hue scale widget */ - label = gtk_label_new (_("Hue:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - data = gtk_adjustment_new (0, -180, 180.0, 1.0, 1.0, 0.0); - hsd->hue_data = GTK_ADJUSTMENT (data); - - slider = gtk_hscale_new (hsd->hue_data); - gtk_widget_set_usize (slider, SLIDER_WIDTH, -1); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 0, 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - - abox = gtk_vbox_new (FALSE, 0); - spinbutton = gtk_spin_button_new (hsd->hue_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 74, -1); - gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0); - gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_signal_connect (GTK_OBJECT (hsd->hue_data), "value_changed", - GTK_SIGNAL_FUNC (hue_saturation_hue_adjustment_update), - hsd); - - gtk_widget_show (label); - gtk_widget_show (slider); - gtk_widget_show (spinbutton); - gtk_widget_show (abox); - - /* Create the lightness scale widget */ - label = gtk_label_new (_("Lightness:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 1.0, 0.0); - hsd->lightness_data = GTK_ADJUSTMENT (data); - - slider = gtk_hscale_new (hsd->lightness_data); - gtk_widget_set_usize (slider, SLIDER_WIDTH, -1); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 1, 2, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - - abox = gtk_vbox_new (FALSE, 0); - spinbutton = gtk_spin_button_new (hsd->lightness_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0); - gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_signal_connect (GTK_OBJECT (hsd->lightness_data), "value_changed", - GTK_SIGNAL_FUNC (hue_saturation_lightness_adjustment_update), - hsd); - - gtk_widget_show (label); - gtk_widget_show (slider); - gtk_widget_show (spinbutton); - gtk_widget_show (abox); - - /* Create the saturation scale widget */ - label = gtk_label_new (_("Saturation:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 1.0, 0.0); - hsd->saturation_data = GTK_ADJUSTMENT (data); - - slider = gtk_hscale_new (hsd->saturation_data); - gtk_widget_set_usize (slider, SLIDER_WIDTH, -1); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 2, 3, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - - abox = gtk_vbox_new (FALSE, 0); - spinbutton = gtk_spin_button_new (hsd->saturation_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0); - gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 2, 3, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - - gtk_signal_connect (GTK_OBJECT (hsd->saturation_data), "value_changed", - GTK_SIGNAL_FUNC (hue_saturation_saturation_adjustment_update), - hsd); - - gtk_widget_show (label); - gtk_widget_show (slider); - gtk_widget_show (spinbutton); - gtk_widget_show (abox); - - gtk_widget_show (table); - - /* Horizontal box for preview toggle button */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* The preview toggle */ - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), hsd->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (hue_saturation_preview_update), - hsd); - - gtk_widget_show (toggle); - gtk_widget_show (hbox); - - gtk_widget_show (vbox); - gtk_widget_show (main_hbox); - gtk_widget_show (main_vbox); - gtk_widget_show (hsd->shell); - - return hsd; -} - -static void -hue_saturation_update (HueSaturationDialog *hsd, - gint update) -{ - gint i, j, b; - gint rgb[3]; - guchar buf[DA_WIDTH * 3]; - - if (update & HUE_SLIDER) - { - gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->hue_data), - hsd->hue[hsd->hue_partition]); - } - if (update & LIGHTNESS_SLIDER) - { - gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->lightness_data), - hsd->lightness[hsd->hue_partition]); - } - if (update & SATURATION_SLIDER) - { - gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->saturation_data), - hsd->saturation[hsd->hue_partition]); - } - - hue_saturation_calculate_transfers (hsd); - - for (i = 0; i < 6; i++) - { - rgb[RED_PIX] = default_colors[i][RED_PIX]; - rgb[GREEN_PIX] = default_colors[i][GREEN_PIX]; - rgb[BLUE_PIX] = default_colors[i][BLUE_PIX]; - - gimp_rgb_to_hls_int (rgb, rgb + 1, rgb + 2); - - rgb[RED_PIX] = hue_transfer[i][rgb[RED_PIX]]; - rgb[GREEN_PIX] = lightness_transfer[i][rgb[GREEN_PIX]]; - rgb[BLUE_PIX] = saturation_transfer[i][rgb[BLUE_PIX]]; - - gimp_hls_to_rgb_int (rgb, rgb + 1, rgb + 2); - - for (j = 0; j < DA_WIDTH; j++) - for (b = 0; b < 3; b++) - buf[j * 3 + b] = (guchar) rgb[b]; - - for (j = 0; j < DA_HEIGHT; j++) - gtk_preview_draw_row (GTK_PREVIEW (hsd->hue_partition_da[i]), - buf, 0, j, DA_WIDTH); - - if (update & DRAW) - gtk_widget_draw (hsd->hue_partition_da[i], NULL); - } -} - -static void -hue_saturation_preview (HueSaturationDialog *hsd) -{ - if (!hsd->image_map) - { - g_warning ("hue_saturation_preview(): No image map"); - return; - } - - active_tool->preserve = TRUE; - image_map_apply (hsd->image_map, hue_saturation, (void *) hsd); - active_tool->preserve = FALSE; -} - -static void -hue_saturation_reset_callback (GtkWidget *widget, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - hsd->hue[hsd->hue_partition] = 0.0; - hsd->lightness[hsd->hue_partition] = 0.0; - hsd->saturation[hsd->hue_partition] = 0.0; - - hue_saturation_update (hsd, ALL); - - if (hsd->preview) - hue_saturation_preview (hsd); -} - -static void -hue_saturation_ok_callback (GtkWidget *widget, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - gimp_dialog_hide (hsd->shell); - - active_tool->preserve = TRUE; - - if (!hsd->preview) - image_map_apply (hsd->image_map, hue_saturation, (gpointer) hsd); - - if (hsd->image_map) - image_map_commit (hsd->image_map); - - active_tool->preserve = FALSE; - - hsd->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -hue_saturation_cancel_callback (GtkWidget *widget, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - gimp_dialog_hide (hsd->shell); - - if (hsd->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (hsd->image_map); - active_tool->preserve = FALSE; - - gdisplays_flush (); - hsd->image_map = NULL; - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -hue_saturation_partition_callback (GtkWidget *widget, - gpointer data) -{ - HueSaturationDialog *hsd; - HueRange partition; - - hsd = (HueSaturationDialog *) data; - - partition = (HueRange) gtk_object_get_data (GTK_OBJECT (widget), - "hue_partition"); - hsd->hue_partition = partition; - - hue_saturation_update (hsd, ALL); -} - -static void -hue_saturation_preview_update (GtkWidget *widget, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - hsd->preview = TRUE; - hue_saturation_preview (hsd); - } - else - { - hsd->preview = FALSE; - if (hsd->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (hsd->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } -} - -static void -hue_saturation_hue_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - if (hsd->hue[hsd->hue_partition] != adjustment->value) - { - hsd->hue[hsd->hue_partition] = adjustment->value; - hue_saturation_update (hsd, DRAW); - - if (hsd->preview) - hue_saturation_preview (hsd); - } -} - -static void -hue_saturation_lightness_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - if (hsd->lightness[hsd->hue_partition] != adjustment->value) - { - hsd->lightness[hsd->hue_partition] = adjustment->value; - hue_saturation_update (hsd, DRAW); - - if (hsd->preview) - hue_saturation_preview (hsd); - } -} - -static void -hue_saturation_saturation_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - HueSaturationDialog *hsd; - - hsd = (HueSaturationDialog *) data; - - if (hsd->saturation[hsd->hue_partition] != adjustment->value) - { - hsd->saturation[hsd->hue_partition] = adjustment->value; - hue_saturation_update (hsd, DRAW); - - if (hsd->preview) - hue_saturation_preview (hsd); - } -} - -static gint -hue_saturation_hue_partition_events (GtkWidget *widget, - GdkEvent *event, - HueSaturationDialog *hsd) -{ - switch (event->type) - { - case GDK_EXPOSE: - hue_saturation_update (hsd, HUE_PARTITION); - break; - - default: - break; - } - - return FALSE; -} diff --git a/app/hue_saturation.h b/app/hue_saturation.h deleted file mode 100644 index 5fec88fa53..0000000000 --- a/app/hue_saturation.h +++ /dev/null @@ -1,71 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __HUE_SATURATION_H__ -#define __HUE_SATURATION_H__ - - -typedef enum -{ - ALL_HUES, - RED_HUES, - YELLOW_HUES, - GREEN_HUES, - CYAN_HUES, - BLUE_HUES, - MAGENTA_HUES -} HueRange; - -typedef struct _HueSaturationDialog HueSaturationDialog; - -struct _HueSaturationDialog -{ - GtkWidget *shell; - - GtkWidget *hue_partition_da[6]; - - GtkAdjustment *hue_data; - GtkAdjustment *lightness_data; - GtkAdjustment *saturation_data; - - GimpDrawable *drawable; - ImageMap image_map; - - gdouble hue[7]; - gdouble lightness[7]; - gdouble saturation[7]; - - HueRange hue_partition; - gboolean preview; -}; - - -Tool * tools_new_hue_saturation (void); -void tools_free_hue_saturation (Tool *tool); - -void hue_saturation_initialize (GDisplay *gdisp); -void hue_saturation_free (void); -void hue_saturation_dialog_hide (void); -void hue_saturation (PixelRegion *srcPR, - PixelRegion *destPR, - void *data); - -void hue_saturation_calculate_transfers (HueSaturationDialog *hsd); - - -#endif /* __HUE_SATURATION_H__ */ diff --git a/app/info_window.c b/app/info_window.c index a5179d9ca7..478fe313bb 100644 --- a/app/info_window.c +++ b/app/info_window.c @@ -34,7 +34,8 @@ #include "info_dialog.h" #include "info_window.h" #include "scroll.h" -#include "tools.h" + +#include "tools/tools.h" #include "pdb/procedural_db.h" diff --git a/app/ink.c b/app/ink.c deleted file mode 100644 index 262abfe40c..0000000000 --- a/app/ink.c +++ /dev/null @@ -1,1618 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "draw_core.h" -#include "gimage_mask.h" -#include "gimpcontext.h" -#include "gimpimage.h" -#include "gimprc.h" -#include "gimpui.h" -#include "ink.h" -#include "paint_options.h" -#include "tools.h" -#include "undo.h" -#include "blob.h" -#include "gdisplay.h" -#include "paint_funcs.h" -#include "pixel_region.h" -#include "temp_buf.h" -#include "tile.h" -#include "tile_manager.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -#define SUBSAMPLE 8 - -#define DIST_SMOOTHER_BUFFER 10 -#define TIME_SMOOTHER_BUFFER 10 - -/* the Ink structures */ - -typedef Blob * (* BlobFunc) (gdouble, - gdouble, - gdouble, - gdouble, - gdouble, - gdouble); - - -typedef struct _InkTool InkTool; - -struct _InkTool -{ - DrawCore *core; /* Core select object */ - - Blob *last_blob; /* blob for last cursor position */ - - gint x1, y1; /* image space coordinate */ - gint x2, y2; /* image space coords */ - - /* circular distance history buffer */ - gdouble dt_buffer[DIST_SMOOTHER_BUFFER]; - gint dt_index; - - /* circular timing history buffer */ - guint32 ts_buffer[TIME_SMOOTHER_BUFFER]; - gint ts_index; - - gdouble last_time; /* previous time of a motion event */ - gdouble lastx, lasty; /* previous position of a motion event */ - - gboolean init_velocity; -}; - -typedef struct _BrushWidget BrushWidget; - -struct _BrushWidget -{ - GtkWidget *widget; - gboolean state; -}; - -typedef struct _InkOptions InkOptions; - -struct _InkOptions -{ - PaintOptions paint_options; - - gdouble size; - gdouble size_d; - GtkObject *size_w; - - gdouble sensitivity; - gdouble sensitivity_d; - GtkObject *sensitivity_w; - - gdouble vel_sensitivity; - gdouble vel_sensitivity_d; - GtkObject *vel_sensitivity_w; - - gdouble tilt_sensitivity; - gdouble tilt_sensitivity_d; - GtkObject *tilt_sensitivity_w; - - gdouble tilt_angle; - gdouble tilt_angle_d; - GtkObject *tilt_angle_w; - - BlobFunc function; - BlobFunc function_d; - GtkWidget *function_w[3]; /* 3 radio buttons */ - - gdouble aspect; - gdouble aspect_d; - gdouble angle; - gdouble angle_d; - BrushWidget *brush_w; -}; - - -/* local function prototypes */ - -static void ink_button_press (Tool *tool, - GdkEventButton *mevent, - GDisplay *gdisp); -static void ink_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void ink_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void ink_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void ink_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static void time_smoother_add (InkTool *ink_tool, - guint32 value); -static gdouble time_smoother_result (InkTool *ink_tool); -static void time_smoother_init (InkTool *ink_tool, - guint32 initval); -static void dist_smoother_add (InkTool *ink_tool, - gdouble value); -static gdouble dist_smoother_result (InkTool *ink_tool); -static void dist_smoother_init (InkTool *ink_tool, - gdouble initval); - -static void ink_init (InkTool *ink_tool, - GimpDrawable *drawable, - gdouble x, - gdouble y); -static void ink_finish (InkTool *ink_tool, - GimpDrawable *drawable, - gint tool_id); -static void ink_cleanup (void); - -static void ink_type_update (GtkWidget *radio_button, - BlobFunc function); -static GdkPixmap * blob_pixmap (GdkColormap *colormap, - GdkVisual *visual, - BlobFunc function); -static void paint_blob (GdkDrawable *drawable, - GdkGC *gc, - Blob *blob); - -/* Rendering functions */ -static void ink_set_paint_area (InkTool *ink_tool, - GimpDrawable *drawable, - Blob *blob); -static void ink_paste (InkTool *ink_tool, - GimpDrawable *drawable, - Blob *blob); - -static void ink_to_canvas_tiles (InkTool *ink_tool, - Blob *blob, - guchar *color); - -static void ink_set_undo_tiles (GimpDrawable *drawable, - gint x, - gint y, - gint w, - gint h); -static void ink_set_canvas_tiles (gint x, - gint y, - gint w, - gint h); - -/* Brush pseudo-widget callbacks */ -static void brush_widget_active_rect (BrushWidget *brush_widget, - GtkWidget *widget, - GdkRectangle *rect); -static void brush_widget_realize (GtkWidget *widget); -static void brush_widget_expose (GtkWidget *widget, - GdkEventExpose *event, - BrushWidget *brush_widget); -static void brush_widget_button_press (GtkWidget *widget, - GdkEventButton *event, - BrushWidget *brush_widget); -static void brush_widget_button_release (GtkWidget *widget, - GdkEventButton *event, - BrushWidget *brush_widget); -static void brush_widget_motion_notify (GtkWidget *widget, - GdkEventMotion *event, - BrushWidget *brush_widget); - - -/* local variables */ - -/* the ink tool options */ -static InkOptions *ink_options = NULL; - -/* undo blocks variables */ -static TileManager *undo_tiles = NULL; - -/* Tiles used to render the stroke at 1 byte/pp */ -static TileManager *canvas_tiles = NULL; - -/* Flat buffer that is used to used to render the dirty region - * for composition onto the destination drawable - */ -static TempBuf *canvas_buf = NULL; - - -/* functions */ - -static void -ink_type_update (GtkWidget *radio_button, - BlobFunc function) -{ - InkOptions *options = ink_options; - - if (GTK_TOGGLE_BUTTON (radio_button)->active) - options->function = function; - - gtk_widget_queue_draw (options->brush_w->widget); -} - -static void -ink_options_reset (void) -{ - InkOptions *options = ink_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->size_w), - options->size_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->sensitivity_w), - options->sensitivity_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->tilt_sensitivity_w), - options->tilt_sensitivity_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->vel_sensitivity_w), - options->vel_sensitivity_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->tilt_angle_w), - options->tilt_angle_d); - gtk_toggle_button_set_active (((options->function_d == blob_ellipse) ? - GTK_TOGGLE_BUTTON (options->function_w[0]) : - ((options->function_d == blob_square) ? - GTK_TOGGLE_BUTTON (options->function_w[1]) : - GTK_TOGGLE_BUTTON (options->function_w[2]))), - TRUE); - options->aspect = options->aspect_d; - options->angle = options->angle_d; - gtk_widget_queue_draw (options->brush_w->widget); -} - -static InkOptions * -ink_options_new (void) -{ - InkOptions *options; - - GtkWidget *table; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *hbox2; - GtkWidget *radio_button; - GtkWidget *pixmap_widget; - GtkWidget *slider; - GtkWidget *frame; - GtkWidget *darea; - GdkPixmap *pixmap; - - /* the new ink tool options structure */ - options = g_new (InkOptions, 1); - paint_options_init ((PaintOptions *) options, - INK, - ink_options_reset); - options->size = options->size_d = 4.4; - options->sensitivity = options->sensitivity_d = 1.0; - options->vel_sensitivity = options->vel_sensitivity_d = 0.8; - options->tilt_sensitivity = options->tilt_sensitivity_d = 0.4; - options->tilt_angle = options->tilt_angle_d = 0.0; - options->function = options->function_d = blob_ellipse; - options->aspect = options->aspect_d = 1.0; - options->angle = options->angle_d = 0.0; - - /* the main vbox */ - vbox = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (((ToolOptions *) options)->main_vbox), vbox, - TRUE, TRUE, 0); - gtk_widget_show (vbox); - - /* adjust sliders */ - frame = gtk_frame_new (_("Adjustment")); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); - gtk_widget_show (frame); - - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 4); - gtk_container_set_border_width (GTK_CONTAINER (table), 2); - gtk_container_add (GTK_CONTAINER (frame), table); - gtk_widget_show (table); - - /* size slider */ - options->size_w = - gtk_adjustment_new (options->size_d, 0.0, 20.0, 1.0, 2.0, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->size_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, - _("Size:"), 1.0, 1.0, - slider, 1, FALSE); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->size_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->size); - - /* angle adjust slider */ - options->tilt_angle_w = - gtk_adjustment_new (options->tilt_angle_d, -90.0, 90.0, 1, 10.0, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->tilt_angle_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Angle:"), 1.0, 1.0, - slider, 1, FALSE); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->tilt_angle_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->tilt_angle); - - /* sens sliders */ - frame = gtk_frame_new (_("Sensitivity")); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); - gtk_widget_show (frame); - - table = gtk_table_new (3, 2, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 4); - gtk_container_set_border_width (GTK_CONTAINER (table), 2); - gtk_container_add (GTK_CONTAINER (frame), table); - gtk_widget_show (table); - - /* size sens slider */ - options->sensitivity_w = - gtk_adjustment_new (options->sensitivity_d, 0.0, 1.0, 0.01, 0.1, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->sensitivity_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Size:"), 1.0, 1.0, - slider, 1, FALSE); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->sensitivity_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->sensitivity); - - /* tilt sens slider */ - options->tilt_sensitivity_w = - gtk_adjustment_new (options->tilt_sensitivity_d, 0.0, 1.0, 0.01, 0.1, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->tilt_sensitivity_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, - _("Tilt:"), 1.0, 1.0, - slider, 1, FALSE); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->tilt_sensitivity_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->tilt_sensitivity); - - /* velocity sens slider */ - options->vel_sensitivity_w = - gtk_adjustment_new (options->vel_sensitivity_d, 0.0, 1.0, 0.01, 0.1, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->vel_sensitivity_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 3, - _("Speed:"), 1.0, 1.0, - slider, 1, FALSE); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->vel_sensitivity_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->vel_sensitivity); - - /* bottom hbox */ - hbox = gtk_hbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); - gtk_widget_show (hbox); - - /* Brush type radiobuttons */ - frame = gtk_frame_new (_("Type")); - gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); - gtk_widget_show (frame); - - hbox2 = gtk_hbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (frame), hbox2); - - vbox = gtk_vbox_new (FALSE, 2); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 2); - gtk_box_pack_start (GTK_BOX (hbox2), vbox, FALSE, FALSE, 0); - gtk_widget_show (vbox); - - pixmap = blob_pixmap (gtk_widget_get_colormap (vbox), - gtk_widget_get_visual (vbox), - blob_ellipse); - - pixmap_widget = gtk_pixmap_new (pixmap, NULL); - gdk_pixmap_unref (pixmap); - gtk_misc_set_padding (GTK_MISC (pixmap_widget), 6, 0); - - radio_button = gtk_radio_button_new (NULL); - gtk_signal_connect (GTK_OBJECT (radio_button), "toggled", - GTK_SIGNAL_FUNC (ink_type_update), - (gpointer)blob_ellipse); - - gtk_container_add (GTK_CONTAINER (radio_button), pixmap_widget); - gtk_box_pack_start (GTK_BOX (vbox), radio_button, FALSE, FALSE, 0); - - options->function_w[0] = radio_button; - - pixmap = blob_pixmap (gtk_widget_get_colormap (vbox), - gtk_widget_get_visual (vbox), - blob_square); - - pixmap_widget = gtk_pixmap_new (pixmap, NULL); - gdk_pixmap_unref (pixmap); - gtk_misc_set_padding (GTK_MISC (pixmap_widget), 6, 0); - - radio_button = - gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio_button)); - gtk_signal_connect (GTK_OBJECT (radio_button), "toggled", - GTK_SIGNAL_FUNC (ink_type_update), - (gpointer)blob_square); - - gtk_container_add (GTK_CONTAINER (radio_button), pixmap_widget); - gtk_box_pack_start (GTK_BOX (vbox), radio_button, FALSE, FALSE, 0); - - options->function_w[1] = radio_button; - - pixmap = blob_pixmap (gtk_widget_get_colormap (vbox), - gtk_widget_get_visual (vbox), - blob_diamond); - - pixmap_widget = gtk_pixmap_new (pixmap, NULL); - gdk_pixmap_unref (pixmap); - gtk_misc_set_padding (GTK_MISC (pixmap_widget), 6, 0); - - radio_button = - gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio_button)); - gtk_signal_connect (GTK_OBJECT (radio_button), "toggled", - GTK_SIGNAL_FUNC (ink_type_update), - (gpointer)blob_diamond); - - gtk_container_add (GTK_CONTAINER (radio_button), pixmap_widget); - gtk_box_pack_start (GTK_BOX (vbox), radio_button, FALSE, FALSE, 0); - - options->function_w[2] = radio_button; - - /* Brush shape widget */ - frame = gtk_frame_new (_("Shape")); - gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); - gtk_widget_show (frame); - - vbox = gtk_vbox_new (FALSE, 2); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 2); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - - frame = gtk_aspect_frame_new (NULL, 0.0, 0.5, 1.0, FALSE); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); - - options->brush_w = g_new (BrushWidget, 1); - options->brush_w->state = FALSE; - - darea = gtk_drawing_area_new(); - options->brush_w->widget = darea; - - gtk_drawing_area_size (GTK_DRAWING_AREA (darea), 60, 60); - gtk_container_add (GTK_CONTAINER (frame), darea); - - gtk_widget_set_events (darea, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK | GDK_EXPOSURE_MASK); - gtk_signal_connect (GTK_OBJECT (darea), "button_press_event", - GTK_SIGNAL_FUNC (brush_widget_button_press), - options->brush_w); - gtk_signal_connect (GTK_OBJECT (darea), "button_release_event", - GTK_SIGNAL_FUNC (brush_widget_button_release), - options->brush_w); - gtk_signal_connect (GTK_OBJECT (darea), "motion_notify_event", - GTK_SIGNAL_FUNC (brush_widget_motion_notify), - options->brush_w); - gtk_signal_connect (GTK_OBJECT (darea), "expose_event", - GTK_SIGNAL_FUNC (brush_widget_expose), - options->brush_w); - gtk_signal_connect (GTK_OBJECT (darea), "realize", - GTK_SIGNAL_FUNC (brush_widget_realize), - options->brush_w); - - gtk_widget_show_all (hbox); - - return options; -} - - -/* the brush widget functions */ - -static void -brush_widget_active_rect (BrushWidget *brush_widget, - GtkWidget *widget, - GdkRectangle *rect) -{ - int x,y; - int r; - - r = MIN (widget->allocation.width, widget->allocation.height) / 2; - - x = widget->allocation.width / 2 + 0.85 * r * ink_options->aspect / 10.0 * - cos (ink_options->angle); - y = widget->allocation.height / 2 + 0.85 * r * ink_options->aspect / 10.0 * - sin (ink_options->angle); - - rect->x = x - 5; - rect->y = y - 5; - rect->width = 10; - rect->height = 10; -} - -static void -brush_widget_realize (GtkWidget *widget) -{ - gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); -} - -static void -brush_widget_draw_brush (BrushWidget *brush_widget, - GtkWidget *widget, - gdouble xc, - gdouble yc, - gdouble radius) -{ - Blob *blob; - - blob = ink_options->function (xc, yc, - radius * cos (ink_options->angle), - radius * sin (ink_options->angle), - (- (radius / ink_options->aspect) * - sin (ink_options->angle)), - ((radius / ink_options->aspect) * - cos (ink_options->angle))); - - paint_blob (widget->window, widget->style->fg_gc[widget->state], blob); - g_free (blob); -} - -static void -brush_widget_expose (GtkWidget *widget, - GdkEventExpose *event, - BrushWidget *brush_widget) -{ - GdkRectangle rect; - int r0; - - r0 = MIN (widget->allocation.width, widget->allocation.height) / 2; - - if (r0 < 2) - return; - - gdk_window_clear_area (widget->window, 0, 0, - widget->allocation.width, - widget->allocation.height); - brush_widget_draw_brush (brush_widget, widget, - widget->allocation.width / 2, - widget->allocation.height / 2, - 0.9 * r0); - - brush_widget_active_rect (brush_widget, widget, &rect); - gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL], - TRUE, /* filled */ - rect.x, rect.y, - rect.width, rect.height); - gtk_draw_shadow (widget->style, widget->window, widget->state, GTK_SHADOW_OUT, - rect.x, rect.y, - rect.width, rect.height); -} - -static void -brush_widget_button_press (GtkWidget *widget, - GdkEventButton *event, - BrushWidget *brush_widget) -{ - GdkRectangle rect; - - brush_widget_active_rect (brush_widget, widget, &rect); - - if ((event->x >= rect.x) && (event->x-rect.x < rect.width) && - (event->y >= rect.y) && (event->y-rect.y < rect.height)) - { - brush_widget->state = TRUE; - - gtk_grab_add (brush_widget->widget); - } -} - -static void -brush_widget_button_release (GtkWidget *widget, - GdkEventButton *event, - BrushWidget *brush_widget) -{ - brush_widget->state = FALSE; - - gtk_grab_remove (brush_widget->widget); -} - -static void -brush_widget_motion_notify (GtkWidget *widget, - GdkEventMotion *event, - BrushWidget *brush_widget) -{ - int x; - int y; - int r0; - int rsquare; - - if (brush_widget->state) - { - x = event->x - widget->allocation.width / 2; - y = event->y - widget->allocation.height / 2; - rsquare = x*x + y*y; - - if (rsquare != 0) - { - ink_options->angle = atan2 (y, x); - - r0 = MIN (widget->allocation.width, widget->allocation.height) / 2; - ink_options->aspect = - 10.0 * sqrt ((double) rsquare / (r0 * r0)) / 0.85; - - if (ink_options->aspect < 1.0) - ink_options->aspect = 1.0; - if (ink_options->aspect > 10.0) - ink_options->aspect = 10.0; - - gtk_widget_draw (widget, NULL); - } - } -} - -/* - * Return a black-on white pixmap in the given colormap and - * visual that represents the BlobFunc 'function' - */ -static GdkPixmap * -blob_pixmap (GdkColormap *colormap, - GdkVisual *visual, - BlobFunc function) -{ - GdkPixmap *pixmap; - GdkGC *black_gc, *white_gc; - GdkColor tmp_color; - Blob *blob; - - pixmap = gdk_pixmap_new (NULL, 22, 21, visual->depth); - - black_gc = gdk_gc_new (pixmap); - gdk_color_black (colormap, &tmp_color); - gdk_gc_set_foreground (black_gc, &tmp_color); - - white_gc = gdk_gc_new (pixmap); - gdk_color_white (colormap, &tmp_color); - gdk_gc_set_foreground (white_gc, &tmp_color); - - gdk_draw_rectangle (pixmap, white_gc, TRUE, 0, 0, 21, 20); - gdk_draw_rectangle (pixmap, black_gc, FALSE, 0, 0, 21, 20); - blob = (*function) (10, 10, 8, 0, 0, 8); - paint_blob (pixmap, black_gc, blob); - g_free (blob); - - gdk_gc_unref (white_gc); - gdk_gc_unref (black_gc); - - return pixmap; -} - -/* - * Draw a blob onto a drawable with the specified graphics context - */ -static void -paint_blob (GdkDrawable *drawable, GdkGC *gc, - Blob *blob) -{ - int i; - - for (i=0;iheight;i++) - { - if (blob->data[i].left <= blob->data[i].right) - gdk_draw_line (drawable, gc, - blob->data[i].left,i+blob->y, - blob->data[i].right+1,i+blob->y); - } -} - - -static Blob * -ink_pen_ellipse (gdouble x_center, gdouble y_center, - gdouble pressure, gdouble xtilt, gdouble ytilt, - gdouble velocity) -{ - double size; - double tsin, tcos; - double aspect, radmin; - double x,y; - double tscale; - double tscale_c; - double tscale_s; - - /* Adjust the size depending on pressure. */ - - size = ink_options->size * (1.0 + ink_options->sensitivity * - (2.0 * pressure - 1.0) ); - - /* Adjust the size further depending on pointer velocity - and velocity-sensitivity. These 'magic constants' are - 'feels natural' tigert-approved. --ADM */ - - if (velocity < 3.0) - velocity = 3.0; - -#ifdef VERBOSE - g_print("%f (%f) -> ", (float)size, (float)velocity); -#endif - - size = ink_options->vel_sensitivity * - ((4.5 * size) / (1.0 + ink_options->vel_sensitivity * (2.0*(velocity)))) - + (1.0 - ink_options->vel_sensitivity) * size; - -#ifdef VERBOSE - g_print("%f\n", (float)size); -#endif - - /* Clamp resulting size to sane limits */ - - if (size > ink_options->size * (1.0 + ink_options->sensitivity)) - size = ink_options->size * (1.0 + ink_options->sensitivity); - - if (size*SUBSAMPLE < 1.0) size = 1.0/SUBSAMPLE; - - /* Add brush angle/aspect to tilt vectorially */ - - /* I'm not happy with the way the brush widget info is combined with - tilt info from the brush. My personal feeling is that representing - both as affine transforms would make the most sense. -RLL */ - - tscale = ink_options->tilt_sensitivity * 10.0; - tscale_c = tscale * cos (gimp_deg_to_rad (ink_options->tilt_angle)); - tscale_s = tscale * sin (gimp_deg_to_rad (ink_options->tilt_angle)); - x = ink_options->aspect*cos(ink_options->angle) + - xtilt * tscale_c - ytilt * tscale_s; - y = ink_options->aspect*sin(ink_options->angle) + - ytilt * tscale_c + xtilt * tscale_s; -#ifdef VERBOSE - g_print ("angle %g aspect %g; %g %g; %g %g\n", - ink_options->angle, ink_options->aspect, tscale_c, tscale_s, x, y); -#endif - aspect = sqrt(x*x+y*y); - - if (aspect != 0) - { - tcos = x/aspect; - tsin = y/aspect; - } - else - { - tsin = sin(ink_options->angle); - tcos = cos(ink_options->angle); - } - - if (aspect < 1.0) - aspect = 1.0; - else if (aspect > 10.0) - aspect = 10.0; - - radmin = SUBSAMPLE * size/aspect; - if (radmin < 1.0) radmin = 1.0; - - return ink_options->function (x_center * SUBSAMPLE, y_center * SUBSAMPLE, - radmin*aspect*tcos, radmin*aspect*tsin, - -radmin*tsin, radmin*tcos); -} - -static void -ink_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - gdouble x, y; - InkTool *ink_tool; - GimpDrawable *drawable; - Blob *b; - - ink_tool = (InkTool *) tool->private; - - /* Keep the coordinates of the target */ - gdisplay_untransform_coords_f (gdisp, bevent->x, bevent->y, - &x, &y, TRUE); - drawable = gimp_image_active_drawable (gdisp->gimage); - - ink_init (ink_tool, drawable, x, y); - - tool->state = ACTIVE; - tool->gdisp = gdisp; - tool->paused_count = 0; - - /* pause the current selection and grab the pointer */ - gdisplays_selection_visibility (gdisp->gimage, SelectionPause); - - /* add motion memory if you press mod1 first ^ perfectmouse */ - if (((bevent->state & GDK_MOD1_MASK) != 0) != (perfectmouse != 0)) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - else - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->gdisp = gdisp; - tool->state = ACTIVE; - - b = ink_pen_ellipse (x, y, - bevent->pressure, bevent->xtilt, bevent->ytilt, 10.0); - - ink_paste (ink_tool, drawable, b); - ink_tool->last_blob = b; - - time_smoother_init (ink_tool, bevent->time); - ink_tool->last_time = bevent->time; - dist_smoother_init (ink_tool, 0.0); - ink_tool->init_velocity = TRUE; - ink_tool->lastx = x; - ink_tool->lasty = y; - - gdisplay_flush_now (gdisp); -} - -static void -ink_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - GImage *gimage; - InkTool *ink_tool; - - gimage = gdisp->gimage; - ink_tool = (InkTool *) tool->private; - - /* resume the current selection and ungrab the pointer */ - gdisplays_selection_visibility (gdisp->gimage, SelectionResume); - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - /* Set tool state to inactive -- no longer painting */ - tool->state = INACTIVE; - - /* free the last blob */ - g_free (ink_tool->last_blob); - ink_tool->last_blob = NULL; - - ink_finish (ink_tool, gimp_image_active_drawable (gdisp->gimage), tool->ID); - gdisplays_flush (); -} - - -static void -dist_smoother_init (InkTool* ink_tool, gdouble initval) -{ - gint i; - - ink_tool->dt_index = 0; - - for (i=0; idt_buffer[i] = initval; - } -} - -static gdouble -dist_smoother_result (InkTool* ink_tool) -{ - gint i; - gdouble result = 0.0; - - for (i=0; idt_buffer[i]; - } - - return (result / (gdouble)DIST_SMOOTHER_BUFFER); -} - -static void -dist_smoother_add (InkTool* ink_tool, gdouble value) -{ - ink_tool->dt_buffer[ink_tool->dt_index] = value; - - if ((++ink_tool->dt_index) == DIST_SMOOTHER_BUFFER) - ink_tool->dt_index = 0; -} - - -static void -time_smoother_init (InkTool* ink_tool, guint32 initval) -{ - gint i; - - ink_tool->ts_index = 0; - - for (i=0; its_buffer[i] = initval; - } -} - -static gdouble -time_smoother_result (InkTool* ink_tool) -{ - gint i; - guint64 result = 0; - - for (i=0; its_buffer[i]; - } - -#ifdef _MSC_VER - return (gdouble) (gint64) (result / TIME_SMOOTHER_BUFFER); -#else - return (result / TIME_SMOOTHER_BUFFER); -#endif -} - -static void -time_smoother_add (InkTool* ink_tool, guint32 value) -{ - ink_tool->ts_buffer[ink_tool->ts_index] = value; - - if ((++ink_tool->ts_index) == TIME_SMOOTHER_BUFFER) - ink_tool->ts_index = 0; -} - - -static void -ink_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - InkTool *ink_tool; - GimpDrawable *drawable; - Blob *b, *blob_union; - - gdouble x, y; - gdouble pressure; - gdouble velocity; - gdouble dist; - gdouble lasttime, thistime; - - ink_tool = (InkTool *) tool->private; - - gdisplay_untransform_coords_f (gdisp, mevent->x, mevent->y, &x, &y, TRUE); - drawable = gimp_image_active_drawable (gdisp->gimage); - - lasttime = ink_tool->last_time; - - time_smoother_add (ink_tool, mevent->time); - thistime = ink_tool->last_time = - time_smoother_result(ink_tool); - - /* The time resolution on X-based GDK motion events is - bloody awful, hence the use of the smoothing function. - Sadly this also means that there is always the chance of - having an indeterminite velocity since this event and - the previous several may still appear to issue at the same - instant. -ADM */ - - if (thistime == lasttime) - thistime = lasttime + 1; - - if (ink_tool->init_velocity) - { - dist_smoother_init (ink_tool, dist = sqrt((ink_tool->lastx-x)*(ink_tool->lastx-x) + - (ink_tool->lasty-y)*(ink_tool->lasty-y))); - ink_tool->init_velocity = FALSE; - } - else - { - dist_smoother_add (ink_tool, sqrt((ink_tool->lastx-x)*(ink_tool->lastx-x) + - (ink_tool->lasty-y)*(ink_tool->lasty-y))); - dist = dist_smoother_result(ink_tool); - } - - ink_tool->lastx = x; - ink_tool->lasty = y; - - pressure = mevent->pressure; - velocity = 10.0 * sqrt((dist) / (double)(thistime - lasttime)); - - b = ink_pen_ellipse (x, y, pressure, mevent->xtilt, mevent->ytilt, velocity); - blob_union = blob_convex_union (ink_tool->last_blob, b); - g_free (ink_tool->last_blob); - ink_tool->last_blob = b; - - ink_paste (ink_tool, drawable, blob_union); - g_free (blob_union); - - gdisplay_flush_now (gdisp); -} - -static void -ink_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Layer *layer; - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; - gint x, y; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &x, &y, FALSE, FALSE); - if ((layer = gimp_image_get_active_layer (gdisp->gimage))) - { - int off_x, off_y; - - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); - - if (x >= off_x && y >= off_y && - x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && - y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) - { - /* One more test--is there a selected region? - * if so, is cursor inside? - */ - if (gimage_mask_is_empty (gdisp->gimage)) - ctype = GIMP_MOUSE_CURSOR; - else if (gimage_mask_value (gdisp->gimage, x, y)) - ctype = GIMP_MOUSE_CURSOR; - } - } - gdisplay_install_tool_cursor (gdisp, ctype, - INK, - CURSOR_MODIFIER_NONE, - FALSE); -} - -static void -ink_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - InkTool *ink_tool; - - ink_tool = (InkTool *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (ink_tool->core, tool); - break; - - case RESUME: - draw_core_resume (ink_tool->core, tool); - break; - - case HALT: - ink_cleanup (); - break; - - default: - break; - } -} - -static void -ink_init (InkTool *ink_tool, - GimpDrawable *drawable, - gdouble x, - gdouble y) -{ - /* free the block structures */ - if (undo_tiles) - tile_manager_destroy (undo_tiles); - if (canvas_tiles) - tile_manager_destroy (canvas_tiles); - - /* Allocate the undo structure */ - undo_tiles = tile_manager_new (gimp_drawable_width (drawable), - gimp_drawable_height (drawable), - gimp_drawable_bytes (drawable)); - - /* Allocate the canvas blocks structure */ - canvas_tiles = tile_manager_new (gimp_drawable_width (drawable), - gimp_drawable_height (drawable), 1); - - /* Get the initial undo extents */ - ink_tool->x1 = ink_tool->x2 = x; - ink_tool->y1 = ink_tool->y2 = y; -} - -static void -ink_finish (InkTool *ink_tool, - GimpDrawable *drawable, - gint tool_id) -{ - /* push an undo */ - drawable_apply_image (drawable, ink_tool->x1, ink_tool->y1, - ink_tool->x2, ink_tool->y2, undo_tiles, TRUE); - undo_tiles = NULL; - - /* invalidate the drawable--have to do it here, because - * it is not done during the actual painting. - */ - gimp_drawable_invalidate_preview (drawable, TRUE); -} - -static void -ink_cleanup (void) -{ - /* CLEANUP */ - /* If the undo tiles exist, nuke them */ - if (undo_tiles) - { - tile_manager_destroy (undo_tiles); - undo_tiles = NULL; - } - - /* If the canvas blocks exist, nuke them */ - if (canvas_tiles) - { - tile_manager_destroy (canvas_tiles); - canvas_tiles = NULL; - } - - /* Free the temporary buffer if it exist */ - if (canvas_buf) - temp_buf_free (canvas_buf); - canvas_buf = NULL; -} - -/********************************* - * Rendering functions * - *********************************/ - -/* Some of this stuff should probably be combined with the - * code it was copied from in paint_core.c; but I wanted - * to learn this stuff, so I've kept it simple. - * - * The following only supports CONSTANT mode. Incremental - * would, I think, interact strangely with the way we - * do things. But it wouldn't be hard to implement at all. - */ - -static void -ink_set_paint_area (InkTool *ink_tool, - GimpDrawable *drawable, - Blob *blob) -{ - gint x, y, width, height; - gint x1, y1, x2, y2; - gint bytes; - - blob_bounds (blob, &x, &y, &width, &height); - - bytes = gimp_drawable_has_alpha (drawable) ? - gimp_drawable_bytes (drawable) : gimp_drawable_bytes (drawable) + 1; - - x1 = CLAMP (x/SUBSAMPLE - 1, 0, gimp_drawable_width (drawable)); - y1 = CLAMP (y/SUBSAMPLE - 1, 0, gimp_drawable_height (drawable)); - x2 = CLAMP ((x + width)/SUBSAMPLE + 2, 0, gimp_drawable_width (drawable)); - y2 = CLAMP ((y + height)/SUBSAMPLE + 2, 0, gimp_drawable_height (drawable)); - - /* configure the canvas buffer */ - if ((x2 - x1) && (y2 - y1)) - canvas_buf = temp_buf_resize (canvas_buf, bytes, x1, y1, - (x2 - x1), (y2 - y1)); -} - -enum { ROW_START, ROW_STOP }; - -/* The insertion sort here, for SUBSAMPLE = 8, tends to beat out - * qsort() by 4x with CFLAGS=-O2, 2x with CFLAGS=-g - */ -static void -insert_sort (gint *data, - gint n) -{ - gint i, j, k; - gint tmp1, tmp2; - - for (i=2; i<2*n; i+=2) - { - tmp1 = data[i]; - tmp2 = data[i+1]; - j = 0; - while (data[j] < tmp1) - j += 2; - - for (k=i; k>j; k-=2) - { - data[k] = data[k-2]; - data[k+1] = data[k-1]; - } - - data[j] = tmp1; - data[j+1] = tmp2; - } -} - -static void -fill_run (guchar *dest, - guchar alpha, - gint w) -{ - if (alpha == 255) - { - memset (dest, 255, w); - } - else - { - while (w--) - { - *dest = MAX(*dest, alpha); - dest++; - } - } -} - -static void -render_blob_line (Blob *blob, - guchar *dest, - gint x, - gint y, - gint width) -{ - gint buf[4*SUBSAMPLE]; - gint *data = buf; - gint n = 0; - gint i, j; - gint current = 0; /* number of filled rows at this point - * in the scan line - */ - gint last_x; - - /* Sort start and ends for all lines */ - - j = y * SUBSAMPLE - blob->y; - for (i=0; i= blob->height) - break; - if ((j > 0) && (blob->data[j].left <= blob->data[j].right)) - { - data[2*n] = blob->data[j].left; - data[2*n+1] = ROW_START; - data[2*SUBSAMPLE+2*n] = blob->data[j].right; - data[2*SUBSAMPLE+2*n+1] = ROW_STOP; - n++; - } - j++; - } - - /* If we have less than SUBSAMPLE rows, compress */ - if (n < SUBSAMPLE) - { - for (i=0; i<2*n; i++) - data[2*n+i] = data[2*SUBSAMPLE+i]; - } - - /* Now count start and end separately */ - n *= 2; - - insert_sort (data, n); - - /* Discard portions outside of tile */ - - while ((n > 0) && (data[0] < SUBSAMPLE*x)) - { - if (data[1] == ROW_START) - current++; - else - current--; - data += 2; - n--; - } - - while ((n > 0) && (data[2*(n-1)] >= SUBSAMPLE*(x+width))) - n--; - - /* Render the row */ - - last_x = 0; - for (i=0; ih; - s = dest->data; - - for (i=0; ix, dest->y + i, dest->w); - s += dest->rowstride; - } - } -} - -static void -ink_paste (InkTool *ink_tool, - GimpDrawable *drawable, - Blob *blob) -{ - GImage *gimage; - PixelRegion srcPR; - gint offx, offy; - gchar col[MAX_CHANNELS]; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - /* Get the the buffer */ - ink_set_paint_area (ink_tool, drawable, blob); - - /* check to make sure there is actually a canvas to draw on */ - if (!canvas_buf) - return; - - gimp_image_get_foreground (gimage, drawable, col); - - /* set the alpha channel */ - col[canvas_buf->bytes - 1] = OPAQUE_OPACITY; - - /* color the pixels */ - color_pixels (temp_buf_data (canvas_buf), col, - canvas_buf->width * canvas_buf->height, canvas_buf->bytes); - - /* set undo blocks */ - ink_set_undo_tiles (drawable, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - /* initialize any invalid canvas tiles */ - ink_set_canvas_tiles (canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - ink_to_canvas_tiles (ink_tool, blob, col); - - /* initialize canvas buf source pixel regions */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - /* apply the paint area to the gimage */ - gimp_image_apply_image (gimage, drawable, &srcPR, - FALSE, - (int) (gimp_context_get_opacity (NULL) * 255), - gimp_context_get_paint_mode (NULL), - undo_tiles, /* specify an alternative src1 */ - canvas_buf->x, canvas_buf->y); - - /* Update the undo extents */ - ink_tool->x1 = MIN (ink_tool->x1, canvas_buf->x); - ink_tool->y1 = MIN (ink_tool->y1, canvas_buf->y); - ink_tool->x2 = MAX (ink_tool->x2, (canvas_buf->x + canvas_buf->width)); - ink_tool->y2 = MAX (ink_tool->y2, (canvas_buf->y + canvas_buf->height)); - - /* Update the gimage--it is important to call gdisplays_update_area - * instead of drawable_update because we don't want the drawable - * preview to be constantly invalidated - */ - gimp_drawable_offsets (drawable, &offx, &offy); - gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, - canvas_buf->width, canvas_buf->height); -} - -/* This routine a) updates the representation of the stroke - * in the canvas tiles, then renders the dirty bit of it - * into canvas_buf. - */ -static void -ink_to_canvas_tiles (InkTool *ink_tool, - Blob *blob, - guchar *color) -{ - PixelRegion srcPR, maskPR; - - /* draw the blob on the canvas tiles */ - pixel_region_init (&srcPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, TRUE); - - render_blob (&srcPR, blob); - - /* combine the canvas tiles and the canvas buf */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - pixel_region_init (&maskPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, FALSE); - - /* apply the canvas tiles to the canvas buf */ - apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); -} - -static void -ink_set_undo_tiles (GimpDrawable *drawable, - int x, int y, int w, int h) -{ - int i, j; - Tile *src_tile; - Tile *dest_tile; - - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - { - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - dest_tile = tile_manager_get_tile (undo_tiles, j, i, FALSE, FALSE); - if (tile_is_valid (dest_tile) == FALSE) - { - src_tile = tile_manager_get_tile (gimp_drawable_data (drawable), - j, i, TRUE, FALSE); - tile_manager_map_tile (undo_tiles, j, i, src_tile); - tile_release (src_tile, FALSE); - } - } - } -} - - -static void -ink_set_canvas_tiles (gint x, - gint y, - gint w, - gint h) -{ - gint i, j; - Tile *tile; - - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - { - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (canvas_tiles, j, i, FALSE, FALSE); - if (tile_is_valid (tile) == FALSE) - { - tile = tile_manager_get_tile (canvas_tiles, j, i, TRUE, TRUE); - memset (tile_data_pointer (tile, 0, 0), - 0, - tile_size (tile)); - tile_release (tile, TRUE); - } - } - } -} - -/**************************/ -/* Global ink functions */ -/**************************/ - -void -ink_no_draw (Tool *tool) -{ - return; -} - -Tool * -tools_new_ink (void) -{ - Tool *tool; - InkTool *private; - - /* The tool options */ - if (! ink_options) - { - ink_options = ink_options_new (); - tools_register (INK, (ToolOptions *) ink_options); - - /* press all default buttons */ - ink_options_reset (); - } - - tool = tools_new_tool (INK); - private = g_new0 (InkTool, 1); - - private->core = draw_core_new (ink_no_draw); - private->last_blob = NULL; - - tool->private = private; - - tool->button_press_func = ink_button_press; - tool->button_release_func = ink_button_release; - tool->motion_func = ink_motion; - tool->cursor_update_func = ink_cursor_update; - tool->control_func = ink_control; - - return tool; -} - -void -tools_free_ink (Tool *tool) -{ - InkTool *ink_tool; - - ink_tool = (InkTool *) tool->private; - - /* Make sure the selection core is not visible */ - if (tool->state == ACTIVE && ink_tool->core) - draw_core_stop (ink_tool->core, tool); - - /* Free the selection core */ - if (ink_tool->core) - draw_core_free (ink_tool->core); - - /* Free the last blob, if any */ - if (ink_tool->last_blob) - g_free (ink_tool->last_blob); - - /* Cleanup memory */ - ink_cleanup (); - - /* Free the paint core */ - g_free (ink_tool); -} diff --git a/app/ink.h b/app/ink.h deleted file mode 100644 index 9c35db1c6b..0000000000 --- a/app/ink.h +++ /dev/null @@ -1,31 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __INK_H__ -#define __INK_H__ - - -Tool * tools_new_ink (void); -void tools_free_ink (Tool *tool); - - -/* Procedure definition and marshalling function */ -extern ProcRecord ink_proc; - - -#endif /* __INK_H__ */ diff --git a/app/interface.c b/app/interface.c index 40c5dab1fe..89eb1d20dc 100644 --- a/app/interface.c +++ b/app/interface.c @@ -54,7 +54,8 @@ #include "session.h" #include "pixel_region.h" #include "tile_manager.h" -#include "tools.h" + +#include "tools/tools.h" #include "pixmaps.h" #include "pixmaps/qmasksel.xpm" diff --git a/app/iscissors.c b/app/iscissors.c deleted file mode 100644 index 0486618a77..0000000000 --- a/app/iscissors.c +++ /dev/null @@ -1,1975 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* This tool is based on a paper from SIGGRAPH '95: - * "Intelligent Scissors for Image Composition", Eric N. Mortensen and - * William A. Barrett, Brigham Young University. - * - * thanks to Professor D. Forsyth for prompting us to implement this tool. */ - -/* The history of this implementation is lonog and varied. It was - * orignally done by Spencer and Peter, and worked fine in the 0.54 - * (motif only) release of the gimp. Later revisions (0.99.something - * until about 1.1.4) completely changed the algorithm used, until it - * bore little resemblance to the one described in the paper above. - * The 0.54 version of the algorithm was then forwards ported to 1.1.4 - * by Austin Donnelly. - */ - -/* Livewire boundary implementation done by Laramie Leavitt */ - - -#include "config.h" - -#include - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" -#include "channel.h" -#include "cursorutil.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "iscissors.h" -#include "edit_selection.h" -#include "paint_funcs.h" -#include "pixel_region.h" -#include "selection_options.h" -#include "temp_buf.h" -#include "tools.h" -#include "bezier_selectP.h" -#include "scan_convert.h" -#include "tile.h" -#include "tile_manager.h" - -#include "libgimp/gimpmath.h" - - -/* local structures */ - -typedef struct _ICurve ICurve; - -struct _ICurve -{ - int x1, y1; - int x2, y2; - GPtrArray *points; -}; - -/* The possible states... */ -typedef enum -{ - NO_ACTION, - SEED_PLACEMENT, - SEED_ADJUSTMENT, - WAITING -} Iscissors_state; - -/* The possible drawing states... */ -typedef enum -{ - DRAW_NOTHING = 0x0, - DRAW_CURRENT_SEED = 0x1, - DRAW_CURVE = 0x2, - DRAW_ACTIVE_CURVE = 0x4, - DRAW_LIVEWIRE = 0x8 -} Iscissors_draw; - -#define DRAW_ALL (DRAW_CURRENT_SEED | DRAW_CURVE) - -typedef struct _iscissors Iscissors; - -struct _iscissors -{ - DrawCore *core; /* Core select object */ - - SelectOps op; - - gint x, y; /* upper left hand coordinate */ - gint ix, iy; /* initial coordinates */ - gint nx, ny; /* new coordinates */ - - TempBuf *dp_buf; /* dynamic programming buffer */ - - ICurve *livewire; /* livewire boundary curve */ - - ICurve *curve1; /* 1st curve connected to current point */ - ICurve *curve2; /* 2nd curve connected to current point */ - - GSList *curves; /* the list of curves */ - - gboolean first_point; /* is this the first point? */ - gboolean connected; /* is the region closed? */ - - Iscissors_state state; /* state of iscissors */ - Iscissors_draw draw; /* items to draw on a draw request */ - - /* XXX might be useful */ - Channel *mask; /* selection mask */ - TileManager *gradient_map; /* lazily filled gradient map */ -}; - -typedef struct _IScissorsOptions IScissorsOptions; - -struct _IScissorsOptions -{ - SelectionOptions selection_options; -}; - - -/**********************************************/ -/* Intelligent scissors selection apparatus */ - - -/* Other defines... */ -#define MAX_GRADIENT 179.606 /* == sqrt(127^2 + 127^2) */ -#define GRADIENT_SEARCH 32 /* how far to look when snapping to an edge */ -#define TARGET_HEIGHT 25 -#define TARGET_WIDTH 25 -#define POINT_WIDTH 8 /* size (in pixels) of seed handles */ -#define POINT_HALFWIDTH (POINT_WIDTH / 2) -#define EXTEND_BY 0.2 /* proportion to expand cost map by */ -#define FIXED 5 /* additional fixed size to expand cost map */ -#define MIN_GRADIENT 63 /* gradients < this are directionless */ - -#define MAX_POINTS 2048 - -#define COST_WIDTH 2 /* number of bytes for each pixel in cost map */ -#define BLOCK_WIDTH 64 -#define BLOCK_HEIGHT 64 -#define CONV_WIDTH (BLOCK_WIDTH + 2) -#define CONV_HEIGHT (BLOCK_HEIGHT + 2) - -/* weight to give between gradient (_G) and direction (_D) */ -#define OMEGA_D 0.2 -#define OMEGA_G 0.8 - -/* sentinel to mark seed point in ?cost? map */ -#define SEED_POINT 9 - -/* Functional defines */ -#define PIXEL_COST(x) (x >> 8) -#define PIXEL_DIR(x) (x & 0x000000ff) - - -/* static variables */ - -/* where to move on a given link direction */ -static gint move [8][2] = -{ - { 1, 0 }, - { 0, 1 }, - { -1, 1 }, - { 1, 1 }, - { -1, 0 }, - { 0, -1 }, - { 1, -1 }, - { -1, -1 }, -}; - -/* IE: - * '---+---+---` - * | 7 | 5 | 6 | - * +---+---+---+ - * | 4 | | 0 | - * +---+---+---+ - * | 2 | 1 | 3 | - * `---+---+---' - */ - -/* points for drawing curves */ -static GdkPoint curve_points [MAX_POINTS]; - - -/* temporary convolution buffers -- */ -static guchar maxgrad_conv0 [TILE_WIDTH * TILE_HEIGHT * 4] = ""; -static guchar maxgrad_conv1 [TILE_WIDTH * TILE_HEIGHT * 4] = ""; -static guchar maxgrad_conv2 [TILE_WIDTH * TILE_HEIGHT * 4] = ""; - - -static gint horz_deriv [9] = -{ - 1, 0, -1, - 2, 0, -2, - 1, 0, -1, -}; - -static gint vert_deriv [9] = -{ - 1, 2, 1, - 0, 0, 0, - -1, -2, -1, -}; - - -static gint blur_32 [9] = -{ - 1, 1, 1, - 1, 24, 1, - 1, 1, 1, -}; - -static gfloat distance_weights [GRADIENT_SEARCH * GRADIENT_SEARCH]; - -static gint diagonal_weight [256]; -static gint direction_value [256][4]; -static gboolean initialized = FALSE; -static Tile *cur_tile = NULL; - - -/***********************************************************************/ -/* static variables */ - -static IScissorsOptions *iscissors_options = NULL; - - -/***********************************************************************/ -/* Local function prototypes */ - -static void iscissors_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void iscissors_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void iscissors_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void iscissors_oper_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void iscissors_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -static void iscissors_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void iscissors_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static void iscissors_reset (Iscissors *iscissors); -static void iscissors_draw (Tool *tool); - -static TileManager * gradient_map_new (GImage *gimage); - -static void find_optimal_path (TileManager *gradient_map, - TempBuf *dp_buf, - gint x1, - gint y1, - gint x2, - gint y2, - gint xs, - gint ys); -static void find_max_gradient (Iscissors *iscissors, - GImage *gimage, - gint *x, - gint *y); -static void calculate_curve (Tool *tool, - ICurve *curve); -static void iscissors_draw_curve (GDisplay *gdisp, - Iscissors *iscissors, - ICurve *curve); -static void iscissors_free_icurves (GSList *list); -static void iscissors_free_buffers (Iscissors *iscissors); - -static gint mouse_over_vertex (Iscissors *iscissors, - gint x, - gint y); -static gboolean clicked_on_vertex (Tool *tool); -static GSList * mouse_over_curve (Iscissors *iscissors, - gint x, - gint y); -static gboolean clicked_on_curve (Tool *tool); - -static void precalculate_arrays (void); -static GPtrArray * plot_pixels (Iscissors *iscissors, - TempBuf *dp_buf, - gint x1, - gint y1, - gint xs, - gint ys, - gint xe, - gint ye); - - -static void -iscissors_options_reset (void) -{ - IScissorsOptions *options = iscissors_options; - - selection_options_reset ((SelectionOptions *) options); -} - -static IScissorsOptions * -iscissors_options_new (void) -{ - IScissorsOptions *options; - - /* the new intelligent scissors tool options structure */ - options = g_new (IScissorsOptions, 1); - selection_options_init ((SelectionOptions *) options, - ISCISSORS, - iscissors_options_reset); - - return options; -} - -Tool * -tools_new_iscissors (void) -{ - Tool * tool; - Iscissors * private; - - if (!iscissors_options) - { - iscissors_options = iscissors_options_new (); - tools_register (ISCISSORS, (ToolOptions *) iscissors_options); - } - - tool = tools_new_tool (ISCISSORS); - private = g_new0 (Iscissors, 1); - - private->core = draw_core_new (iscissors_draw); - private->op = -1; - private->curves = NULL; - private->dp_buf = NULL; - private->state = NO_ACTION; - private->mask = NULL; - private->gradient_map = NULL; - private->livewire = NULL; - - tool->auto_snap_to = FALSE; /* Don't snap to guides */ - - tool->private = (void *) private; - - tool->button_press_func = iscissors_button_press; - tool->button_release_func = iscissors_button_release; - tool->motion_func = iscissors_motion; - tool->oper_update_func = iscissors_oper_update; - tool->modifier_key_func = iscissors_modifier_update; - tool->cursor_update_func = iscissors_cursor_update; - tool->control_func = iscissors_control; - - iscissors_reset (private); - - return tool; -} - -void -tools_free_iscissors (Tool *tool) -{ - Iscissors * iscissors; - - iscissors = (Iscissors *) tool->private; - - if (tool->state == ACTIVE) - draw_core_stop (iscissors->core, tool); - draw_core_free (iscissors->core); - - iscissors_reset (iscissors); - - g_free (iscissors); -} - - -/* Local functions */ - -static void -iscissors_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - GimpDrawable *drawable; - Iscissors *iscissors; - gboolean grab_pointer = FALSE; - - iscissors = (Iscissors *) tool->private; - drawable = gimp_image_active_drawable (gdisp->gimage); - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &iscissors->x, &iscissors->y, FALSE, FALSE); - - /* If the tool was being used in another image...reset it */ - - if (tool->state == ACTIVE && gdisp != tool->gdisp) - { - draw_core_stop (iscissors->core, tool); - iscissors_reset (iscissors); - } - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - switch (iscissors->state) - { - case NO_ACTION: - iscissors->state = SEED_PLACEMENT; - iscissors->draw = DRAW_CURRENT_SEED; - grab_pointer = TRUE; - - if (! (bevent->state & GDK_SHIFT_MASK)) - find_max_gradient (iscissors, gdisp->gimage, - &iscissors->x, &iscissors->y); - - iscissors->x = CLAMP (iscissors->x, 0, gdisp->gimage->width - 1); - iscissors->y = CLAMP (iscissors->y, 0, gdisp->gimage->height - 1); - - iscissors->ix = iscissors->x; - iscissors->iy = iscissors->y; - - /* Initialize the selection core only on starting the tool */ - draw_core_start (iscissors->core, gdisp->canvas->window, tool); - break; - - default: - /* Check if the mouse click occured on a vertex or the curve itself */ - if (clicked_on_vertex (tool)) - { - iscissors->nx = iscissors->x; - iscissors->ny = iscissors->y; - iscissors->state = SEED_ADJUSTMENT; - iscissors->draw = DRAW_ACTIVE_CURVE; - - if (((SelectionOptions *) iscissors_options)->interactive) - iscissors->draw |= DRAW_LIVEWIRE; - - draw_core_resume (iscissors->core, tool); - grab_pointer = TRUE; - } - /* If the iscissors is connected, check if the click was inside */ - else if (iscissors->connected && iscissors->mask && - channel_value (iscissors->mask, iscissors->x, iscissors->y)) - { - /* Undraw the curve */ - tool->state = INACTIVE; - iscissors->draw = DRAW_CURVE; - draw_core_stop (iscissors->core, tool); - - if (iscissors->op == SELECTION_REPLACE) - gimage_mask_clear (gdisp->gimage); - else - gimage_mask_undo (gdisp->gimage); - - if (((SelectionOptions *) iscissors_options)->feather) - channel_feather (iscissors->mask, - gimp_image_get_mask (gdisp->gimage), - ((SelectionOptions *) iscissors_options)->feather_radius, - ((SelectionOptions *) iscissors_options)->feather_radius, - iscissors->op, 0, 0); - else - channel_combine_mask (gimp_image_get_mask (gdisp->gimage), - iscissors->mask, iscissors->op, 0, 0); - - iscissors_reset (iscissors); - - gdisplays_flush (); - } - /* if we're not connected, we're adding a new point */ - else if (!iscissors->connected) - { - iscissors->state = SEED_PLACEMENT; - iscissors->draw = DRAW_CURRENT_SEED; - - if (((SelectionOptions *) iscissors_options)->interactive) - iscissors->draw |= DRAW_LIVEWIRE; - - grab_pointer = TRUE; - - draw_core_resume (iscissors->core, tool); - } - break; - } - - if (grab_pointer) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); -} - - -static void -iscissors_convert (Iscissors *iscissors, - GDisplay *gdisp) -{ - ScanConverter *sc; - ScanConvertPoint *pts; - guint npts; - GSList *list; - ICurve *icurve; - guint packed; - gint i; - gint index; - - sc = scan_converter_new (gdisp->gimage->width, gdisp->gimage->height, 1); - - /* go over the curves in reverse order, adding the points we have */ - list = iscissors->curves; - index = g_slist_length (list); - while (index) - { - index--; - icurve = (ICurve *) g_slist_nth_data (list, index); - - npts = icurve->points->len; - pts = g_new (ScanConvertPoint, npts); - - for (i = 0; i < npts; i ++) - { - packed = GPOINTER_TO_INT (g_ptr_array_index (icurve->points, i)); - pts[i].x = packed & 0x0000ffff; - pts[i].y = packed >> 16; - } - - scan_converter_add_points (sc, npts, pts); - g_free (pts); - } - - if (iscissors->mask) - channel_delete (iscissors->mask); - - iscissors->mask = scan_converter_to_channel (sc, gdisp->gimage); - scan_converter_free (sc); - - channel_invalidate_bounds (iscissors->mask); -} - - -static void -iscissors_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - Iscissors *iscissors; - ICurve *curve; - - iscissors = (Iscissors *) tool->private; - - /* Make sure X didn't skip the button release event -- as it's known - * to do */ - if (iscissors->state == WAITING) - return; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); /* XXX why the flush? */ - - /* Undraw everything */ - switch (iscissors->state) - { - case SEED_PLACEMENT: - iscissors->draw = DRAW_CURVE | DRAW_CURRENT_SEED; - if (((SelectionOptions *) iscissors_options)->interactive) - iscissors->draw |= DRAW_LIVEWIRE; - break; - case SEED_ADJUSTMENT: - iscissors->draw = DRAW_CURVE | DRAW_ACTIVE_CURVE; - if (((SelectionOptions *) iscissors_options)->interactive) - iscissors->draw |= DRAW_LIVEWIRE; - break; - default: - break; - } - - draw_core_stop (iscissors->core, tool); - - /* First take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - /* Progress to the next stage of intelligent selection */ - switch (iscissors->state) - { - case SEED_PLACEMENT: - /* Add a new icurve */ - if (!iscissors->first_point) - { - /* Determine if we're connecting to the first point */ - if (iscissors->curves) - { - curve = (ICurve *) iscissors->curves->data; - if (abs (iscissors->x - curve->x1) < POINT_HALFWIDTH && - abs (iscissors->y - curve->y1) < POINT_HALFWIDTH) - { - iscissors->x = curve->x1; - iscissors->y = curve->y1; - iscissors->connected = TRUE; - } - } - - /* Create the new curve segment */ - if (iscissors->ix != iscissors->x || - iscissors->iy != iscissors->y) - { - curve = g_new (ICurve, 1); - - curve->x1 = iscissors->ix; - curve->y1 = iscissors->iy; - iscissors->ix = curve->x2 = iscissors->x; - iscissors->iy = curve->y2 = iscissors->y; - curve->points = NULL; - iscissors->curves = g_slist_append (iscissors->curves, - (void *) curve); - calculate_curve (tool, curve); - } - } - else /* this was our first point */ - { - iscissors->first_point = FALSE; - } - break; - - case SEED_ADJUSTMENT: - /* recalculate both curves */ - if (iscissors->curve1) - { - iscissors->curve1->x1 = iscissors->nx; - iscissors->curve1->y1 = iscissors->ny; - calculate_curve (tool, iscissors->curve1); - } - if (iscissors->curve2) - { - iscissors->curve2->x2 = iscissors->nx; - iscissors->curve2->y2 = iscissors->ny; - calculate_curve (tool, iscissors->curve2); - } - break; - - default: - break; - } - } - - /* Draw only the boundary */ - iscissors->state = WAITING; - iscissors->draw = DRAW_CURVE; - draw_core_resume (iscissors->core, tool); - - /* convert the curves into a region */ - if (iscissors->connected) - iscissors_convert (iscissors, gdisp); -} - -static void -iscissors_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Iscissors *iscissors; - - iscissors = (Iscissors *) tool->private; - - if (tool->state != ACTIVE || iscissors->state == NO_ACTION) - return; - - if (iscissors->state == SEED_PLACEMENT) - { - iscissors->draw = DRAW_CURRENT_SEED; - - if (((SelectionOptions *) iscissors_options)->interactive) - iscissors->draw = DRAW_CURRENT_SEED | DRAW_LIVEWIRE; - } - else if (iscissors->state == SEED_ADJUSTMENT) - { - iscissors->draw = DRAW_ACTIVE_CURVE; - } - - draw_core_pause (iscissors->core, tool); - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &iscissors->x, &iscissors->y, FALSE, FALSE); - - switch (iscissors->state) - { - case SEED_PLACEMENT: - /* Hold the shift key down to disable the auto-edge snap feature */ - if (! (mevent->state & GDK_SHIFT_MASK)) - find_max_gradient (iscissors, gdisp->gimage, - &iscissors->x, &iscissors->y); - - iscissors->x = CLAMP (iscissors->x, 0, gdisp->gimage->width - 1); - iscissors->y = CLAMP (iscissors->y, 0, gdisp->gimage->height - 1); - - if (iscissors->first_point) - { - iscissors->ix = iscissors->x; - iscissors->iy = iscissors->y; - } - break; - - case SEED_ADJUSTMENT: - /* Move the current seed to the location of the cursor */ - if (! (mevent->state & GDK_SHIFT_MASK)) - find_max_gradient (iscissors, gdisp->gimage, - &iscissors->x, &iscissors->y); - - iscissors->x = CLAMP (iscissors->x, 0, gdisp->gimage->width - 1); - iscissors->y = CLAMP (iscissors->y, 0, gdisp->gimage->height - 1); - - iscissors->nx = iscissors->x; - iscissors->ny = iscissors->y; - break; - - default: - break; - } - - draw_core_resume (iscissors->core, tool); -} - - -static void -iscissors_draw (Tool *tool) -{ - GDisplay *gdisp; - Iscissors *iscissors; - ICurve *curve; - GSList *list; - gint tx1, ty1, tx2, ty2; - gint txn, tyn; - - gdisp = tool->gdisp; - iscissors = (Iscissors *) tool->private; - - gdisplay_transform_coords (gdisp, iscissors->ix, iscissors->iy, &tx1, &ty1, - FALSE); - - /* Draw the crosshairs target if we're placing a seed */ - if (iscissors->draw & DRAW_CURRENT_SEED) - { - gdisplay_transform_coords (gdisp, iscissors->x, iscissors->y, &tx2, &ty2, - FALSE); - - gdk_draw_line (iscissors->core->win, iscissors->core->gc, - tx2 - (TARGET_WIDTH >> 1), ty2, - tx2 + (TARGET_WIDTH >> 1), ty2); - gdk_draw_line (iscissors->core->win, iscissors->core->gc, - tx2, ty2 - (TARGET_HEIGHT >> 1), - tx2, ty2 + (TARGET_HEIGHT >> 1)); - - /* Draw a line boundary */ - if (!iscissors->first_point && !(iscissors->draw & DRAW_LIVEWIRE)) - { - gdk_draw_line (iscissors->core->win, iscissors->core->gc, - tx1, ty1, tx2, ty2); - } - } - - /* Draw the livewire boundary */ - if ((iscissors->draw & DRAW_LIVEWIRE) && !iscissors->first_point) - { - /* See if the mouse has moved. If so, create a new segment... */ - if (! iscissors->livewire || - (iscissors->livewire && - (iscissors->ix != iscissors->livewire->x1 || - iscissors->x != iscissors->livewire->x2 || - iscissors->iy != iscissors->livewire->y1 || - iscissors->y != iscissors->livewire->y2))) - { - curve = g_new (ICurve, 1); - - curve->x1 = iscissors->ix; - curve->y1 = iscissors->iy; - curve->x2 = iscissors->x; - curve->y2 = iscissors->y; - curve->points = NULL; - - if (iscissors->livewire) - { - if (iscissors->livewire->points) - g_ptr_array_free (iscissors->livewire->points, TRUE); - - g_free (iscissors->livewire); - - iscissors->livewire = NULL; - } - - iscissors->livewire = curve; - calculate_curve (tool, curve); - curve = NULL; - } - /* plot the curve */ - iscissors_draw_curve (gdisp, iscissors, iscissors->livewire); - } - - if ((iscissors->draw & DRAW_CURVE) && !iscissors->first_point) - { - /* Draw a point at the init point coordinates */ - if (!iscissors->connected) - gdk_draw_arc (iscissors->core->win, iscissors->core->gc, 1, - tx1 - POINT_HALFWIDTH, ty1 - POINT_HALFWIDTH, - POINT_WIDTH, POINT_WIDTH, 0, 23040); - - /* Go through the list of icurves, and render each one... */ - for (list = iscissors->curves; list; list = g_slist_next (list)) - { - curve = (ICurve *) list->data; - - /* plot the curve */ - iscissors_draw_curve (gdisp, iscissors, curve); - - gdisplay_transform_coords (gdisp, curve->x1, curve->y1, &tx1, &ty1, - FALSE); - - gdk_draw_arc (iscissors->core->win, iscissors->core->gc, 1, - tx1 - POINT_HALFWIDTH, ty1 - POINT_HALFWIDTH, - POINT_WIDTH, POINT_WIDTH, 0, 23040); - } - } - - if (iscissors->draw & DRAW_ACTIVE_CURVE) - { - gdisplay_transform_coords (gdisp, iscissors->nx, iscissors->ny, - &txn, &tyn, FALSE); - - /* plot both curves, and the control point between them */ - if (iscissors->curve1) - { - gdisplay_transform_coords (gdisp, iscissors->curve1->x2, - iscissors->curve1->y2, &tx1, &ty1, FALSE); - - gdk_draw_line (iscissors->core->win, iscissors->core->gc, - tx1, ty1, txn, tyn); - } - if (iscissors->curve2) - { - gdisplay_transform_coords (gdisp, iscissors->curve2->x1, - iscissors->curve2->y1, &tx2, &ty2, FALSE); - - gdk_draw_line (iscissors->core->win, iscissors->core->gc, - tx2, ty2, txn, tyn); - } - - gdk_draw_arc (iscissors->core->win, iscissors->core->gc, 1, - txn - POINT_HALFWIDTH, tyn - POINT_HALFWIDTH, - POINT_WIDTH, POINT_WIDTH, 0, 23040); - } -} - - -static void -iscissors_draw_curve (GDisplay *gdisp, - Iscissors *iscissors, - ICurve *curve) -{ - gpointer *point; - guint len; - gint tx, ty; - gint npts = 0; - guint32 coords; - - /* Uh, this shouldn't happen, but it does. So we ignore it. - * Quality code, baby. */ - if (!curve->points) - return; - - point = curve->points->pdata; - len = curve->points->len; - while (len--) - { - coords = GPOINTER_TO_INT (*point); - point++; - gdisplay_transform_coords (gdisp, (coords & 0x0000ffff), - (coords >> 16), &tx, &ty, FALSE); - if (npts < MAX_POINTS) - { - curve_points [npts].x = tx; - curve_points [npts].y = ty; - npts ++; - } - else - { - g_warning ("too many points in ICurve segment!"); - return; - } - } - - /* draw the curve */ - gdk_draw_lines (iscissors->core->win, iscissors->core->gc, - curve_points, npts); -} - -static void -iscissors_oper_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Iscissors *iscissors; - gint x, y; - - iscissors = (Iscissors *) tool->private; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &x, &y, FALSE, FALSE); - - if (mouse_over_vertex (iscissors, x, y)) - { - iscissors->op = SELECTION_MOVE_MASK; /* abused */ - } - else if (mouse_over_curve (iscissors, x, y)) - { - iscissors->op = SELECTION_MOVE; /* abused */ - } - else if (iscissors->connected && iscissors->mask && - channel_value (iscissors->mask, x, y)) - { - if (mevent->state & GDK_SHIFT_MASK && - mevent->state & GDK_CONTROL_MASK) - { - iscissors->op = SELECTION_INTERSECT; - } - else if (mevent->state & GDK_SHIFT_MASK) - { - iscissors->op = SELECTION_ADD; - } - else if (mevent->state & GDK_CONTROL_MASK) - { - iscissors->op = SELECTION_SUB; - } - else - { - iscissors->op = SELECTION_REPLACE; - } - } - else if (iscissors->connected && iscissors->mask) - { - iscissors->op = -1; - } - else - { - iscissors->op = -2; - } -} - -static void -iscissors_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - Iscissors *iscissors; - SelectOps op; - - iscissors = (Iscissors *) tool->private; - - op = iscissors->op; - - if (op == -2) - return; - - switch (kevent->keyval) - { - case GDK_Shift_L: case GDK_Shift_R: - if (op == SELECTION_REPLACE) - op = SELECTION_ADD; - else if (op == SELECTION_ADD) - op = SELECTION_REPLACE; - else if (op == SELECTION_SUB) - op = SELECTION_INTERSECT; - else if (op == SELECTION_INTERSECT) - op = SELECTION_SUB; - break; - - case GDK_Control_L: case GDK_Control_R: - if (op == SELECTION_REPLACE) - op = SELECTION_SUB; - else if (op == SELECTION_ADD) - op = SELECTION_INTERSECT; - else if (op == SELECTION_SUB) - op = SELECTION_REPLACE; - else if (op == SELECTION_INTERSECT) - op = SELECTION_ADD; - break; - } - - iscissors->op = op; -} - -static void -iscissors_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Iscissors *iscissors; - - iscissors = (Iscissors *) tool->private; - - switch (iscissors->op) - { - case SELECTION_REPLACE: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_NONE, - FALSE); - break; - case SELECTION_ADD: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_PLUS, - FALSE); - break; - case SELECTION_SUB: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_MINUS, - FALSE); - break; - case SELECTION_INTERSECT: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_INTERSECT, - FALSE); - break; - case SELECTION_MOVE_MASK: /* abused */ - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - ISCISSORS, - CURSOR_MODIFIER_MOVE, - FALSE); - break; - case SELECTION_MOVE: /* abused */ - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - ISCISSORS, - CURSOR_MODIFIER_PLUS, - FALSE); - break; - case -1: - gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, - ISCISSORS, - CURSOR_MODIFIER_NONE, - FALSE); - break; - default: - switch (iscissors->state) - { - case WAITING: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - ISCISSORS, - CURSOR_MODIFIER_PLUS, - FALSE); - break; - case SEED_PLACEMENT: - case SEED_ADJUSTMENT: - default: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - ISCISSORS, - CURSOR_MODIFIER_NONE, - FALSE); - break; - } - } -} - -static void -iscissors_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - Iscissors * iscissors; - Iscissors_draw draw; - - iscissors = (Iscissors *) tool->private; - - switch (iscissors->state) - { - case SEED_PLACEMENT: - draw = DRAW_CURVE | DRAW_CURRENT_SEED; - break; - - case SEED_ADJUSTMENT: - draw = DRAW_CURVE | DRAW_ACTIVE_CURVE; - break; - - default: - draw = DRAW_CURVE; - break; - } - - iscissors->draw = draw; - switch (action) - { - case PAUSE: - draw_core_pause (iscissors->core, tool); - break; - - case RESUME: - draw_core_resume (iscissors->core, tool); - break; - - case HALT: - draw_core_stop (iscissors->core, tool); - iscissors_reset (iscissors); - break; - - default: - break; - } -} - - -static void -iscissors_reset (Iscissors *iscissors) -{ - /* Free and reset the curve list */ - if (iscissors->curves) - { - iscissors_free_icurves (iscissors->curves); - g_slist_free (iscissors->curves); - iscissors->curves = NULL; - } - - /* free mask */ - if (iscissors->mask) - channel_delete (iscissors->mask); - iscissors->mask = NULL; - - /* free the gradient map */ - if (iscissors->gradient_map) - { - /* release any tile we were using */ - if (cur_tile) - { - tile_release (cur_tile, FALSE); - cur_tile = NULL; - } - - tile_manager_destroy (iscissors->gradient_map); - iscissors->gradient_map = NULL; - } - - iscissors->curve1 = NULL; - iscissors->curve2 = NULL; - iscissors->first_point = TRUE; - iscissors->connected = FALSE; - iscissors->state = NO_ACTION; - - /* Reset the dp buffers */ - iscissors_free_buffers (iscissors); - - /* If they haven't already been initialized, precalculate the diagonal - * weight and direction value arrays - */ - if (!initialized) - { - precalculate_arrays (); - initialized = TRUE; - } -} - - -static void -iscissors_free_icurves (GSList *list) -{ - ICurve * curve; - - while (list) - { - curve = (ICurve *) list->data; - if (curve->points) - g_ptr_array_free (curve->points, TRUE); - - g_free (curve); - list = g_slist_next (list); - } -} - - -static void -iscissors_free_buffers (Iscissors *iscissors) -{ - if (iscissors->dp_buf) - temp_buf_free (iscissors->dp_buf); - - iscissors->dp_buf = NULL; -} - - -/* XXX need some scan-conversion routines from somewhere. maybe. ? */ - -static gint -mouse_over_vertex (Iscissors *iscissors, - gint x, - gint y) -{ - GSList *list; - ICurve *curve; - gint curves_found = 0; - - /* traverse through the list, returning non-zero if the current cursor - * position is on an existing curve vertex. Set the curve1 and curve2 - * variables to the two curves containing the vertex in question - */ - - iscissors->curve1 = iscissors->curve2 = NULL; - - list = iscissors->curves; - - while (list && curves_found < 2) - { - curve = (ICurve *) list->data; - - if (abs (curve->x1 - x) < POINT_HALFWIDTH && - abs (curve->y1 - y) < POINT_HALFWIDTH) - { - iscissors->curve1 = curve; - if (curves_found++) - return curves_found; - } - else if (abs (curve->x2 - x) < POINT_HALFWIDTH && - abs (curve->y2 - y) < POINT_HALFWIDTH) - { - iscissors->curve2 = curve; - if (curves_found++) - return curves_found; - } - - list = g_slist_next (list); - } - - return curves_found; -} - -static gboolean -clicked_on_vertex (Tool *tool) -{ - Iscissors *iscissors; - gint curves_found = 0; - - iscissors = (Iscissors *) tool->private; - - curves_found = mouse_over_vertex (iscissors, iscissors->x, iscissors->y); - - if (curves_found > 1) - return TRUE; - - /* if only one curve was found, the curves are unconnected, and - * the user only wants to move either the first or last point - * disallow this for now. - */ - if (curves_found == 1) - return FALSE; - - /* no vertices were found at the cursor click point. Now check whether - * the click occured on a curve. If so, create a new vertex there and - * two curve segments to replace what used to be just one... - */ - return clicked_on_curve (tool); -} - - -static GSList * -mouse_over_curve (Iscissors *iscissors, - gint x, - gint y) -{ - GSList *list; - gpointer *pt; - gint len; - ICurve *curve; - guint32 coords; - gint tx, ty; - - /* traverse through the list, returning the curve segment's list element - * if the current cursor position is on a curve... - */ - - for (list = iscissors->curves; list; list = g_slist_next (list)) - { - curve = (ICurve *) list->data; - - pt = curve->points->pdata; - len = curve->points->len; - while (len--) - { - coords = GPOINTER_TO_INT (*pt); - pt++; - tx = coords & 0x0000ffff; - ty = coords >> 16; - - /* Is the specified point close enough to the curve? */ - if (abs (tx - x) < POINT_HALFWIDTH && - abs (ty - y) < POINT_HALFWIDTH) - { - return list; - } - } - } - - return NULL; -} - -static gboolean -clicked_on_curve (Tool *tool) -{ - Iscissors *iscissors; - GSList *list, *new_link; - ICurve *curve, *new_curve; - - iscissors = (Iscissors *) tool->private; - - /* traverse through the list, getting back the curve segment's list - * element if the current cursor position is on a curve... - * If this occurs, replace the curve with two new curves, - * separated by a new vertex. - */ - list = mouse_over_curve (iscissors, iscissors->x, iscissors->y); - - if (list) - { - curve = (ICurve *) list->data; - - /* Since we're modifying the curve, undraw the existing one */ - iscissors->draw = DRAW_CURVE; - draw_core_pause (iscissors->core, tool); - - /* Create the new curve */ - new_curve = g_new (ICurve, 1); - - new_curve->x2 = curve->x2; - new_curve->y2 = curve->y2; - new_curve->x1 = curve->x2 = iscissors->x; - new_curve->y1 = curve->y2 = iscissors->y; - new_curve->points = NULL; - - /* Create the new link and supply the new curve as data */ - new_link = g_slist_alloc (); - new_link->data = (void *) new_curve; - - /* Insert the new link in the list */ - new_link->next = list->next; - list->next = new_link; - - iscissors->curve1 = new_curve; - iscissors->curve2 = curve; - - /* Redraw the curve */ - draw_core_resume (iscissors->core, tool); - - return TRUE; - } - - return FALSE; -} - - -static void -precalculate_arrays (void) -{ - gint i; - - for (i = 0; i < 256; i++) - { - /* The diagonal weight array */ - diagonal_weight [i] = (int) (i * G_SQRT2); - - /* The direction value array */ - direction_value [i][0] = (127 - abs (127 - i)) * 2; - direction_value [i][1] = abs (127 - i) * 2; - direction_value [i][2] = abs (191 - i) * 2; - direction_value [i][3] = abs (63 - i) * 2; - } - - /* set the 256th index of the direction_values to the hightest cost */ - direction_value [255][0] = 255; - direction_value [255][1] = 255; - direction_value [255][2] = 255; - direction_value [255][3] = 255; -} - - -static void -calculate_curve (Tool *tool, - ICurve *curve) -{ - GDisplay *gdisp; - Iscissors *iscissors; - gint x, y, dir; - gint xs, ys, xe, ye; - gint x1, y1, x2, y2; - gint width, height; - gint ewidth, eheight; - - /* Calculate the lowest cost path from one vertex to the next as specified - * by the parameter "curve". - * Here are the steps: - * 1) Calculate the appropriate working area for this operation - * 2) Allocate a temp buf for the dynamic programming array - * 3) Run the dynamic programming algorithm to find the optimal path - * 4) Translate the optimal path into pixels in the icurve data - * structure. - */ - - gdisp = tool->gdisp; - iscissors = (Iscissors *) tool->private; - - /* Get the bounding box */ - xs = CLAMP (curve->x1, 0, gdisp->gimage->width - 1); - ys = CLAMP (curve->y1, 0, gdisp->gimage->height - 1); - xe = CLAMP (curve->x2, 0, gdisp->gimage->width - 1); - ye = CLAMP (curve->y2, 0, gdisp->gimage->height - 1); - x1 = MIN (xs, xe); - y1 = MIN (ys, ye); - x2 = MAX (xs, xe) + 1; /* +1 because if xe = 199 & xs = 0, x2 - x1, width = 200 */ - y2 = MAX (ys, ye) + 1; - - /* expand the boundaries past the ending points by - * some percentage of width and height. This serves the following purpose: - * It gives the algorithm more area to search so better solutions - * are found. This is particularly helpful in finding "bumps" which - * fall outside the bounding box represented by the start and end - * coordinates of the "curve". - */ - ewidth = (x2 - x1) * EXTEND_BY + FIXED; - eheight = (y2 - y1) * EXTEND_BY + FIXED; - - if (xe >= xs) - x2 += CLAMP (ewidth, 0, gdisp->gimage->width - x2); - else - x1 -= CLAMP (ewidth, 0, x1); - if (ye >= ys) - y2 += CLAMP (eheight, 0, gdisp->gimage->height - y2); - else - y1 -= CLAMP (eheight, 0, y1); - - /* blow away any previous points list we might have */ - if (curve->points) - { - g_ptr_array_free (curve->points, TRUE); - curve->points = NULL; - } - - /* If the bounding box has width and height... */ - if ((x2 - x1) && (y2 - y1)) - { - width = (x2 - x1); - height = (y2 - y1); - - /* Initialise the gradient map tile manager for this image if we - * don't already have one. */ - if (!iscissors->gradient_map) - iscissors->gradient_map = gradient_map_new (gdisp->gimage); - - /* allocate the dynamic programming array */ - iscissors->dp_buf = - temp_buf_resize (iscissors->dp_buf, 4, x1, y1, width, height); - - /* find the optimal path of pixels from (x1, y1) to (x2, y2) */ - find_optimal_path (iscissors->gradient_map, iscissors->dp_buf, - x1, y1, x2, y2, xs, ys); - - /* get a list of the pixels in the optimal path */ - curve->points = plot_pixels (iscissors, iscissors->dp_buf, - x1, y1, xs, ys, xe, ye); - } - /* If the bounding box has no width */ - else if ((x2 - x1) == 0) - { - /* plot a vertical line */ - y = ys; - dir = (ys > ye) ? -1 : 1; - curve->points = g_ptr_array_new (); - while (y != ye) - { - g_ptr_array_add (curve->points, GINT_TO_POINTER ((y << 16) + xs)); - y += dir; - } - } - /* If the bounding box has no height */ - else if ((y2 - y1) == 0) - { - /* plot a horizontal line */ - x = xs; - dir = (xs > xe) ? -1 : 1; - curve->points = g_ptr_array_new (); - while (x != xe) - { - g_ptr_array_add (curve->points, GINT_TO_POINTER ((ys << 16) + x)); - x += dir; - } - } -} - - -/* badly need to get a replacement - this is _way_ too expensive */ -static gboolean -gradient_map_value (TileManager *map, - gint x, - gint y, - guint8 *grad, - guint8 *dir) -{ - static int cur_tilex; - static int cur_tiley; - guint8 *p; - - if (!cur_tile || - x / TILE_WIDTH != cur_tilex || - y / TILE_HEIGHT != cur_tiley) - { - if (cur_tile) - tile_release (cur_tile, FALSE); - cur_tile = tile_manager_get_tile (map, x, y, TRUE, FALSE); - if (!cur_tile) - return FALSE; - cur_tilex = x / TILE_WIDTH; - cur_tiley = y / TILE_HEIGHT; - } - - p = tile_data_pointer (cur_tile, x % TILE_WIDTH, y % TILE_HEIGHT); - *grad = p[0]; - *dir = p[1]; - - return TRUE; -} - -static gint -calculate_link (TileManager *gradient_map, - gint x, - gint y, - guint32 pixel, - gint link) -{ - gint value = 0; - guint8 grad1, dir1, grad2, dir2; - - if (!gradient_map_value (gradient_map, x, y, &grad1, &dir1)) - { - grad1 = 0; - dir1 = 255; - } - - /* Convert the gradient into a cost: large gradients are good, and - * so have low cost. */ - grad1 = 255 - grad1; - - /* calculate the contribution of the gradient magnitude */ - if (link > 1) - value += diagonal_weight [grad1] * OMEGA_G; - else - value += grad1 * OMEGA_G; - - /* calculate the contribution of the gradient direction */ - x += (gint8)(pixel & 0xff); - y += (gint8)((pixel & 0xff00) >> 8); - if (!gradient_map_value (gradient_map, x, y, &grad2, &dir2)) - { - grad2 = 0; - dir2 = 255; - } - value += (direction_value [dir1][link] + direction_value [dir2][link]) * - OMEGA_D; - - return value; -} - - -static GPtrArray * -plot_pixels (Iscissors *iscissors, - TempBuf *dp_buf, - gint x1, - gint y1, - gint xs, - gint ys, - gint xe, - gint ye) -{ - gint x, y; - guint32 coords; - gint link; - gint width; - guint *data; - GPtrArray *list; - - width = dp_buf->width; - - /* Start the data pointer at the correct location */ - data = (guint *) temp_buf_data (dp_buf) + (ye - y1) * width + (xe - x1); - - x = xe; - y = ye; - - list = g_ptr_array_new (); - - while (1) - { - coords = (y << 16) + x; - g_ptr_array_add (list, GINT_TO_POINTER (coords)); - - link = PIXEL_DIR (*data); - if (link == SEED_POINT) - return list; - - x += move [link][0]; - y += move [link][1]; - data += move [link][1] * width + move [link][0]; - } - - /* won't get here */ - return NULL; -} - - -#define PACK(x, y) ((((y) & 0xff) << 8) | ((x) & 0xff)) -#define OFFSET(pixel) ((gint8)((pixel) & 0xff) + \ - ((gint8)(((pixel) & 0xff00) >> 8)) * dp_buf->width) - - -static void -find_optimal_path (TileManager *gradient_map, - TempBuf *dp_buf, - gint x1, - gint y1, - gint x2, - gint y2, - gint xs, - gint ys) -{ - gint i, j, k; - gint x, y; - gint link; - gint linkdir; - gint dirx, diry; - gint min_cost; - gint new_cost; - gint offset; - gint cum_cost [8]; - gint link_cost [8]; - gint pixel_cost [8]; - guint32 pixel [8]; - guint32 * data, *d; - - /* initialize the dynamic programming buffer */ - data = (guint32 *) temp_buf_data_clear (dp_buf); - - /* what directions are we filling the array in according to? */ - dirx = (xs - x1 == 0) ? 1 : -1; - diry = (ys - y1 == 0) ? 1 : -1; - linkdir = (dirx * diry); - - y = ys; - - for (i = 0; i < dp_buf->height; i++) - { - x = xs; - - d = data + (y-y1) * dp_buf->width + (x-x1); - - for (j = 0; j < dp_buf->width; j++) - { - min_cost = G_MAXINT; - - /* pixel[] array encodes how to get to a neigbour, if possible. - * 0 means no connection (eg edge). - * Rest packed as bottom two bytes: y offset then x offset. - * Initially, we assume we can't get anywhere. */ - for (k = 0; k < 8; k++) - pixel [k] = 0; - - /* Find the valid neighboring pixels */ - /* the previous pixel */ - if (j) - pixel [((dirx == 1) ? 4 : 0)] = PACK (-dirx, 0); - - /* the previous row of pixels */ - if (i) - { - pixel [((diry == 1) ? 5 : 1)] = PACK (0, -diry); - - link = (linkdir == 1) ? 3 : 2; - if (j) - pixel [((diry == 1) ? (link + 4) : link)] = PACK(-dirx, -diry); - - link = (linkdir == 1) ? 2 : 3; - if (j != dp_buf->width - 1) - pixel [((diry == 1) ? (link + 4) : link)] = PACK (dirx, -diry); - } - - /* find the minimum cost of going through each neighbor to reach the - * seed point... - */ - link = -1; - for (k = 0; k < 8; k ++) - if (pixel [k]) - { - link_cost [k] = calculate_link (gradient_map, - xs + j*dirx, ys + i*diry, - pixel [k], - ((k > 3) ? k - 4 : k)); - offset = OFFSET (pixel [k]); - pixel_cost [k] = PIXEL_COST (d [offset]); - cum_cost [k] = pixel_cost [k] + link_cost [k]; - if (cum_cost [k] < min_cost) - { - min_cost = cum_cost [k]; - link = k; - } - } - - /* If anything can be done... */ - if (link >= 0) - { - /* set the cumulative cost of this pixel and the new direction */ - *d = (cum_cost [link] << 8) + link; - - /* possibly change the links from the other pixels to this pixel... - * these changes occur if a neighboring pixel will receive a lower - * cumulative cost by going through this pixel. - */ - for (k = 0; k < 8; k ++) - if (pixel [k] && k != link) - { - /* if the cumulative cost at the neighbor is greater than - * the cost through the link to the current pixel, change the - * neighbor's link to point to the current pixel. - */ - new_cost = link_cost [k] + cum_cost [link]; - if (pixel_cost [k] > new_cost) - { - /* reverse the link direction /-----------------------\ */ - offset = OFFSET (pixel [k]); - d [offset] = (new_cost << 8) + ((k > 3) ? k - 4 : k + 4); - } - } - } - /* Set the seed point */ - else if (!i && !j) - *d = SEED_POINT; - - /* increment the data pointer and the x counter */ - d += dirx; - x += dirx; - } - - /* increment the y counter */ - y += diry; - } -} - - -/* Called to fill in a newly referenced tile in the gradient map */ -static void -gradmap_tile_validate (TileManager *tm, - Tile *tile) -{ - static gboolean first_gradient = TRUE; - gint x, y; - gint dw, dh; - gint sw, sh; - gint i, j; - gint b; - gfloat gradient; - guint8 *gradmap; - guint8 *tiledata; - guint8 *datah, *datav; - gint8 hmax, vmax; - Tile *srctile; - PixelRegion srcPR, destPR; - GImage *gimage; - - gimage = (GImage *) tile_manager_get_user_data (tm); - - if (first_gradient) - { - gint radius = GRADIENT_SEARCH >> 1; - /* compute the distance weights */ - for (i = 0; i < GRADIENT_SEARCH; i++) - for (j = 0; j < GRADIENT_SEARCH; j++) - distance_weights [i * GRADIENT_SEARCH + j] = - 1.0 / (1 + sqrt (SQR(i - radius) + SQR(j - radius))); - first_gradient = FALSE; - } - - tile_manager_get_tile_coordinates (tm, tile, &x, &y); - dw = tile_ewidth (tile); - dh = tile_eheight (tile); - - /* get corresponding tile in the gimage */ - srctile = tile_manager_get_tile (gimp_image_composite (gimage), - x, y, TRUE, FALSE); - if (!srctile) - return; - - sw = tile_ewidth (srctile); - sh = tile_eheight (srctile); - - srcPR.w = MIN (dw, sw); - srcPR.h = MIN (dh, sh); - srcPR.bytes = gimp_image_composite_bytes (gimage); - srcPR.data = tile_data_pointer (srctile, 0, 0); - srcPR.rowstride = srcPR.w * srcPR.bytes; - - /* XXX tile edges? */ - - /* Blur the source to get rid of noise */ - destPR.rowstride = TILE_WIDTH * 4; - destPR.data = maxgrad_conv0; - convolve_region (&srcPR, &destPR, blur_32, 3, 32, NORMAL_CONVOL); - - /* Set the "src" temp buf up as the new source Pixel Region */ - srcPR.rowstride = destPR.rowstride; - srcPR.data = destPR.data; - - /* Get the horizontal derivative */ - destPR.data = maxgrad_conv1; - convolve_region (&srcPR, &destPR, horz_deriv, 3, 1, NEGATIVE_CONVOL); - - /* Get the vertical derivative */ - destPR.data = maxgrad_conv2; - convolve_region (&srcPR, &destPR, vert_deriv, 3, 1, NEGATIVE_CONVOL); - - /* calculate overall gradient */ - tiledata = tile_data_pointer (tile, 0, 0); - for (i = 0; i < srcPR.h; i++) - { - datah = maxgrad_conv1 + srcPR.rowstride*i; - datav = maxgrad_conv2 + srcPR.rowstride*i; - gradmap = tiledata + tile_ewidth (tile) * COST_WIDTH * i; - - for (j = 0; j < srcPR.w; j++) - { - hmax = datah[0] - 128; - vmax = datav[0] - 128; - for (b = 1; b < srcPR.bytes; b++) - { - if (abs (datah[b] - 128) > abs (hmax)) hmax = datah[b] - 128; - if (abs (datav[b] - 128) > abs (vmax)) vmax = datav[b] - 128; - } - - if (i == 0 || j == 0 || i == srcPR.h-1 || j == srcPR.w-1) - { - gradmap[j*COST_WIDTH] = 0; - gradmap[j*COST_WIDTH + 1] = 255; - goto contin; - } - - /* 1 byte absolute magitude first */ - gradient = sqrt(SQR(hmax) + SQR(vmax)); - gradmap[j*COST_WIDTH] = gradient * 255 / MAX_GRADIENT; - - /* then 1 byte direction */ - if (gradient > MIN_GRADIENT) - { - gfloat direction; - if (!hmax) - direction = (vmax > 0) ? G_PI_2 : -G_PI_2; - else - direction = atan ((double) vmax / (double) hmax); - /* Scale the direction from between 0 and 254, - * corresponding to -PI/2, PI/2 255 is reserved for - * directionless pixels */ - gradmap[j*COST_WIDTH + 1] = - (guint8) (254 * (direction + G_PI_2) / G_PI); - } - else - gradmap[j*COST_WIDTH + 1] = 255; /* reserved for weak gradient */ - -contin: - datah += srcPR.bytes; - datav += srcPR.bytes; - } - } - - tile_release (srctile, FALSE); -} - -static TileManager * -gradient_map_new (GImage *gimage) -{ - TileManager *tm; - - tm = tile_manager_new (gimage->width, gimage->height, - sizeof (guint8) * COST_WIDTH); - tile_manager_set_user_data (tm, gimage); - tile_manager_set_validate_proc (tm, gradmap_tile_validate); - - return tm; -} - -static void -find_max_gradient (Iscissors *iscissors, - GImage *gimage, - gint *x, - gint *y) -{ - PixelRegion srcPR; - gint radius; - gint i, j; - gint endx, endy; - gint sx, sy, cx, cy; - gint x1, y1, x2, y2; - void *pr; - guint8 *gradient; - gfloat g, max_gradient; - - /* Initialise the gradient map tile manager for this image if we - * don't already have one. */ - if (!iscissors->gradient_map) - iscissors->gradient_map = gradient_map_new (gimage); - - radius = GRADIENT_SEARCH >> 1; - - /* calculate the extent of the search */ - cx = CLAMP (*x, 0, gimage->width); - cy = CLAMP (*y, 0, gimage->height); - sx = cx - radius; - sy = cy - radius; - x1 = CLAMP (cx - radius, 0, gimage->width); - y1 = CLAMP (cy - radius, 0, gimage->height); - x2 = CLAMP (cx + radius, 0, gimage->width); - y2 = CLAMP (cy + radius, 0, gimage->height); - /* calculate the factor to multiply the distance from the cursor by */ - - max_gradient = 0; - *x = cx; - *y = cy; - - /* Find the point of max gradient */ - pixel_region_init (&srcPR, iscissors->gradient_map, - x1, y1, x2 - x1, y2 - y1, FALSE); - - /* this iterates over 1, 2 or 4 tiles only */ - for (pr = pixel_regions_register (1, &srcPR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - endx = srcPR.x + srcPR.w; - endy = srcPR.y + srcPR.h; - for (i = srcPR.y; i < endy; i++) - { - gradient = srcPR.data + srcPR.rowstride * (i - srcPR.y); - for (j = srcPR.x; j < endx; j++) - { - g = *gradient; - gradient += COST_WIDTH; - g *= distance_weights [(i-y1) * GRADIENT_SEARCH + (j-x1)]; - if (g > max_gradient) - { - max_gradient = g; - *x = j; - *y = i; - } - } - } - } -} - -/* End of iscissors.c */ diff --git a/app/iscissors.h b/app/iscissors.h deleted file mode 100644 index a89cb37451..0000000000 --- a/app/iscissors.h +++ /dev/null @@ -1,27 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __ISCISSORS_H__ -#define __ISCISSORS_H__ - - -Tool * tools_new_iscissors (void); -void tools_free_iscissors (Tool *tool); - - -#endif /* __ISCISSORS_H__ */ diff --git a/app/levels.c b/app/levels.c deleted file mode 100644 index d8b8eeaa72..0000000000 --- a/app/levels.c +++ /dev/null @@ -1,1610 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include -#include -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimphistogram.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "histogramwidget.h" -#include "image_map.h" -#include "levels.h" -#include "gimplut.h" -#include "lut_funcs.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpenv.h" -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -#define LOW_INPUT 0x1 -#define GAMMA 0x2 -#define HIGH_INPUT 0x4 -#define LOW_OUTPUT 0x8 -#define HIGH_OUTPUT 0x10 -#define INPUT_LEVELS 0x20 -#define OUTPUT_LEVELS 0x40 -#define INPUT_SLIDERS 0x80 -#define OUTPUT_SLIDERS 0x100 -#define DRAW 0x200 -#define ALL 0xFFF - -#define DA_WIDTH 256 -#define DA_HEIGHT 25 -#define GRADIENT_HEIGHT 15 -#define CONTROL_HEIGHT DA_HEIGHT - GRADIENT_HEIGHT -#define HISTOGRAM_WIDTH 256 -#define HISTOGRAM_HEIGHT 150 - -#define LEVELS_DA_MASK GDK_EXPOSURE_MASK | \ - GDK_ENTER_NOTIFY_MASK | \ - GDK_BUTTON_PRESS_MASK | \ - GDK_BUTTON_RELEASE_MASK | \ - GDK_BUTTON1_MOTION_MASK | \ - GDK_POINTER_MOTION_HINT_MASK - - -/* the levels structures */ - -typedef struct _Levels Levels; - -struct _Levels -{ - gint x, y; /* coords for last mouse click */ -}; - -typedef struct _LevelsDialog LevelsDialog; - -struct _LevelsDialog -{ - GtkWidget *shell; - - GtkAdjustment *low_input_data; - GtkAdjustment *gamma_data; - GtkAdjustment *high_input_data; - GtkAdjustment *low_output_data; - GtkAdjustment *high_output_data; - - GtkWidget *input_levels_da[2]; - GtkWidget *output_levels_da[2]; - GtkWidget *channel_menu; - - HistogramWidget *histogram; - GimpHistogram *hist; - - GimpDrawable *drawable; - - ImageMap image_map; - - gint color; - gint channel; - gint low_input[5]; - gdouble gamma[5]; - gint high_input[5]; - gint low_output[5]; - gint high_output[5]; - gboolean preview; - - gint active_slider; - gint slider_pos[5]; /* positions for the five sliders */ - - guchar input[5][256]; /* this is used only by the gui */ - - GimpLut *lut; -}; - - -/* levels action functions */ -static void levels_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static LevelsDialog * levels_dialog_new (void); - -static void levels_calculate_transfers (LevelsDialog *ld); -static void levels_update (LevelsDialog *ld, - gint channel); -static void levels_preview (LevelsDialog *ld); -static void levels_channel_callback (GtkWidget *widget, - gpointer data); -static void levels_reset_callback (GtkWidget *widget, - gpointer data); -static void levels_ok_callback (GtkWidget *widget, - gpointer data); -static void levels_cancel_callback (GtkWidget *widget, - gpointer data); -static void levels_auto_callback (GtkWidget *widget, - gpointer data); -static void levels_load_callback (GtkWidget *widget, - gpointer data); -static void levels_save_callback (GtkWidget *widget, - gpointer data); -static void levels_preview_update (GtkWidget *widget, - gpointer data); -static void levels_low_input_adjustment_update (GtkAdjustment *adjustment, - gpointer data); -static void levels_gamma_adjustment_update (GtkAdjustment *adjustment, - gpointer data); -static void levels_high_input_adjustment_update (GtkAdjustment *adjustment, - gpointer data); -static void levels_low_output_adjustment_update (GtkAdjustment *adjustment, - gpointer data); -static void levels_high_output_adjustment_update (GtkAdjustment *adjustment, - gpointer data); -static gint levels_input_da_events (GtkWidget *widget, - GdkEvent *event, - LevelsDialog *ld); -static gint levels_output_da_events (GtkWidget *widget, - GdkEvent *event, - LevelsDialog *ld); - -static void file_dialog_create (GtkWidget *widget); -static void file_dialog_ok_callback (GtkWidget *widget, - gpointer data); -static void file_dialog_cancel_callback (GtkWidget *widget, - gpointer data); - -static gboolean levels_read_from_file (FILE *f); -static void levels_write_to_file (FILE *f); - - -/* the levels tool options */ -static ToolOptions *levels_options = NULL; - -/* the levels tool dialog */ -static LevelsDialog *levels_dialog = NULL; - -/* the levels file dialog */ -static GtkWidget *file_dlg = NULL; -static gboolean load_save; - -static GtkWidget *color_option_items[5]; - - -/* levels action functions */ - -static void -levels_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - levels_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_levels (void) -{ - Tool * tool; - Levels * private; - - /* The tool options */ - if (! levels_options) - { - levels_options = tool_options_new (_("Levels")); - tools_register (LEVELS, levels_options); - } - - tool = tools_new_tool (LEVELS); - private = g_new0 (Levels, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = levels_control; - - return tool; -} - -void -levels_dialog_hide (void) -{ - if (levels_dialog) - levels_cancel_callback (NULL, (gpointer) levels_dialog); -} - -void -tools_free_levels (Tool *tool) -{ - Levels * private; - - private = (Levels *) tool->private; - - /* Close the color select dialog */ - levels_dialog_hide (); - - g_free (private); -} - -void -levels_initialize (GDisplay *gdisp) -{ - gint i; - - if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Levels for indexed drawables cannot be adjusted.")); - return; - } - - /* The levels dialog */ - if (!levels_dialog) - levels_dialog = levels_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (levels_dialog->shell)) - gtk_widget_show (levels_dialog->shell); - - /* Initialize the values */ - levels_dialog->channel = GIMP_HISTOGRAM_VALUE; - for (i = 0; i < 5; i++) - { - levels_dialog->low_input[i] = 0; - levels_dialog->gamma[i] = 1.0; - levels_dialog->high_input[i] = 255; - levels_dialog->low_output[i] = 0; - levels_dialog->high_output[i] = 255; - } - - levels_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - levels_dialog->color = gimp_drawable_is_rgb (levels_dialog->drawable); - levels_dialog->image_map = image_map_create (gdisp, levels_dialog->drawable); - - /* check for alpha channel */ - gtk_widget_set_sensitive (color_option_items[4], - gimp_drawable_has_alpha (levels_dialog->drawable)); - - /* hide or show the channel menu based on image type */ - if (levels_dialog->color) - for (i = 0; i < 4; i++) - gtk_widget_set_sensitive (color_option_items[i], TRUE); - else - for (i = 1; i < 4; i++) - gtk_widget_set_sensitive (color_option_items[i], FALSE); - - /* set the current selection */ - gtk_option_menu_set_history (GTK_OPTION_MENU (levels_dialog->channel_menu), - levels_dialog->channel); - - - levels_update (levels_dialog, LOW_INPUT | GAMMA | HIGH_INPUT | LOW_OUTPUT | HIGH_OUTPUT | DRAW); - levels_update (levels_dialog, INPUT_LEVELS | OUTPUT_LEVELS); - - gimp_histogram_calculate_drawable (levels_dialog->hist, - levels_dialog->drawable); - histogram_widget_update (levels_dialog->histogram, levels_dialog->hist); - histogram_widget_range (levels_dialog->histogram, -1, -1); -} - -void -levels_free (void) -{ - if (levels_dialog) - { - if (levels_dialog->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (levels_dialog->image_map); - active_tool->preserve = FALSE; - - levels_dialog->image_map = NULL; - } - gtk_widget_destroy (levels_dialog->shell); - } -} - -/*******************/ -/* Levels dialog */ -/*******************/ - -static LevelsDialog * -levels_dialog_new (void) -{ - LevelsDialog *ld; - GtkWidget *main_vbox; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *vbox2; - GtkWidget *label; - GtkWidget *frame; - GtkWidget *toggle; - GtkWidget *channel_hbox; - GtkWidget *hbbox; - GtkWidget *button; - GtkWidget *spinbutton; - GtkObject *data; - - ld = g_new0 (LevelsDialog, 1); - ld->channel = GIMP_HISTOGRAM_VALUE; - ld->preview = TRUE; - ld->lut = gimp_lut_new (); - ld->hist = gimp_histogram_new (); - - /* The shell and main vbox */ - ld->shell = gimp_dialog_new (_("Levels"), "levels", - tools_help_func, tool_info[LEVELS].private_tip, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), levels_ok_callback, - ld, NULL, NULL, TRUE, FALSE, - _("Reset"), levels_reset_callback, - ld, NULL, NULL, FALSE, FALSE, - _("Cancel"), levels_cancel_callback, - ld, NULL, NULL, FALSE, TRUE, - - NULL); - - main_vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (ld->shell)->vbox), main_vbox); - - hbox = gtk_hbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - - /* The option menu for selecting channels */ - channel_hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), channel_hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Modify Levels for Channel:")); - gtk_box_pack_start (GTK_BOX (channel_hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - ld->channel_menu = gimp_option_menu_new2 - (FALSE, levels_channel_callback, - ld, (gpointer) ld->channel, - - _("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, &color_option_items[0], - _("Red"), (gpointer) GIMP_HISTOGRAM_RED, &color_option_items[1], - _("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, &color_option_items[2], - _("Blue"), (gpointer) GIMP_HISTOGRAM_BLUE, &color_option_items[3], - _("Alpha"), (gpointer) GIMP_HISTOGRAM_ALPHA, &color_option_items[4], - - NULL); - gtk_box_pack_start (GTK_BOX (channel_hbox), ld->channel_menu, FALSE, FALSE, 0); - gtk_widget_show (ld->channel_menu); - - gtk_widget_show (channel_hbox); - - /* Horizontal box for input levels spinbuttons */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Input Levels:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* low input spin */ - data = gtk_adjustment_new (0, 0, 255, 1, 10, 10); - ld->low_input_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (ld->low_input_data, 0.5, 0); - gtk_widget_set_usize (spinbutton, 50, -1); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->low_input_data), "value_changed", - GTK_SIGNAL_FUNC (levels_low_input_adjustment_update), - ld); - - gtk_widget_show (spinbutton); - - /* input gamma spin */ - data = gtk_adjustment_new (1, 0.1, 10, 0.1, 1, 1); - ld->gamma_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (ld->gamma_data, 0.5, 2); - gtk_widget_set_usize (spinbutton, 50, -1); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->gamma_data), "value_changed", - GTK_SIGNAL_FUNC (levels_gamma_adjustment_update), - ld); - - gtk_widget_show (spinbutton); - - /* high input spin */ - data = gtk_adjustment_new (255, 0, 255, 1, 10, 10); - ld->high_input_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (ld->high_input_data, 0.5, 0); - gtk_widget_set_usize (spinbutton, 50, -1); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->high_input_data), "value_changed", - GTK_SIGNAL_FUNC (levels_high_input_adjustment_update), - ld); - - gtk_widget_show (spinbutton); - gtk_widget_show (hbox); - - /* The levels histogram */ - hbox = gtk_hbox_new (TRUE, 2); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, FALSE, 0); - ld->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT); - gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (ld->histogram)); - - /* ignore button_events, since we don't want the user to be able to set the range */ - gtk_widget_set_events (GTK_WIDGET (ld->histogram), - (GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK)); - - gtk_widget_show (GTK_WIDGET (ld->histogram)); - gtk_widget_show (frame); - gtk_widget_show (hbox); - - /* The input levels drawing area */ - hbox = gtk_hbox_new (TRUE, 2); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); - - vbox2 = gtk_vbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (frame), vbox2); - - ld->input_levels_da[0] = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (ld->input_levels_da[0]), - DA_WIDTH, GRADIENT_HEIGHT); - gtk_widget_set_events (ld->input_levels_da[0], LEVELS_DA_MASK); - gtk_box_pack_start (GTK_BOX (vbox2), ld->input_levels_da[0], FALSE, TRUE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->input_levels_da[0]), "event", - GTK_SIGNAL_FUNC (levels_input_da_events), - ld); - - ld->input_levels_da[1] = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (ld->input_levels_da[1]), - DA_WIDTH, CONTROL_HEIGHT); - gtk_widget_set_events (ld->input_levels_da[1], LEVELS_DA_MASK); - gtk_box_pack_start (GTK_BOX (vbox2), ld->input_levels_da[1], FALSE, TRUE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->input_levels_da[1]), "event", - GTK_SIGNAL_FUNC (levels_input_da_events), - ld); - - gtk_widget_show (ld->input_levels_da[0]); - gtk_widget_show (ld->input_levels_da[1]); - gtk_widget_show (vbox2); - gtk_widget_show (frame); - gtk_widget_show (hbox); - - /* Horizontal box for levels spin widgets */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Output Levels:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* low output spin */ - data = gtk_adjustment_new (0, 0, 255, 1, 10, 10); - ld->low_output_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (ld->low_output_data, 0.5, 0); - gtk_widget_set_usize (spinbutton, 50, -1); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->low_output_data), "value_changed", - GTK_SIGNAL_FUNC (levels_low_output_adjustment_update), - ld); - - gtk_widget_show (spinbutton); - - /* high output spin */ - data = gtk_adjustment_new (255, 0, 255, 1, 10, 10); - ld->high_output_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (ld->high_output_data, 0.5, 0); - gtk_widget_set_usize (spinbutton, 50, -1); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->high_output_data), "value_changed", - GTK_SIGNAL_FUNC (levels_high_output_adjustment_update), - ld); - - gtk_widget_show (spinbutton); - gtk_widget_show (hbox); - - /* The output levels drawing area */ - hbox = gtk_hbox_new (TRUE, 2); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); - - vbox2 = gtk_vbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (frame), vbox2); - - ld->output_levels_da[0] = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_size (GTK_PREVIEW (ld->output_levels_da[0]), DA_WIDTH, GRADIENT_HEIGHT); - gtk_widget_set_events (ld->output_levels_da[0], LEVELS_DA_MASK); - gtk_box_pack_start (GTK_BOX (vbox2), ld->output_levels_da[0], FALSE, TRUE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->output_levels_da[0]), "event", - GTK_SIGNAL_FUNC (levels_output_da_events), - ld); - - ld->output_levels_da[1] = gtk_preview_new (GTK_PREVIEW_GRAYSCALE); - gtk_preview_size (GTK_PREVIEW (ld->output_levels_da[1]), DA_WIDTH, CONTROL_HEIGHT); - gtk_widget_set_events (ld->output_levels_da[1], LEVELS_DA_MASK); - gtk_box_pack_start (GTK_BOX (vbox2), ld->output_levels_da[1], FALSE, TRUE, 0); - - gtk_signal_connect (GTK_OBJECT (ld->output_levels_da[1]), "event", - GTK_SIGNAL_FUNC (levels_output_da_events), - ld); - - gtk_widget_show (ld->output_levels_da[0]); - gtk_widget_show (ld->output_levels_da[1]); - gtk_widget_show (vbox2); - gtk_widget_show (frame); - gtk_widget_show (hbox); - - gtk_widget_show (vbox); - - /* The preview toggle */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), ld->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (levels_preview_update), - ld); - - gtk_widget_show (toggle); - - gtk_widget_show (hbox); - - /* Horizontal button box for auto / load / save */ - hbbox = gtk_hbutton_box_new (); - gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4); - gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD); - gtk_box_pack_end (GTK_BOX (main_vbox), hbbox, FALSE, FALSE, 0); - - button = gtk_button_new_with_label (_("Auto")); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (levels_auto_callback), - ld); - - gtk_widget_show (button); - - button = gtk_button_new_with_label (_("Load")); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (levels_load_callback), - ld->shell); - - gtk_widget_show (button); - - button = gtk_button_new_with_label (_("Save")); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (levels_save_callback), - ld->shell); - - gtk_widget_show (button); - - gtk_widget_show (hbbox); - - gtk_widget_show (main_vbox); - gtk_widget_show (ld->shell); - - return ld; -} - -static void -levels_draw_slider (GdkWindow *window, - GdkGC *border_gc, - GdkGC *fill_gc, - gint xpos) -{ - int y; - - for (y = 0; y < CONTROL_HEIGHT; y++) - gdk_draw_line(window, fill_gc, xpos - y / 2, y, - xpos + y / 2, y); - - gdk_draw_line (window, border_gc, xpos, 0, - xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1); - - gdk_draw_line (window, border_gc, xpos, 0, - xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1); - - gdk_draw_line (window, border_gc, xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1, - xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1); -} - -static void -levels_erase_slider (GdkWindow *window, - gint xpos) -{ - gdk_window_clear_area (window, xpos - (CONTROL_HEIGHT - 1) / 2, 0, - CONTROL_HEIGHT - 1, CONTROL_HEIGHT); -} - -static void -levels_calculate_transfers (LevelsDialog *ld) -{ - gdouble inten; - gint i, j; - - /* Recalculate the levels arrays */ - for (j = 0; j < 5; j++) - { - for (i = 0; i < 256; i++) - { - /* determine input intensity */ - if (ld->high_input[j] != ld->low_input[j]) - inten = (double) (i - ld->low_input[j]) / - (double) (ld->high_input[j] - ld->low_input[j]); - else - inten = (double) (i - ld->low_input[j]); - - inten = CLAMP (inten, 0.0, 1.0); - if (ld->gamma[j] != 0.0) - inten = pow (inten, (1.0 / ld->gamma[j])); - ld->input[j][i] = (guchar) (inten * 255.0 + 0.5); - } - } -} - -static void -levels_update (LevelsDialog *ld, - gint update) -{ - gint i; - gint sel_channel; - - if (ld->color) - { - sel_channel = ld->channel; - } - else - { - if (ld->channel == 2) - sel_channel = GIMP_HISTOGRAM_ALPHA; - else - sel_channel = GIMP_HISTOGRAM_VALUE; - } - - /* Recalculate the transfer arrays */ - levels_calculate_transfers (ld); - /* set up the lut */ - levels_lut_setup (ld->lut, ld->gamma, ld->low_input, ld->high_input, - ld->low_output, ld->high_output, - gimp_drawable_bytes (ld->drawable)); - - if (update & LOW_INPUT) - { - gtk_adjustment_set_value (ld->low_input_data, - ld->low_input[ld->channel]); - } - if (update & GAMMA) - { - gtk_adjustment_set_value (ld->gamma_data, - ld->gamma[ld->channel]); - } - if (update & HIGH_INPUT) - { - gtk_adjustment_set_value (ld->high_input_data, - ld->high_input[ld->channel]); - } - if (update & LOW_OUTPUT) - { - gtk_adjustment_set_value (ld->low_output_data, - ld->low_output[ld->channel]); - } - if (update & HIGH_OUTPUT) - { - gtk_adjustment_set_value (ld->high_output_data, - ld->high_output[ld->channel]); - } - if (update & INPUT_LEVELS) - { - guchar buf[DA_WIDTH*3]; - - switch (sel_channel) - { - default: - g_warning ("unknown channel type, can't happen\n"); - /* fall through */ - case GIMP_HISTOGRAM_VALUE: - case GIMP_HISTOGRAM_ALPHA: - for (i = 0; i < DA_WIDTH; i++) - { - buf[3*i+0] = ld->input[sel_channel][i]; - buf[3*i+1] = ld->input[sel_channel][i]; - buf[3*i+2] = ld->input[sel_channel][i]; - } - break; - - case GIMP_HISTOGRAM_RED: - case GIMP_HISTOGRAM_GREEN: - case GIMP_HISTOGRAM_BLUE: - for (i = 0; i < DA_WIDTH; i++) - { - buf[3*i+0] = ld->input[GIMP_HISTOGRAM_RED][i]; - buf[3*i+1] = ld->input[GIMP_HISTOGRAM_GREEN][i]; - buf[3*i+2] = ld->input[GIMP_HISTOGRAM_BLUE][i]; - } - break; - } - - for (i = 0; i < GRADIENT_HEIGHT/2; i++) - gtk_preview_draw_row (GTK_PREVIEW (ld->input_levels_da[0]), - buf, 0, i, DA_WIDTH); - - - for (i = 0; i < DA_WIDTH; i++) - { - buf[3*i+0] = i; - buf[3*i+1] = i; - buf[3*i+2] = i; - } - - for (i = GRADIENT_HEIGHT/2; i < GRADIENT_HEIGHT; i++) - gtk_preview_draw_row (GTK_PREVIEW (ld->input_levels_da[0]), - buf, 0, i, DA_WIDTH); - - if (update & DRAW) - gtk_widget_draw (ld->input_levels_da[0], NULL); - } - if (update & OUTPUT_LEVELS) - { - guchar buf[DA_WIDTH*3]; - guchar r, g, b; - - r = g = b = 0; - switch (sel_channel) - { - default: - g_warning ("unknown channel type, can't happen\n"); - /* fall through */ - case GIMP_HISTOGRAM_VALUE: - case GIMP_HISTOGRAM_ALPHA: r = g = b = 1; break; - case GIMP_HISTOGRAM_RED: r = 1; break; - case GIMP_HISTOGRAM_GREEN: g = 1; break; - case GIMP_HISTOGRAM_BLUE: b = 1; break; - } - - for (i = 0; i < DA_WIDTH; i++) - { - buf[3*i+0] = i*r; - buf[3*i+1] = i*g; - buf[3*i+2] = i*b; - } - - for (i = 0; i < GRADIENT_HEIGHT; i++) - gtk_preview_draw_row (GTK_PREVIEW (ld->output_levels_da[0]), - buf, 0, i, DA_WIDTH); - - if (update & DRAW) - gtk_widget_draw (ld->output_levels_da[0], NULL); - } - if (update & INPUT_SLIDERS) - { - double width, mid, tmp; - - levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[0]); - levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[1]); - levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[2]); - - ld->slider_pos[0] = DA_WIDTH * ((double) ld->low_input[ld->channel] / 255.0); - ld->slider_pos[2] = DA_WIDTH * ((double) ld->high_input[ld->channel] / 255.0); - - width = (double) (ld->slider_pos[2] - ld->slider_pos[0]) / 2.0; - mid = ld->slider_pos[0] + width; - tmp = log10 (1.0 / ld->gamma[ld->channel]); - ld->slider_pos[1] = (int) (mid + width * tmp + 0.5); - - levels_draw_slider (ld->input_levels_da[1]->window, - ld->input_levels_da[1]->style->black_gc, - ld->input_levels_da[1]->style->dark_gc[GTK_STATE_NORMAL], - ld->slider_pos[1]); - levels_draw_slider (ld->input_levels_da[1]->window, - ld->input_levels_da[1]->style->black_gc, - ld->input_levels_da[1]->style->black_gc, - ld->slider_pos[0]); - levels_draw_slider (ld->input_levels_da[1]->window, - ld->input_levels_da[1]->style->black_gc, - ld->input_levels_da[1]->style->white_gc, - ld->slider_pos[2]); - } - if (update & OUTPUT_SLIDERS) - { - levels_erase_slider (ld->output_levels_da[1]->window, ld->slider_pos[3]); - levels_erase_slider (ld->output_levels_da[1]->window, ld->slider_pos[4]); - - ld->slider_pos[3] = DA_WIDTH * ((double) ld->low_output[ld->channel] / 255.0); - ld->slider_pos[4] = DA_WIDTH * ((double) ld->high_output[ld->channel] / 255.0); - - levels_draw_slider (ld->output_levels_da[1]->window, - ld->output_levels_da[1]->style->black_gc, - ld->output_levels_da[1]->style->black_gc, - ld->slider_pos[3]); - levels_draw_slider (ld->output_levels_da[1]->window, - ld->output_levels_da[1]->style->black_gc, - ld->output_levels_da[1]->style->white_gc, - ld->slider_pos[4]); - } -} - -static void -levels_preview (LevelsDialog *ld) -{ - if (!ld->image_map) - { - g_warning ("levels_preview: No Image Map"); - return; - } - if (!ld->preview) - return; - active_tool->preserve = TRUE; - image_map_apply (ld->image_map, (ImageMapApplyFunc) gimp_lut_process_2, - (void *) ld->lut); - active_tool->preserve = FALSE; -} - -static void -levels_channel_callback (GtkWidget *widget, - gpointer data) -{ - LevelsDialog *ld; - - ld = (LevelsDialog *) data; - - gimp_menu_item_update (widget, &ld->channel); - - if(ld->color) - histogram_widget_channel (ld->histogram, ld->channel); - else - { - if(ld->channel > 1) - { - histogram_widget_channel (ld->histogram, 1); - ld->channel = 2; - } - else - { - histogram_widget_channel (ld->histogram, 0); - ld->channel = 1; - } - } - levels_update (ld, ALL); -} - -static void -levels_adjust_channel (LevelsDialog *ld, - GimpHistogram *hist, - gint channel) -{ - gint i; - gdouble count, new_count, percentage, next_percentage; - - ld->gamma[channel] = 1.0; - ld->low_output[channel] = 0; - ld->high_output[channel] = 255; - - count = gimp_histogram_get_count (hist, 0, 255); - - if (count == 0.0) - { - ld->low_input[channel] = 0; - ld->high_input[channel] = 0; - } - else - { - /* Set the low input */ - new_count = 0.0; - for (i = 0; i < 255; i++) - { - new_count += gimp_histogram_get_value(hist, channel, i); - percentage = new_count / count; - next_percentage = - (new_count + gimp_histogram_get_value (hist, - channel, - i + 1)) / count; - if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006)) - { - ld->low_input[channel] = i + 1; - break; - } - } - /* Set the high input */ - new_count = 0.0; - for (i = 255; i > 0; i--) - { - new_count += gimp_histogram_get_value(hist, channel, i); - percentage = new_count / count; - next_percentage = - (new_count + gimp_histogram_get_value (hist, - channel, - i - 1)) / count; - if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006)) - { - ld->high_input[channel] = i - 1; - break; - } - } - } -} - -static void -levels_reset_callback (GtkWidget *widget, - gpointer data) -{ - LevelsDialog *ld; - - ld = (LevelsDialog *) data; - - ld->low_input[ld->channel] = 0; - ld->gamma[ld->channel] = 1.0; - ld->high_input[ld->channel] = 255; - ld->low_output[ld->channel] = 0; - ld->high_output[ld->channel] = 255; - - levels_update (ld, ALL); - - if (ld->preview) - levels_preview (ld); -} - -static void -levels_ok_callback (GtkWidget *widget, - gpointer data) -{ - LevelsDialog *ld; - - ld = (LevelsDialog *) data; - - gimp_dialog_hide (ld->shell); - - active_tool->preserve = TRUE; - - if (!ld->preview) - { - levels_lut_setup (ld->lut, ld->gamma, ld->low_input, ld->high_input, - ld->low_output, ld->high_output, - gimp_drawable_bytes (ld->drawable)); - image_map_apply (ld->image_map, (ImageMapApplyFunc) gimp_lut_process_2, - (void *) ld->lut); - } - - if (ld->image_map) - image_map_commit (ld->image_map); - - active_tool->preserve = FALSE; - - ld->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -levels_cancel_callback (GtkWidget *widget, - gpointer data) -{ - LevelsDialog *ld; - - ld = (LevelsDialog *) data; - - gimp_dialog_hide (ld->shell); - - if (ld->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (ld->image_map); - active_tool->preserve = FALSE; - - gdisplays_flush (); - ld->image_map = NULL; - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -levels_auto_callback (GtkWidget *widget, - gpointer data) -{ - LevelsDialog *ld; - int channel; - - ld = (LevelsDialog *) data; - - if (ld->color) - { - /* Set the overall value to defaults */ - ld->low_input[GIMP_HISTOGRAM_VALUE] = 0; - ld->gamma[GIMP_HISTOGRAM_VALUE] = 1.0; - ld->high_input[GIMP_HISTOGRAM_VALUE] = 255; - ld->low_output[GIMP_HISTOGRAM_VALUE] = 0; - ld->high_output[GIMP_HISTOGRAM_VALUE] = 255; - - for (channel = 0; channel < 3; channel ++) - levels_adjust_channel (ld, ld->hist, channel + 1); - } - else - levels_adjust_channel (ld, ld->hist, GIMP_HISTOGRAM_VALUE); - - levels_update (ld, ALL); - if (ld->preview) - levels_preview (ld); -} - -static void -levels_load_callback (GtkWidget *widget, - gpointer data) -{ - if (!file_dlg) - file_dialog_create (GTK_WIDGET (data)); - else if (GTK_WIDGET_VISIBLE (file_dlg)) - return; - - load_save = TRUE; - - gtk_window_set_title (GTK_WINDOW (file_dlg), _("Load Levels")); - gtk_widget_show (file_dlg); -} - -static void -levels_save_callback (GtkWidget *widget, - gpointer data) -{ - if (!file_dlg) - file_dialog_create (GTK_WIDGET (data)); - else if (GTK_WIDGET_VISIBLE (file_dlg)) - return; - - load_save = FALSE; - - gtk_window_set_title (GTK_WINDOW (file_dlg), _("Save Levels")); - gtk_widget_show (file_dlg); -} - -static void -levels_preview_update (GtkWidget *widget, - gpointer data) -{ - LevelsDialog *ld; - - ld = (LevelsDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - ld->preview = TRUE; - levels_preview (ld); - } - else - { - ld->preview = FALSE; - if (ld->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (ld->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } - -} - -static void -levels_low_input_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - LevelsDialog *ld; - gint value; - - ld = (LevelsDialog *) data; - - value = (gint) (adjustment->value + 0.5); - value = CLAMP (value, 0, ld->high_input[ld->channel]); - - /* enforce a consistent displayed value (low_input <= high_input) */ - gtk_adjustment_set_value (adjustment, value); - - if (ld->low_input[ld->channel] != value) - { - ld->low_input[ld->channel] = value; - levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW); - - if (ld->preview) - levels_preview (ld); - } -} - -static void -levels_gamma_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - LevelsDialog *ld; - - ld = (LevelsDialog *) data; - - if (ld->gamma[ld->channel] != adjustment->value) - { - ld->gamma[ld->channel] = adjustment->value; - levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW); - - if (ld->preview) - levels_preview (ld); - } -} - -static void -levels_high_input_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - LevelsDialog *ld; - gint value; - - ld = (LevelsDialog *) data; - - value = (gint) (adjustment->value + 0.5); - value = CLAMP (value, ld->low_input[ld->channel], 255); - - /* enforce a consistent displayed value (high_input >= low_input) */ - gtk_adjustment_set_value (adjustment, value); - - if (ld->high_input[ld->channel] != value) - { - ld->high_input[ld->channel] = value; - levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW); - - if (ld->preview) - levels_preview (ld); - } -} - -static void -levels_low_output_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - LevelsDialog *ld; - gint value; - - ld = (LevelsDialog *) data; - - value = (gint) (adjustment->value + 0.5); - - if (ld->low_output[ld->channel] != value) - { - ld->low_output[ld->channel] = value; - levels_update (ld, OUTPUT_LEVELS | OUTPUT_SLIDERS | DRAW); - - if (ld->preview) - levels_preview (ld); - } -} - -static void -levels_high_output_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - LevelsDialog *ld; - gint value; - - ld = (LevelsDialog *) data; - - value = (gint) (adjustment->value + 0.5); - - if (ld->high_output[ld->channel] != value) - { - ld->high_output[ld->channel] = value; - levels_update (ld, OUTPUT_LEVELS | OUTPUT_SLIDERS | DRAW); - - if (ld->preview) - levels_preview (ld); - } -} - -static gint -levels_input_da_events (GtkWidget *widget, - GdkEvent *event, - LevelsDialog *ld) -{ - GdkEventButton *bevent; - GdkEventMotion *mevent; - gchar text[12]; - gdouble width, mid, tmp; - gint x, distance; - gint i; - gint update = FALSE; - - switch (event->type) - { - case GDK_EXPOSE: - if (widget == ld->input_levels_da[1]) - levels_update (ld, INPUT_SLIDERS); - break; - - case GDK_BUTTON_PRESS: - gtk_grab_add (widget); - bevent = (GdkEventButton *) event; - - distance = G_MAXINT; - for (i = 0; i < 3; i++) - if (fabs (bevent->x - ld->slider_pos[i]) < distance) - { - ld->active_slider = i; - distance = fabs (bevent->x - ld->slider_pos[i]); - } - - x = bevent->x; - update = TRUE; - break; - - case GDK_BUTTON_RELEASE: - gtk_grab_remove (widget); - switch (ld->active_slider) - { - case 0: /* low input */ - levels_update (ld, LOW_INPUT | GAMMA | DRAW); - break; - case 1: /* gamma */ - levels_update (ld, GAMMA); - break; - case 2: /* high input */ - levels_update (ld, HIGH_INPUT | GAMMA | DRAW); - break; - } - - if (ld->preview) - levels_preview (ld); - break; - - case GDK_MOTION_NOTIFY: - mevent = (GdkEventMotion *) event; - gdk_window_get_pointer (widget->window, &x, NULL, NULL); - update = TRUE; - break; - - default: - break; - } - - if (update) - { - switch (ld->active_slider) - { - case 0: /* low input */ - ld->low_input[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0; - ld->low_input[ld->channel] = CLAMP (ld->low_input[ld->channel], 0, - ld->high_input[ld->channel]); - break; - - case 1: /* gamma */ - width = (double) (ld->slider_pos[2] - ld->slider_pos[0]) / 2.0; - mid = ld->slider_pos[0] + width; - - x = CLAMP (x, ld->slider_pos[0], ld->slider_pos[2]); - tmp = (double) (x - mid) / width; - ld->gamma[ld->channel] = 1.0 / pow (10, tmp); - - /* round the gamma value to the nearest 1/100th */ - sprintf (text, "%2.2f", ld->gamma[ld->channel]); - ld->gamma[ld->channel] = atof (text); - break; - - case 2: /* high input */ - ld->high_input[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0; - ld->high_input[ld->channel] = CLAMP (ld->high_input[ld->channel], - ld->low_input[ld->channel], 255); - break; - } - - levels_update (ld, INPUT_SLIDERS | INPUT_LEVELS | DRAW); - } - - return FALSE; -} - -static gint -levels_output_da_events (GtkWidget *widget, - GdkEvent *event, - LevelsDialog *ld) -{ - GdkEventButton *bevent; - GdkEventMotion *mevent; - int x, distance; - int i; - int update = FALSE; - - switch (event->type) - { - case GDK_EXPOSE: - if (widget == ld->output_levels_da[1]) - levels_update (ld, OUTPUT_SLIDERS); - break; - - - case GDK_BUTTON_PRESS: - bevent = (GdkEventButton *) event; - - distance = G_MAXINT; - for (i = 3; i < 5; i++) - if (fabs (bevent->x - ld->slider_pos[i]) < distance) - { - ld->active_slider = i; - distance = fabs (bevent->x - ld->slider_pos[i]); - } - - x = bevent->x; - update = TRUE; - break; - - case GDK_BUTTON_RELEASE: - switch (ld->active_slider) - { - case 3: /* low output */ - levels_update (ld, LOW_OUTPUT | DRAW); - break; - case 4: /* high output */ - levels_update (ld, HIGH_OUTPUT | DRAW); - break; - } - - if (ld->preview) - levels_preview (ld); - break; - - case GDK_MOTION_NOTIFY: - mevent = (GdkEventMotion *) event; - gdk_window_get_pointer (widget->window, &x, NULL, NULL); - update = TRUE; - break; - - default: - break; - } - - if (update) - { - switch (ld->active_slider) - { - case 3: /* low output */ - ld->low_output[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0; - ld->low_output[ld->channel] = CLAMP (ld->low_output[ld->channel], - 0, 255); - break; - - case 4: /* high output */ - ld->high_output[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0; - ld->high_output[ld->channel] = CLAMP (ld->high_output[ld->channel], - 0, 255); - break; - } - - levels_update (ld, OUTPUT_SLIDERS | DRAW); - } - - return FALSE; -} - -static void -file_dialog_create (GtkWidget *parent) -{ - gchar *temp; - - file_dlg = gtk_file_selection_new (_("Load/Save Levels")); - gtk_window_set_wmclass (GTK_WINDOW (file_dlg), "load_save_levels", "Gimp"); - gtk_window_set_position (GTK_WINDOW (file_dlg), GTK_WIN_POS_MOUSE); - - gtk_container_set_border_width (GTK_CONTAINER (file_dlg), 2); - gtk_container_set_border_width (GTK_CONTAINER (GTK_FILE_SELECTION (file_dlg)->button_area), 2); - - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->cancel_button), - "clicked", GTK_SIGNAL_FUNC (file_dialog_cancel_callback), - NULL); - gtk_signal_connect (GTK_OBJECT (file_dlg), "delete_event", - GTK_SIGNAL_FUNC (file_dialog_cancel_callback), - NULL); - gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->ok_button), - "clicked", GTK_SIGNAL_FUNC (file_dialog_ok_callback), - NULL); - - gtk_signal_connect (GTK_OBJECT (parent), "unmap", - GTK_SIGNAL_FUNC (file_dialog_cancel_callback), - NULL); - - temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "levels" G_DIR_SEPARATOR_S, - gimp_directory ()); - gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_dlg), temp); - g_free (temp); - - gimp_help_connect_help_accel (file_dlg, tools_help_func, - tool_info[LEVELS].private_tip); -} - -static void -file_dialog_ok_callback (GtkWidget *widget, - gpointer data) -{ - FILE *f; - gchar *filename; - - filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_dlg)); - - if (load_save) - { - f = fopen (filename, "rt"); - - if (!f) - { - g_message (_("Unable to open file %s"), filename); - return; - } - - if (!levels_read_from_file (f)) - { - g_message (("Error in reading file %s"), filename); - return; - } - - fclose (f); - } - else - { - f = fopen(filename, "wt"); - - if (!f) - { - g_message (_("Unable to open file %s"), filename); - return; - } - - levels_write_to_file (f); - - fclose (f); - } - file_dialog_cancel_callback (file_dlg, NULL); -} - -static void -file_dialog_cancel_callback (GtkWidget *widget, - gpointer data) -{ - gimp_dialog_hide (file_dlg); -} - -static gboolean -levels_read_from_file (FILE *f) -{ - int low_input[5]; - int high_input[5]; - int low_output[5]; - int high_output[5]; - double gamma[5]; - int i, fields; - char buf[50], *nptr; - - if (!fgets (buf, 50, f)) - return FALSE; - - if (strcmp (buf, "# GIMP Levels File\n") != 0) - return FALSE; - - for (i = 0; i < 5; i++) - { - fields = fscanf (f, "%d %d %d %d ", - &low_input[i], - &high_input[i], - &low_output[i], - &high_output[i]); - - if (fields != 4) - return FALSE; - - if (!fgets (buf, 50, f)) - return FALSE; - - gamma[i] = strtod(buf, &nptr); - - if (buf == nptr || errno == ERANGE) - return FALSE; - } - - for (i = 0; i < 5; i++) - { - levels_dialog->low_input[i] = low_input[i]; - levels_dialog->high_input[i] = high_input[i]; - levels_dialog->low_output[i] = low_output[i]; - levels_dialog->high_output[i] = high_output[i]; - levels_dialog->gamma[i] = gamma[i]; - } - - levels_update (levels_dialog, ALL); - - if (levels_dialog->preview) - levels_preview (levels_dialog); - - return TRUE; -} - -static void -levels_write_to_file (FILE *f) -{ - int i; - - fprintf (f, "# GIMP Levels File\n"); - - for (i = 0; i < 5; i++) - { - fprintf (f, "%d %d %d %d %f\n", - levels_dialog->low_input[i], - levels_dialog->high_input[i], - levels_dialog->low_output[i], - levels_dialog->high_output[i], - levels_dialog->gamma[i]); - } -} diff --git a/app/levels.h b/app/levels.h deleted file mode 100644 index 11be1c59ff..0000000000 --- a/app/levels.h +++ /dev/null @@ -1,31 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __LEVELS_H__ -#define __LEVELS_H__ - - -Tool * tools_new_levels (void); -void tools_free_levels (Tool *tool); - -void levels_dialog_hide (void); -void levels_initialize (GDisplay *gdisp); -void levels_free (void); - - -#endif /* __LEVELS_H__ */ diff --git a/app/magnify.c b/app/magnify.c deleted file mode 100644 index 1d60a74324..0000000000 --- a/app/magnify.c +++ /dev/null @@ -1,467 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "gdisplay.h" -#include "gimprc.h" -#include "gimpui.h" -#include "info_window.h" -#include "magnify.h" -#include "scale.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpintl.h" - - -/* the magnify structures */ - -typedef struct _Magnify Magnify; - -struct _Magnify -{ - DrawCore *core; /* Core select object */ - - gint x, y; /* upper left hand coordinate */ - gint w, h; /* width and height */ - - gint op; /* magnify operation */ -}; - -typedef struct _MagnifyOptions MagnifyOptions; - -struct _MagnifyOptions -{ - ToolOptions tool_options; - - /* gint allow_resize_windows; (from gimprc) */ - gint allow_resize_d; - GtkWidget *allow_resize_w; - - ZoomType type; - ZoomType type_d; - GtkWidget *type_w[2]; -}; - - -/* magnify action functions */ -static void magnify_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void magnify_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void magnify_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void magnify_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -static void magnify_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void magnify_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -/* magnify utility functions */ -static void zoom_in (gint *src, - gint *dest, - gint scale); -static void zoom_out (gint *src, - gint *dest, - gint scale); - - -/* the magnify tool options */ -static MagnifyOptions *magnify_options = NULL; - - -/* magnify tool options functions */ - -static void -magnify_options_reset (void) -{ - MagnifyOptions *options = magnify_options; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->allow_resize_w), - options->allow_resize_d); - - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE); -} - -static MagnifyOptions * -magnify_options_new (void) -{ - MagnifyOptions *options; - - GtkWidget *vbox; - GtkWidget *frame; - - /* the new magnify tool options structure */ - options = g_new (MagnifyOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Magnify Tool"), - magnify_options_reset); - options->allow_resize_d = allow_resize_windows; - options->type_d = options->type = ZOOMIN; - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* the allow_resize toggle button */ - options->allow_resize_w = - gtk_check_button_new_with_label (_("Allow Window Resizing")); - gtk_signal_connect (GTK_OBJECT (options->allow_resize_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &allow_resize_windows); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->allow_resize_w), - allow_resize_windows); - gtk_box_pack_start (GTK_BOX (vbox), options->allow_resize_w, FALSE, FALSE, 0); - gtk_widget_show (options->allow_resize_w); - - /* tool toggle */ - frame = - gimp_radio_group_new2 (TRUE, _("Tool Toggle"), - gimp_radio_button_update, - &options->type, (gpointer) options->type, - - _("Zoom in"), (gpointer) ZOOMIN, - &options->type_w[0], - _("Zoom out"), (gpointer) ZOOMOUT, - &options->type_w[1], - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return options; -} - -/* magnify utility functions */ - -static void -zoom_in (gint *src, - gint *dest, - gint scale) -{ - while (scale--) - { - if (*src > 1) - (*src)--; - else - if (*dest < 0x10) - (*dest)++; - } -} - - -static void -zoom_out (gint *src, - gint *dest, - gint scale) -{ - while (scale--) - { - if (*dest > 1) - (*dest)--; - else - if (*src < 0x10) - (*src)++; - } -} - - -/* magnify action functions */ - -static void -magnify_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - Magnify *magnify; - gint x, y; - - magnify = (Magnify *) tool->private; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0); - - magnify->x = x; - magnify->y = y; - magnify->w = 0; - magnify->h = 0; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - draw_core_start (magnify->core, - gdisp->canvas->window, - tool); -} - - -static void -magnify_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - Magnify *magnify; - gint win_width, win_height; - gint width, height; - gint scalesrc, scaledest; - gint scale; - gint x1, y1, x2, y2, w, h; - - magnify = (Magnify *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - draw_core_stop (magnify->core, tool); - tool->state = INACTIVE; - - /* First take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - x1 = (magnify->w < 0) ? magnify->x + magnify->w : magnify->x; - y1 = (magnify->h < 0) ? magnify->y + magnify->h : magnify->y; - w = (magnify->w < 0) ? -magnify->w : magnify->w; - h = (magnify->h < 0) ? -magnify->h : magnify->h; - x2 = x1 + w; - y2 = y1 + h; - - /* these change the user zoom level, so should not be changed to - * the resolution-aware scale macros -- austin */ - scalesrc = SCALESRC (gdisp); - scaledest = SCALEDEST (gdisp); - - win_width = gdisp->disp_width; - win_height = gdisp->disp_height; - width = (win_width * scalesrc) / scaledest; - height = (win_height * scalesrc) / scaledest; - - if (!w || !h) - scale = 1; - else - scale = MIN ((width / w), (height / h)); - - magnify->op = magnify_options->type; - - switch (magnify->op) - { - case ZOOMIN: - zoom_in (&scalesrc, &scaledest, scale); - break; - case ZOOMOUT: - zoom_out (&scalesrc, &scaledest, scale); - break; - } - - gdisp->scale = (scaledest << 8) + scalesrc; - gdisp->offset_x = (scaledest * ((x1 + x2) / 2)) / scalesrc - - (win_width / 2); - gdisp->offset_y = (scaledest * ((y1 + y2) / 2)) / scalesrc - - (win_height / 2); - - /* resize the image */ - resize_display (gdisp, allow_resize_windows, TRUE); - } -} - -static void -magnify_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Magnify *magnify; - gint x, y; - - if (tool->state != ACTIVE) - return; - - magnify = (Magnify *) tool->private; - - draw_core_pause (magnify->core, tool); - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - magnify->w = (x - magnify->x); - magnify->h = (y - magnify->y); - - draw_core_resume (magnify->core, tool); -} - - -static void -magnify_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - switch (kevent->keyval) - { - case GDK_Alt_L: case GDK_Alt_R: - break; - case GDK_Shift_L: case GDK_Shift_R: - break; - case GDK_Control_L: case GDK_Control_R: - if (magnify_options->type == ZOOMIN) - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (magnify_options->type_w[ZOOMOUT]), TRUE); - else - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (magnify_options->type_w[ZOOMIN]), TRUE); - break; - } -} - -static void -magnify_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - if (magnify_options->type == ZOOMIN) - { - gdisplay_install_tool_cursor (gdisp, GIMP_ZOOM_CURSOR, - MAGNIFY, - CURSOR_MODIFIER_PLUS, - FALSE); - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_ZOOM_CURSOR, - MAGNIFY, - CURSOR_MODIFIER_MINUS, - FALSE); - } -} - - -void -magnify_draw (Tool *tool) -{ - Magnify *magnify; - gint x1, y1, x2, y2; - - magnify = (Magnify *) tool->private; - - x1 = MIN (magnify->x, magnify->x + magnify->w); - y1 = MIN (magnify->y, magnify->y + magnify->h); - x2 = MAX (magnify->x, magnify->x + magnify->w); - y2 = MAX (magnify->y, magnify->y + magnify->h); - - gdisplay_transform_coords (tool->gdisp, x1, y1, &x1, &y1, 0); - gdisplay_transform_coords (tool->gdisp, x2, y2, &x2, &y2, 0); - - gdk_draw_rectangle (magnify->core->win, magnify->core->gc, 0, - x1, y1, (x2 - x1), (y2 - y1)); -} - - -static void -magnify_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - Magnify *magnify; - - magnify = (Magnify *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (magnify->core, tool); - break; - - case RESUME: - draw_core_resume (magnify->core, tool); - break; - - case HALT: - draw_core_stop (magnify->core, tool); - break; - - default: - break; - } -} - - -Tool * -tools_new_magnify (void) -{ - Tool *tool; - Magnify *private; - - /* The tool options */ - if (! magnify_options) - { - magnify_options = magnify_options_new (); - tools_register (MAGNIFY, (ToolOptions *) magnify_options); - } - - tool = tools_new_tool (MAGNIFY); - private = g_new0 (Magnify, 1); - - private->core = draw_core_new (magnify_draw); - private->x = private->y = 0; - private->w = private->h = 0; - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->auto_snap_to = FALSE; /* Don't snap to guides */ - - tool->private = (void *) private; - - tool->button_press_func = magnify_button_press; - tool->button_release_func = magnify_button_release; - tool->motion_func = magnify_motion; - tool->modifier_key_func = magnify_modifier_update; - tool->cursor_update_func = magnify_cursor_update; - tool->control_func = magnify_control; - - return tool; -} - - -void -tools_free_magnify (Tool *tool) -{ - Magnify *magnify; - - magnify = (Magnify *) tool->private; - - draw_core_free (magnify->core); - g_free (magnify); -} diff --git a/app/magnify.h b/app/magnify.h deleted file mode 100644 index 4f70b77bb7..0000000000 --- a/app/magnify.h +++ /dev/null @@ -1,29 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __MAGNIFY_H__ -#define __MAGNIFY_H__ - - -Tool * tools_new_magnify (void); -void tools_free_magnify (Tool *tool); - -void magnify_draw (Tool *tool); - - -#endif /* __MAGNIFY_H__ */ diff --git a/app/measure.c b/app/measure.c deleted file mode 100644 index 70bf89a35c..0000000000 --- a/app/measure.c +++ /dev/null @@ -1,838 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * Measure tool - * Copyright (C) 1999 Sven Neumann - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "info_dialog.h" -#include "measure.h" -#include "undo.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* definitions */ -#define TARGET 8 -#define ARC_RADIUS 30 -#define ARC_RADIUS_2 1100 -#define STATUSBAR_SIZE 128 - -/* maximum information buffer size */ -#define MAX_INFO_BUF 16 - -/* possible measure functions */ -typedef enum -{ - CREATING, - ADDING, - MOVING, - MOVING_ALL, - GUIDING, - FINISHED -} MeasureFunction; - -/* the measure structure */ -typedef struct _MeasureTool MeasureTool; - -struct _MeasureTool -{ - DrawCore *core; /* draw core */ - MeasureFunction function; /* what are we doing? */ - gint last_x; /* last x coordinate */ - gint last_y; /* last y coordinate */ - gint point; /* what are we manipulating? */ - gint num_points; /* how many points? */ - gint x[3]; /* three x coordinates */ - gint y[3]; /* three y coordinates */ - gdouble angle1; /* first angle */ - gdouble angle2; /* second angle */ - guint context_id; /* for the statusbar */ -}; - -/* the measure tool options */ -typedef struct _MeasureOptions MeasureOptions; - -struct _MeasureOptions -{ - ToolOptions tool_options; - - gboolean use_info_window; - gboolean use_info_window_d; - GtkWidget *use_info_window_w; -}; - - -/* local function prototypes */ -static void measure_tool_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void measure_tool_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void measure_tool_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void measure_tool_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void measure_tool_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -static void measure_tool_info_window_close_callback (GtkWidget *widget, - gpointer data); -static void measure_tool_info_update (void); - - -static MeasureOptions *measure_tool_options = NULL; - -/* the measure tool info window */ -static InfoDialog *measure_tool_info = NULL; -static gchar distance_buf[MAX_INFO_BUF]; -static gchar angle_buf[MAX_INFO_BUF]; - - -static void -measure_tool_options_reset (void) -{ - MeasureOptions *options = measure_tool_options; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_info_window_w), - options->use_info_window_d); -} - -static MeasureOptions * -measure_tool_options_new (void) -{ - MeasureOptions *options; - GtkWidget *vbox; - - /* the new measure tool options structure */ - options = g_new (MeasureOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Measure Tool"), - measure_tool_options_reset); - options->use_info_window = options->use_info_window_d = FALSE; - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* the use_info_window toggle button */ - options->use_info_window_w = - gtk_check_button_new_with_label (_("Use Info Window")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_info_window_w), - options->use_info_window_d); - gtk_box_pack_start (GTK_BOX (vbox), options->use_info_window_w, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->use_info_window_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->use_info_window); - gtk_widget_show (options->use_info_window_w); - - return options; -} - -static gdouble -measure_get_angle (gint dx, - gint dy, - gdouble xres, - gdouble yres) -{ - gdouble angle; - - if (dx) - angle = gimp_rad_to_deg (atan (((gdouble) (dy) / yres) / - ((gdouble) (dx) / xres))); - else if (dy) - angle = dy > 0 ? 270.0 : 90.0; - else - angle = 180.0; - - if (dx > 0) - { - if (dy > 0) - angle = 360.0 - angle; - else - angle = -angle; - } - else - { - angle = 180.0 - angle; - } - - return angle; -} - -static void -measure_tool_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - MeasureTool *measure_tool; - gint x[3]; - gint y[3]; - gint i; - - measure_tool = (MeasureTool *) tool->private; - - /* if we are changing displays, pop the statusbar of the old one */ - if (tool->state == ACTIVE && gdisp != tool->gdisp) - { - GDisplay *old_gdisp = tool->gdisp; - - gtk_statusbar_pop (GTK_STATUSBAR (old_gdisp->statusbar), - measure_tool->context_id); - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - measure_tool->context_id, ("")); - } - - measure_tool->function = CREATING; - - if (tool->state == ACTIVE && gdisp == tool->gdisp) - { - /* if the cursor is in one of the handles, - * the new function will be moving or adding a new point or guide - */ - for (i = 0; i < measure_tool->num_points; i++) - { - gdisplay_transform_coords (gdisp, - measure_tool->x[i], measure_tool->y[i], - &x[i], &y[i], FALSE); - - if (bevent->x == CLAMP (bevent->x, x[i] - TARGET, x[i] + TARGET) && - bevent->y == CLAMP (bevent->y, y[i] - TARGET, y[i] + TARGET)) - { - if (bevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) - { - gboolean undo_group; - Guide *guide; - - undo_group = (bevent->state & GDK_CONTROL_MASK && - bevent->state & GDK_MOD1_MASK && - (measure_tool->y[i] == - CLAMP (measure_tool->y[i], - 0, gdisp->gimage->height)) && - (measure_tool->x[i] == - CLAMP (measure_tool->x[i], - 0, gdisp->gimage->width))); - - if (undo_group) - undo_push_group_start (gdisp->gimage, GUIDE_UNDO); - - if (bevent->state & GDK_CONTROL_MASK && - (measure_tool->y[i] == - CLAMP (measure_tool->y[i], 0, gdisp->gimage->height))) - { - guide = gimp_image_add_hguide (gdisp->gimage); - undo_push_guide (gdisp->gimage, guide); - guide->position = measure_tool->y[i]; - gdisplays_expose_guide (gdisp->gimage, guide); - } - - if (bevent->state & GDK_MOD1_MASK && - (measure_tool->x[i] == - CLAMP (measure_tool->x[i], 0, gdisp->gimage->width))) - { - guide = gimp_image_add_vguide (gdisp->gimage); - undo_push_guide (gdisp->gimage, guide); - guide->position = measure_tool->x[i]; - gdisplays_expose_guide (gdisp->gimage, guide); - } - - if (undo_group) - undo_push_group_end (gdisp->gimage); - - gdisplays_flush (); - measure_tool->function = GUIDING; - break; - } - measure_tool->function = (bevent->state & GDK_SHIFT_MASK) ? ADDING : MOVING; - measure_tool->point = i; - break; - } - } - - /* adding to the middle point makes no sense */ - if (i == 0 && measure_tool->function == ADDING && measure_tool->num_points == 3) - measure_tool->function = MOVING; - - /* if the function is still CREATING, we are outside the handles */ - if (measure_tool->function == CREATING) - { - if (measure_tool->num_points > 1 && bevent->state & GDK_MOD1_MASK) - { - measure_tool->function = MOVING_ALL; - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &measure_tool->last_x, &measure_tool->last_y, - TRUE, FALSE); - } - } - } - - if (measure_tool->function == CREATING) - { - if (tool->state == ACTIVE) - { - /* reset everything */ - draw_core_stop (measure_tool->core, tool); - - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), - measure_tool->context_id); - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - measure_tool->context_id, ""); - - distance_buf[0] = '\0'; - angle_buf[0] = '\0'; - if (measure_tool_info) - measure_tool_info_update (); - } - else - { - /* initialize the statusbar display */ - measure_tool->context_id = - gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), - "measure"); - } - - /* set the first point and go into ADDING mode */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &measure_tool->x[0], &measure_tool->y[0], - TRUE, FALSE); - measure_tool->point = 0; - measure_tool->num_points = 1; - measure_tool->function = ADDING; - - /* set the gdisplay */ - tool->gdisp = gdisp; - - /* start drawing the measure tool */ - draw_core_start (measure_tool->core, gdisp->canvas->window, tool); - } - - /* create the info window if necessary */ - if (! measure_tool_info && - (measure_tool_options->use_info_window || - ! GTK_WIDGET_VISIBLE (gdisp->statusarea))) - { - measure_tool_info = info_dialog_new (_("Measure Tool"), - tools_help_func, NULL); - info_dialog_add_label (measure_tool_info, _("Distance:"), distance_buf); - info_dialog_add_label (measure_tool_info, _("Angle:"), angle_buf); - - gimp_dialog_create_action_area (GTK_DIALOG (measure_tool_info->shell), - - _("Close"), - measure_tool_info_window_close_callback, - measure_tool_info, NULL, NULL, TRUE, FALSE, - - NULL); - } - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - tool->state = ACTIVE; - - /* set the pointer to the crosshair, - * so one actually sees the cursor position - */ - gdisplay_install_tool_cursor (gdisp, GIMP_CROSSHAIR_SMALL_CURSOR, - MEASURE, - CURSOR_MODIFIER_NONE, - FALSE); -} - -static void -measure_tool_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - MeasureTool *measure_tool; - - measure_tool = (MeasureTool *) tool->private; - - measure_tool->function = FINISHED; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); -} - -static void -measure_tool_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - MeasureTool *measure_tool; - gint x, y; - gint ax, ay; - gint bx, by; - gint dx, dy; - gint i; - gint tmp; - gdouble angle; - gdouble distance; - gchar status_str[STATUSBAR_SIZE]; - - measure_tool = (MeasureTool *) tool->private; - - /* undraw the current tool */ - draw_core_pause (measure_tool->core, tool); - - /* get the coordinates */ - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, FALSE); - - /* - * A few comments here, because this routine looks quite weird at first ... - * - * The goal is to keep point 0, called the start point, to be always the one - * in the middle or, if there are only two points, the one that is fixed. - * The angle is then always measured at this point. - */ - - switch (measure_tool->function) - { - case ADDING: - switch (measure_tool->point) - { - case 0: /* we are adding to the start point */ - break; - case 1: /* we are adding to the end point, make it the new start point */ - tmp = measure_tool->x[0]; - measure_tool->x[0] = measure_tool->x[1]; - measure_tool->x[1] = tmp; - tmp = measure_tool->y[0]; - measure_tool->y[0] = measure_tool->y[1]; - measure_tool->y[1] = tmp; - break; - case 2: /* we are adding to the third point, make it the new start point */ - measure_tool->x[1] = measure_tool->x[0]; - measure_tool->y[1] = measure_tool->y[0]; - measure_tool->x[0] = measure_tool->x[2]; - measure_tool->y[0] = measure_tool->y[2]; - break; - default: - break; - } - measure_tool->num_points = MIN (measure_tool->num_points + 1, 3); - measure_tool->point = measure_tool->num_points - 1; - measure_tool->function = MOVING; - /* no, don't break here! */ - - case MOVING: - /* if we are moving the start point and only have two, make it the end point */ - if (measure_tool->num_points == 2 && measure_tool->point == 0) - { - tmp = measure_tool->x[0]; - measure_tool->x[0] = measure_tool->x[1]; - measure_tool->x[1] = tmp; - tmp = measure_tool->y[0]; - measure_tool->y[0] = measure_tool->y[1]; - measure_tool->y[1] = tmp; - measure_tool->point = 1; - } - i = measure_tool->point; - - measure_tool->x[i] = x; - measure_tool->y[i] = y; - - /* restrict to horizontal/vertical movements, if modifiers are pressed */ - if (mevent->state & GDK_MOD1_MASK) - { - if (mevent->state & GDK_CONTROL_MASK) - { - dx = measure_tool->x[i] - measure_tool->x[0]; - dy = measure_tool->y[i] - measure_tool->y[0]; - - measure_tool->x[i] = measure_tool->x[0] + - (dx > 0 ? MAX (abs (dx), abs (dy)) : - MAX (abs (dx), abs (dy))); - measure_tool->y[i] = measure_tool->y[0] + - (dy > 0 ? MAX (abs (dx), abs (dy)) : - MAX (abs (dx), abs (dy))); - } - else - measure_tool->x[i] = measure_tool->x[0]; - } - else if (mevent->state & GDK_CONTROL_MASK) - measure_tool->y[i] = measure_tool->y[0]; - break; - - case MOVING_ALL: - dx = x - measure_tool->last_x; - dy = y - measure_tool->last_y; - for (i = 0; i < measure_tool->num_points; i++) - { - measure_tool->x[i] += dx; - measure_tool->y[i] += dy; - } - measure_tool->last_x = x; - measure_tool->last_y = y; - break; - - default: - break; - } - - if (measure_tool->function == MOVING) - { - /* calculate distance and angle */ - ax = measure_tool->x[1] - measure_tool->x[0]; - ay = measure_tool->y[1] - measure_tool->y[0]; - - if (measure_tool->num_points == 3) - { - bx = measure_tool->x[2] - measure_tool->x[0]; - by = measure_tool->y[2] - measure_tool->y[0]; - } - else - { - bx = 0; - by = 0; - } - - if (gdisp->dot_for_dot) - { - distance = sqrt (SQR (ax - bx) + SQR (ay - by)); - - if (measure_tool->num_points != 3) - bx = ax > 0 ? 1 : -1; - - measure_tool->angle1 = measure_get_angle (ax, ay, 1.0, 1.0); - measure_tool->angle2 = measure_get_angle (bx, by, 1.0, 1.0); - angle = fabs (measure_tool->angle1 - measure_tool->angle2); - if (angle > 180.0) - angle = fabs (360.0 - angle); - - g_snprintf (status_str, STATUSBAR_SIZE, "%.1f %s, %.2f %s", - distance, _("pixels"), angle, _("degrees")); - - if (measure_tool_options) - { - g_snprintf (distance_buf, MAX_INFO_BUF, "%.1f %s", distance, _("pixels")); - g_snprintf (angle_buf, MAX_INFO_BUF, "%.2f %s", angle, _("degrees")); - } - } - else /* show real world units */ - { - gchar *format_str = - g_strdup_printf ("%%.%df %s, %%.2f %s", - gimp_unit_get_digits (gdisp->gimage->unit), - gimp_unit_get_symbol (gdisp->gimage->unit), - _("degrees")); - - distance = gimp_unit_get_factor (gdisp->gimage->unit) * - sqrt (SQR ((gdouble)(ax - bx) / gdisp->gimage->xresolution) + - SQR ((gdouble)(ay - by) / gdisp->gimage->yresolution)); - - if (measure_tool->num_points != 3) - bx = ax > 0 ? 1 : -1; - - measure_tool->angle1 = measure_get_angle (ax, ay, - gdisp->gimage->xresolution, - gdisp->gimage->yresolution); - measure_tool->angle2 = measure_get_angle (bx, by, - gdisp->gimage->xresolution, - gdisp->gimage->yresolution); - angle = fabs (measure_tool->angle1 - measure_tool->angle2); - if (angle > 180.0) - angle = fabs (360.0 - angle); - - g_snprintf (status_str, STATUSBAR_SIZE, format_str, distance , angle); - g_free (format_str); - - if (measure_tool_options) - { - gchar *format_str = - g_strdup_printf ("%%.%df %s", - gimp_unit_get_digits (gdisp->gimage->unit), - gimp_unit_get_symbol (gdisp->gimage->unit)); - g_snprintf (distance_buf, MAX_INFO_BUF, format_str, distance); - g_snprintf (angle_buf, MAX_INFO_BUF, "%.2f %s", angle, _("degrees")); - g_free (format_str); - } - } - - /* show info in statusbar */ - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), - measure_tool->context_id); - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - measure_tool->context_id, - status_str); - - /* and in the info window */ - if (measure_tool_info) - measure_tool_info_update (); - - } /* measure_tool->function == MOVING */ - - /* redraw the current tool */ - draw_core_resume (measure_tool->core, tool); -} - -static void -measure_tool_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - MeasureTool *measure_tool; - gint x[3]; - gint y[3]; - gint i; - gboolean in_handle = FALSE; - - GdkCursorType ctype = GIMP_CROSSHAIR_SMALL_CURSOR; - CursorModifier cmodifier = CURSOR_MODIFIER_NONE; - - measure_tool = (MeasureTool *) tool->private; - - if (tool->state == ACTIVE && tool->gdisp == gdisp) - { - for (i = 0; i < measure_tool->num_points; i++) - { - gdisplay_transform_coords (gdisp, measure_tool->x[i], measure_tool->y[i], - &x[i], &y[i], FALSE); - - if (mevent->x == CLAMP (mevent->x, x[i] - TARGET, x[i] + TARGET) && - mevent->y == CLAMP (mevent->y, y[i] - TARGET, y[i] + TARGET)) - { - in_handle = TRUE; - - if (mevent->state & GDK_CONTROL_MASK) - { - if (mevent->state & GDK_MOD1_MASK) - ctype = GDK_BOTTOM_RIGHT_CORNER; - else - ctype = GDK_BOTTOM_SIDE; - break; - } - if (mevent->state & GDK_MOD1_MASK) - { - ctype = GDK_RIGHT_SIDE; - break; - } - - if (mevent->state & GDK_SHIFT_MASK) - cmodifier = CURSOR_MODIFIER_PLUS; - else - cmodifier = CURSOR_MODIFIER_MOVE; - - if (i == 0 && measure_tool->num_points == 3 && - cmodifier == CURSOR_MODIFIER_PLUS) - cmodifier = CURSOR_MODIFIER_MOVE; - break; - } - } - - if (!in_handle && measure_tool->num_points > 1 && - mevent->state & GDK_MOD1_MASK) - cmodifier = CURSOR_MODIFIER_MOVE; - } - - gdisplay_install_tool_cursor (gdisp, ctype, - MEASURE, - cmodifier, - FALSE); -} - -static void -measure_tool_draw (Tool *tool) -{ - MeasureTool *measure_tool; - gint x[3]; - gint y[3]; - gint i; - gint angle1, angle2; - gint draw_arc = 0; - - measure_tool = (MeasureTool *) tool->private; - - for (i = 0; i < measure_tool->num_points; i++) - { - gdisplay_transform_coords (tool->gdisp, - measure_tool->x[i], measure_tool->y[i], - &x[i], &y[i], FALSE); - if (i == 0 && measure_tool->num_points == 3) - { - gdk_draw_arc (measure_tool->core->win, measure_tool->core->gc, FALSE, - x[i] - (TARGET >> 1), y[i] - (TARGET >> 1), - TARGET, TARGET, 0, 23040); - } - else - { - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[i] - TARGET, y[i], - x[i] + TARGET, y[i]); - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[i], y[i] - TARGET, - x[i], y[i] + TARGET); - } - if (i > 0) - { - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[0], y[0], - x[i], y[i]); - /* only draw the arc if the lines are long enough */ - if ((SQR (x[i] - x[0]) + SQR (y[i] - y[0])) > ARC_RADIUS_2) - draw_arc++; - } - } - - if (measure_tool->num_points > 1 && draw_arc == measure_tool->num_points - 1) - { - angle1 = measure_tool->angle2 * 64.0; - angle2 = (measure_tool->angle1 - measure_tool->angle2) * 64.0; - - if (angle2 > 11520) - angle2 -= 23040; - if (angle2 < -11520) - angle2 += 23040; - - if (angle2 != 0) - { - gdk_draw_arc (measure_tool->core->win, measure_tool->core->gc, FALSE, - x[0] - ARC_RADIUS, y[0] - ARC_RADIUS, - 2 * ARC_RADIUS, 2 * ARC_RADIUS, - angle1, angle2); - - if (measure_tool->num_points == 2) - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[0], y[0], - x[1] - x[0] <= 0 ? x[0] - ARC_RADIUS - (TARGET >> 1) : - x[0] + ARC_RADIUS + (TARGET >> 1), - y[0]); - } - } -} - -static void -measure_tool_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - MeasureTool *measure_tool; - - measure_tool = (MeasureTool *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (measure_tool->core, tool); - break; - - case RESUME: - draw_core_resume (measure_tool->core, tool); - break; - - case HALT: - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), - measure_tool->context_id); - draw_core_stop (measure_tool->core, tool); - tool->state = INACTIVE; - break; - - default: - break; - } -} - -static void -measure_tool_info_update (void) -{ - info_dialog_update (measure_tool_info); - info_dialog_popup (measure_tool_info); -} - -static void -measure_tool_info_window_close_callback (GtkWidget *widget, - gpointer client_data) -{ - info_dialog_free (measure_tool_info); - measure_tool_info = NULL; -} - -Tool * -tools_new_measure_tool (void) -{ - Tool *tool; - MeasureTool *private; - - /* The tool options */ - if (! measure_tool_options) - { - measure_tool_options = measure_tool_options_new (); - tools_register (MEASURE, (ToolOptions *) measure_tool_options); - } - - tool = tools_new_tool (MEASURE); - private = g_new0 (MeasureTool, 1); - - private->core = draw_core_new (measure_tool_draw); - private->num_points = 0; - private->function = CREATING; - - tool->private = (void *) private; - - tool->preserve = TRUE; /* Preserve tool across drawable changes */ - - tool->button_press_func = measure_tool_button_press; - tool->button_release_func = measure_tool_button_release; - tool->motion_func = measure_tool_motion; - tool->cursor_update_func = measure_tool_cursor_update; - tool->control_func = measure_tool_control; - - return tool; -} - -void -tools_free_measure_tool (Tool *tool) -{ - MeasureTool *measure_tool; - - measure_tool = (MeasureTool *) tool->private; - - if (tool->state == ACTIVE) - { - gtk_statusbar_pop (GTK_STATUSBAR (tool->gdisp->statusbar), - measure_tool->context_id); - draw_core_stop (measure_tool->core, tool); - } - - draw_core_free (measure_tool->core); - - if (measure_tool_info) - { - info_dialog_free (measure_tool_info); - measure_tool_info = NULL; - } - - g_free (measure_tool); -} diff --git a/app/measure.h b/app/measure.h deleted file mode 100644 index c9004833bc..0000000000 --- a/app/measure.h +++ /dev/null @@ -1,27 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __MEASURE_H__ -#define __MEASURE_H__ - - -Tool * tools_new_measure_tool (void); -void tools_free_measure_tool (Tool *tool); - - -#endif /* __MEASURE_H__ */ diff --git a/app/menus.c b/app/menus.c index 20b13ec2af..55c0636ff1 100644 --- a/app/menus.c +++ b/app/menus.c @@ -31,6 +31,7 @@ #include "commands.h" #include "dialog_handler.h" #include "fileops.h" +#include "gdisplay.h" #include "gimphelp.h" #include "gimprc.h" #include "gimpui.h" @@ -41,8 +42,8 @@ #include "paint_funcs.h" #include "preferences_dialog.h" #include "scale.h" -#include "tools.h" -#include "gdisplay.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" diff --git a/app/menus/menus.c b/app/menus/menus.c index 20b13ec2af..55c0636ff1 100644 --- a/app/menus/menus.c +++ b/app/menus/menus.c @@ -31,6 +31,7 @@ #include "commands.h" #include "dialog_handler.h" #include "fileops.h" +#include "gdisplay.h" #include "gimphelp.h" #include "gimprc.h" #include "gimpui.h" @@ -41,8 +42,8 @@ #include "paint_funcs.h" #include "preferences_dialog.h" #include "scale.h" -#include "tools.h" -#include "gdisplay.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" diff --git a/app/move.c b/app/move.c deleted file mode 100644 index 1818da444b..0000000000 --- a/app/move.c +++ /dev/null @@ -1,553 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" -#include "appenv.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "edit_selection.h" -#include "floating_sel.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gdisplay_ops.h" -#include "gdisplay.h" -#include "layer.h" -#include "move.h" -#include "selection.h" -#include "tools.h" -#include "tool_options.h" -#include "undo.h" - -#include "config.h" -#include "libgimp/gimpintl.h" - -/* the move structures */ - -typedef struct _MoveTool MoveTool; - -struct _MoveTool -{ - Layer *layer; - Guide *guide; - GDisplay *disp; -}; - - -/* move tool action functions */ -static void move_tool_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void move_tool_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void move_tool_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void move_tool_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void move_tool_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static void move_create_gc (GDisplay *gdisp); - - -/* the move tool options */ -static ToolOptions *move_options = NULL; - -/* local variables */ -static GdkGC *move_gc = NULL; - - -/* move action functions */ - -static void -move_tool_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - MoveTool *move; - Layer *layer; - Guide *guide; - gint x, y; - - move = (MoveTool *) tool->private; - - tool->gdisp = gdisp; - move->layer = NULL; - move->guide = NULL; - move->disp = NULL; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, - FALSE, FALSE); - - if (bevent->state & GDK_MOD1_MASK && - !gimage_mask_is_empty (gdisp->gimage)) - { - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE); - tool->state = ACTIVE; - } - else if (bevent->state & GDK_SHIFT_MASK) - { - init_edit_selection (tool, gdisp, bevent, EDIT_LAYER_TRANSLATE); - tool->state = ACTIVE; - } - else - { - if (gdisp->draw_guides && - (guide = gdisplay_find_guide (gdisp, bevent->x, bevent->y))) - { - undo_push_guide (gdisp->gimage, guide); - - gdisplays_expose_guide (gdisp->gimage, guide); - gimp_image_remove_guide (gdisp->gimage, guide); - gdisplay_flush (gdisp); - gimp_image_add_guide (gdisp->gimage, guide); - - move->guide = guide; - move->disp = gdisp; - - tool->scroll_lock = TRUE; - tool->state = ACTIVE; - - move_tool_motion (tool, NULL, gdisp); - } - else if ((layer = gimp_image_pick_correlate_layer (gdisp->gimage, x, y))) - { - /* If there is a floating selection, and this aint it, - * use the move tool - */ - if (gimp_image_floating_sel (gdisp->gimage) && - !layer_is_floating_sel (layer)) - { - move->layer = gimp_image_floating_sel (gdisp->gimage); - } - /* Otherwise, init the edit selection */ - else - { - gimp_image_set_active_layer (gdisp->gimage, layer); - init_edit_selection (tool, gdisp, bevent, EDIT_LAYER_TRANSLATE); - } - tool->state = ACTIVE; - } - } - - /* if we've got an active tool grab the pointer */ - if (tool->state == ACTIVE) - { - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - } -} - -static void -move_draw_guide (GDisplay *gdisp, - Guide *guide) -{ - gint x1, y1; - gint x2, y2; - gint w, h; - gint x, y; - - if (!move_gc) - move_create_gc (gdisp); - - if (guide->position == -1) - return; - - gdisplay_transform_coords (gdisp, gdisp->gimage->width, - gdisp->gimage->height, &x2, &y2, FALSE); - - gdk_window_get_size (gdisp->canvas->window, &w, &h); - - switch (guide->orientation) - { - case ORIENTATION_HORIZONTAL: - gdisplay_transform_coords (gdisp, 0, guide->position, &x1, &y, FALSE); - if (x1 < 0) x1 = 0; - if (x2 > w) x2 = w; - - gdk_draw_line (gdisp->canvas->window, move_gc, x1, y, x2, y); - break; - - case ORIENTATION_VERTICAL: - gdisplay_transform_coords (gdisp, guide->position, 0, &x, &y1, FALSE); - if (y1 < 0) y1 = 0; - if (y2 > h) y2 = h; - - gdk_draw_line (gdisp->canvas->window, move_gc, x, y1, x, y2); - break; - - default: - g_warning ("mdg / BAD FALLTHROUGH"); - break; - } -} - -static void -move_tool_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - MoveTool *move; - gboolean delete_guide; - gint x1, y1; - gint x2, y2; - - move = (MoveTool *) tool->private; - - gdk_flush (); - - tool->state = INACTIVE; - gdk_pointer_ungrab (bevent->time); - - if (move->guide) - { - tool->scroll_lock = FALSE; - - delete_guide = FALSE; - gdisplay_untransform_coords (gdisp, 0, 0, &x1, &y1, FALSE, FALSE); - gdisplay_untransform_coords (gdisp, gdisp->disp_width, gdisp->disp_height, - &x2, &y2, FALSE, FALSE); - - if (x1 < 0) x1 = 0; - if (y1 < 0) y1 = 0; - if (x2 > gdisp->gimage->width) x2 = gdisp->gimage->width; - if (y2 > gdisp->gimage->height) y2 = gdisp->gimage->height; - - switch (move->guide->orientation) - { - case ORIENTATION_HORIZONTAL: - if ((move->guide->position < y1) || (move->guide->position > y2)) - delete_guide = TRUE; - break; - - case ORIENTATION_VERTICAL: - if ((move->guide->position < x1) || (move->guide->position > x2)) - delete_guide = TRUE; - break; - - default: - break; - } - - gdisplays_expose_guide (gdisp->gimage, move->guide); - - if (delete_guide) - { - move_draw_guide (gdisp, move->guide); - gimp_image_delete_guide (gdisp->gimage, move->guide); - move->guide = NULL; - move->disp = NULL; - } - else - { - move_tool_motion (tool, NULL, gdisp); - } - - selection_resume (gdisp->select); - gdisplays_flush (); - - if (move->guide) - gdisplay_draw_guide (gdisp, move->guide, TRUE); - } - else - { - /* Take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - if (move->layer) - { - floating_sel_anchor (move->layer); - gdisplays_flush (); - } - } - } -} - -static void -move_tool_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) - -{ - MoveTool *move; - gint x, y; - - move = (MoveTool *) tool->private; - - if (move->guide) - { - move_draw_guide (gdisp, move->guide); - - if (mevent && mevent->window != gdisp->canvas->window) - { - move->guide->position = -1; - return; - } - - if (mevent) - { - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &x, &y, TRUE, FALSE); - - if (move->guide->orientation == ORIENTATION_HORIZONTAL) - move->guide->position = y; - else - move->guide->position = x; - - move_draw_guide (gdisp, move->guide); - } - } -} - -static void -move_tool_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - MoveTool *move; - Guide *guide; - Layer *layer; - gint x, y; - - move = (MoveTool *) tool->private; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, - FALSE, FALSE); - - if (mevent->state & GDK_MOD1_MASK && - !gimage_mask_is_empty (gdisp->gimage)) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_MOVE, - FALSE); - } - else if (mevent->state & GDK_SHIFT_MASK) - { - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - MOVE, - CURSOR_MODIFIER_NONE, - FALSE); - } - else - { - if (gdisp->draw_guides && - (guide = gdisplay_find_guide (gdisp, mevent->x, mevent->y))) - { - tool->gdisp = gdisp; - gdisplay_install_tool_cursor (gdisp, GDK_HAND2, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_HAND, - FALSE); - - if (tool->state != ACTIVE) - { - if (move->guide) - { - gdisp = gdisplays_check_valid (move->disp, move->disp->gimage); - if (gdisp) - gdisplay_draw_guide (gdisp, move->guide, FALSE); - } - - gdisp = gdisp; - gdisplay_draw_guide (gdisp, guide, TRUE); - move->guide = guide; - move->disp = gdisp; - } - } - else if ((layer = gimp_image_pick_correlate_layer (gdisp->gimage, x, y))) - { - /* if there is a floating selection, and this aint it... */ - if (gimp_image_floating_sel (gdisp->gimage) && - !layer_is_floating_sel (layer)) - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - RECT_SELECT, - CURSOR_MODIFIER_ANCHOR, - FALSE); - else if (layer == gdisp->gimage->active_layer) - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - MOVE, - CURSOR_MODIFIER_NONE, - FALSE); - else - gdisplay_install_tool_cursor (gdisp, GDK_HAND2, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_HAND, - FALSE); - } - else - { - gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, - MOVE, - CURSOR_MODIFIER_NONE, - FALSE); - } - } -} - - -static void -move_tool_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - MoveTool *move; - - move = tool->private; - - switch (action) - { - case PAUSE: - break; - - case RESUME: - if (move->guide) - gdisplay_draw_guide (gdisp, move->guide, TRUE); - break; - - case HALT: - break; - - default: - break; - } -} - -static void -move_create_gc (GDisplay *gdisp) -{ - if (!move_gc) - { - GdkGCValues values; - - values.foreground.pixel = gdisplay_white_pixel (gdisp); - values.function = GDK_INVERT; - move_gc = gdk_gc_new_with_values (gdisp->canvas->window, &values, - GDK_GC_FUNCTION); - } -} - -void -move_tool_start_hguide (Tool *tool, - GDisplay *gdisp) -{ - MoveTool *private; - - selection_pause (gdisp->select); - - tool->gdisp = gdisp; - tool->scroll_lock = TRUE; - - private = tool->private; - - if (private->guide && private->disp && private->disp->gimage) - gdisplay_draw_guide (private->disp, private->guide, FALSE); - - private->guide = gimp_image_add_hguide (gdisp->gimage); - private->disp = gdisp; - - tool->state = ACTIVE; - - undo_push_guide (gdisp->gimage, private->guide); -} - -void -move_tool_start_vguide (Tool *tool, - GDisplay *gdisp) -{ - MoveTool *private; - - selection_pause (gdisp->select); - - tool->gdisp = gdisp; - tool->scroll_lock = TRUE; - - private = tool->private; - - if (private->guide && private->disp && private->disp->gimage) - gdisplay_draw_guide (private->disp, private->guide, FALSE); - - private->guide = gimp_image_add_vguide (gdisp->gimage); - private->disp = gdisp; - - tool->state = ACTIVE; - - undo_push_guide (gdisp->gimage, private->guide); -} - -Tool * -tools_new_move_tool (void) -{ - Tool *tool; - MoveTool *private; - - /* The tool options */ - if (! move_options) - { - move_options = tool_options_new (_("Move Tool")); - tools_register (MOVE, (ToolOptions *) move_options); - } - - tool = tools_new_tool (MOVE); - private = g_new0 (MoveTool, 1); - - private->layer = NULL; - private->guide = NULL; - private->disp = NULL; - - tool->auto_snap_to = FALSE; /* Don't snap to guides */ - - tool->private = (void *) private; - - tool->button_press_func = move_tool_button_press; - tool->button_release_func = move_tool_button_release; - tool->motion_func = move_tool_motion; - tool->arrow_keys_func = edit_sel_arrow_keys_func; - tool->cursor_update_func = move_tool_cursor_update; - tool->control_func = move_tool_control; - - return tool; -} - -void -tools_free_move_tool (Tool *tool) -{ - MoveTool *move; - - move = (MoveTool *) tool->private; - - if (tool->gdisp) - { - if (move->guide) - gdisplay_draw_guide (tool->gdisp, move->guide, FALSE); - } - - g_free (move); -} diff --git a/app/move.h b/app/move.h deleted file mode 100644 index f4f97c1c46..0000000000 --- a/app/move.h +++ /dev/null @@ -1,32 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __MOVE_H__ -#define __MOVE_H__ - - -void move_tool_start_hguide (Tool *tool, - GDisplay *gdisp); -void move_tool_start_vguide (Tool *tool, - GDisplay *gdisp); - -Tool * tools_new_move_tool (void); -void tools_free_move_tool (Tool *tool); - - -#endif /* __MOVE_H__ */ diff --git a/app/paint_core.c b/app/paint_core.c deleted file mode 100644 index d3829c3d68..0000000000 --- a/app/paint_core.c +++ /dev/null @@ -1,2151 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "brush_scale.h" -#include "cursorutil.h" -#include "devices.h" -#include "draw_core.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpbrushpipe.h" -#include "gimpcontext.h" -#include "gimpimage.h" -#include "gimprc.h" -#include "gradient.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "pixel_region.h" -#include "selection.h" -#include "temp_buf.h" -#include "tile.h" -#include "tile_manager.h" -#include "tools.h" -#include "undo.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - -#include "paint_core_kernels.h" - -/* target size */ -#define TARGET_HEIGHT 15 -#define TARGET_WIDTH 15 - -#define EPSILON 0.00001 - -#define STATUSBAR_SIZE 128 - -/* global variables--for use in the various paint tools */ -PaintCore non_gui_paint_core; - -/* local function prototypes */ -static void paint_core_calculate_brush_size (MaskBuf *mask, - gdouble scale, - gint *width, - gint *height); -static MaskBuf * paint_core_subsample_mask (MaskBuf *mask, - gdouble x, - gdouble y); -static MaskBuf * paint_core_pressurize_mask (MaskBuf *brush_mask, - gdouble x, - gdouble y, - gdouble pressure); -static MaskBuf * paint_core_solidify_mask (MaskBuf *brush_mask); -static MaskBuf * paint_core_scale_mask (MaskBuf *brush_mask, - gdouble scale); -static MaskBuf * paint_core_scale_pixmap (MaskBuf *brush_mask, - gdouble scale); - -static MaskBuf * paint_core_get_brush_mask (PaintCore *paint_core, - BrushApplicationMode brush_hardness, - gdouble scale); -static void paint_core_paste (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - LayerModeEffects paint_mode, - PaintApplicationMode mode); -static void paint_core_replace (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - PaintApplicationMode mode); - -static void brush_to_canvas_tiles (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity); -static void brush_to_canvas_buf (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity); -static void canvas_tiles_to_canvas_buf (PaintCore *paint_core); - -static void set_undo_tiles (GimpDrawable *drawable, - gint x, - gint y, - gint w, - gint h); -static void set_canvas_tiles (gint x, - gint y, - gint w, - gint h); -static void paint_core_invalidate_cache (GimpBrush *brush, - gpointer data); - - -/* paint buffers utility functions */ -static void free_paint_buffers (void); - -/* brush pipe utility functions */ -static void paint_line_pixmap_mask (GimpImage *dest, - GimpDrawable *drawable, - TempBuf *pixmap_mask, - TempBuf *brush_mask, - guchar *d, - gint x, - gint y, - gint bytes, - gint width, - BrushApplicationMode mode); - -/***********************************************************************/ - - -/* undo blocks variables */ -static TileManager *undo_tiles = NULL; -static TileManager *canvas_tiles = NULL; - - -/***********************************************************************/ - - -/* paint buffers variables */ -static TempBuf *orig_buf = NULL; -static TempBuf *canvas_buf = NULL; - - -/* brush buffers */ -static MaskBuf *pressure_brush; -static MaskBuf *solid_brush; -static MaskBuf *scale_brush = NULL; -static MaskBuf *scale_pixmap = NULL; -static MaskBuf *kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1]; - -static MaskBuf *last_brush_mask = NULL; -static gboolean cache_invalid = FALSE; - - -/***********************************************************************/ - -static void -paint_core_sample_color (GimpDrawable *drawable, - gint x, - gint y, - gint state) -{ - GimpRGB color; - guchar *col; - - if( x >= 0 && x < gimp_drawable_width (drawable) && - y >= 0 && y < gimp_drawable_height (drawable)) - { - if ((col = gimp_drawable_get_color_at (drawable, x, y))) - { - gimp_rgba_set_uchar (&color, - col[RED_PIX], - col[GREEN_PIX], - col[BLUE_PIX], - 255); - - if ((state & GDK_CONTROL_MASK)) - gimp_context_set_foreground (gimp_context_get_user (), &color); - else - gimp_context_set_background (gimp_context_get_user (), &color); - - g_free (col); - } - } -} - - -void -paint_core_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - PaintCore *paint_core; - GimpBrush *current_brush; - gboolean draw_line; - gdouble x, y; - GimpDrawable *drawable; - - paint_core = (PaintCore *) tool->private; - - g_return_if_fail (gdisp != NULL); - g_return_if_fail (paint_core != NULL); - - gdisplay_untransform_coords_f (gdisp, (double) bevent->x, (double) bevent->y, - &x, &y, TRUE); - drawable = gimp_image_active_drawable (gdisp->gimage); - - if (! paint_core_init (paint_core, drawable, x, y)) - return; - - draw_line = FALSE; - - paint_core->curpressure = bevent->pressure; - paint_core->curxtilt = bevent->xtilt; - paint_core->curytilt = bevent->ytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = bevent->wheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - paint_core->state = bevent->state; - - if (gdisp != tool->gdisp || - paint_core->context_id < 1) - { - /* initialize the statusbar display */ - paint_core->context_id = - gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); - } - - /* if this is a new image, reinit the core vals */ - if ((gdisp != tool->gdisp) || ! (bevent->state & GDK_SHIFT_MASK)) - { - /* initialize some values */ - paint_core->startx = paint_core->lastx = paint_core->curx = x; - paint_core->starty = paint_core->lasty = paint_core->cury = y; - paint_core->startpressure = paint_core->lastpressure = paint_core->curpressure; - paint_core->startytilt = paint_core->lastytilt = paint_core->curytilt; - paint_core->startxtilt = paint_core->lastxtilt = paint_core->curxtilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->startwheel = paint_core->lastwheel = paint_core->curwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - } - - /* If shift is down and this is not the first paint - * stroke, then draw a line from the last coords to the pointer - */ - else if (bevent->state & GDK_SHIFT_MASK) - { - draw_line = TRUE; - paint_core->startx = paint_core->lastx; - paint_core->starty = paint_core->lasty; - paint_core->startpressure = paint_core->lastpressure; - paint_core->startxtilt = paint_core->lastxtilt; - paint_core->startytilt = paint_core->lastytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->startwheel = paint_core->lastwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - /* Restrict to multiples of 15 degrees if ctrl is pressed */ - if (bevent->state & GDK_CONTROL_MASK) - { - gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; - gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; - gint dx, dy, i, radius, frac; - - dx = paint_core->curx - paint_core->lastx; - dy = paint_core->cury - paint_core->lasty; - - if (dy) - { - radius = sqrt (SQR (dx) + SQR (dy)); - frac = abs ((dx << 8) / dy); - for (i = 0; i < 6; i++) - { - if (frac < tangens2[i]) - break; - } - dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); - dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); - } - paint_core->curx = paint_core->lastx + dx; - paint_core->cury = paint_core->lasty + dy; - } - } - - tool->state = ACTIVE; - tool->gdisp = gdisp; - tool->paused_count = 0; - - /* pause the current selection and grab the pointer */ - gdisplays_selection_visibility (gdisp->gimage, SelectionPause); - - /* add motion memory if perfectmouse is set */ - if (perfectmouse != 0) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - else - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - /* Let the specific painting function initialize itself */ - (* paint_core->paint_func) (paint_core, drawable, INIT_PAINT); - - if (paint_core->pick_colors - && !(bevent->state & GDK_SHIFT_MASK) - && (bevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) - { - paint_core_sample_color (drawable, x, y, bevent->state); - paint_core->pick_state = TRUE; - return; - } - else - paint_core->pick_state = FALSE; - - /* store the current brush pointer */ - current_brush = paint_core->brush; - - /* Paint to the image */ - if (draw_line) - { - draw_core_pause (paint_core->core, tool); - paint_core_interpolate (paint_core, drawable); - - paint_core->lastx = paint_core->curx; - paint_core->lasty = paint_core->cury; - paint_core->lastpressure = paint_core->curpressure; - paint_core->lastxtilt = paint_core->curxtilt; - paint_core->lastytilt = paint_core->curytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->lastwheel = paint_core->curwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - } - else - { - /* If we current point == last point, check if the brush - * wants to be painted in that case. (Direction dependent - * pixmap brush pipes don't, as they don't know which - * pixmap to select.) - */ - if (paint_core->lastx != paint_core->curx - || paint_core->lasty != paint_core->cury - || (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_core->brush) - ->klass)->want_null_motion) (paint_core)) - { - if (paint_core->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) - paint_core->brush = - (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_core->brush) - ->klass)->select_brush) (paint_core); - - (* paint_core->paint_func) (paint_core, drawable, MOTION_PAINT); - } - } - - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, drawable, PRETRACE_PAINT); - - gdisplay_flush_now (gdisp); - - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, drawable, POSTTRACE_PAINT); - - /* restore the current brush pointer */ - paint_core->brush = current_brush; -} - -void -paint_core_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - GImage *gimage; - PaintCore *paint_core; - - gimage = gdisp->gimage; - paint_core = (PaintCore *) tool->private; - - /* resume the current selection and ungrab the pointer */ - gdisplays_selection_visibility (gdisp->gimage, SelectionResume); - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - /* Let the specific painting function finish up */ - (* paint_core->paint_func) (paint_core, - gimp_image_active_drawable (gdisp->gimage), - FINISH_PAINT); - - /* Set tool state to inactive -- no longer painting */ - draw_core_stop (paint_core->core, tool); - tool->state = INACTIVE; - - paint_core->pick_state = FALSE; - - paint_core_finish (paint_core, gimp_image_active_drawable (gdisp->gimage), - tool->ID); - gdisplays_flush (); -} - -void -paint_core_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - PaintCore *paint_core; - - paint_core = (PaintCore *) tool->private; - - gdisplay_untransform_coords_f (gdisp, (double) mevent->x, (double) mevent->y, - &paint_core->curx, &paint_core->cury, TRUE); - - if (paint_core->pick_state) - { - paint_core_sample_color (gimp_image_active_drawable (gdisp->gimage), - paint_core->curx, paint_core->cury, - mevent->state); - return; - } - - paint_core->curpressure = mevent->pressure; - paint_core->curxtilt = mevent->xtilt; - paint_core->curytilt = mevent->ytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = mevent->wheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - paint_core->state = mevent->state; - - paint_core_interpolate (paint_core, - gimp_image_active_drawable (gdisp->gimage)); - - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, - gimp_image_active_drawable (gdisp->gimage), - PRETRACE_PAINT); - - gdisplay_flush_now (gdisp); - - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, - gimp_image_active_drawable (gdisp->gimage), - POSTTRACE_PAINT); - - paint_core->lastx = paint_core->curx; - paint_core->lasty = paint_core->cury; - paint_core->lastpressure = paint_core->curpressure; - paint_core->lastxtilt = paint_core->curxtilt; - paint_core->lastytilt = paint_core->curytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->lastwheel = paint_core->curwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ -} - -void -paint_core_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Layer *layer; - PaintCore *paint_core; - gint x, y; - gchar status_str[STATUSBAR_SIZE]; - - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; - CursorModifier cmodifier = CURSOR_MODIFIER_NONE; - gboolean ctoggle = FALSE; - - paint_core = (PaintCore *) tool->private; - - /* undraw the current tool */ - draw_core_pause (paint_core->core, tool); - - if (gdisp != tool->gdisp || paint_core->context_id < 1) - { - /* initialize the statusbar display */ - paint_core->context_id = - gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); - } - - if (paint_core->context_id) - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), paint_core->context_id); - - if ((layer = gimp_image_get_active_layer (gdisp->gimage))) - { - /* If shift is down and this is not the first paint stroke, draw a line */ - if (gdisp == tool->gdisp && (mevent->state & GDK_SHIFT_MASK)) - { - gdouble dx, dy, d; - - ctype = GDK_PENCIL; - /* Get the current coordinates */ - gdisplay_untransform_coords_f (gdisp, - (double) mevent->x, - (double) mevent->y, - &paint_core->curx, - &paint_core->cury, TRUE); - - dx = paint_core->curx - paint_core->lastx; - dy = paint_core->cury - paint_core->lasty; - - /* Restrict to multiples of 15 degrees if ctrl is pressed */ - if (mevent->state & GDK_CONTROL_MASK) - { - gint idx = dx; - gint idy = dy; - gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; - gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; - gint i, radius, frac; - - if (idy) - { - radius = sqrt (SQR (idx) + SQR (idy)); - frac = abs ((idx << 8) / idy); - for (i = 0; i < 6; i++) - { - if (frac < tangens2[i]) - break; - } - dx = idx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); - dy = idy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); - } - - paint_core->curx = paint_core->lastx + dx; - paint_core->cury = paint_core->lasty + dy; - } - - /* show distance in statusbar */ - if (gdisp->dot_for_dot) - { - d = sqrt (SQR (dx) + SQR (dy)); - g_snprintf (status_str, STATUSBAR_SIZE, "%.1f %s", d, _("pixels")); - } - else - { - gchar *format_str = - g_strdup_printf ("%%.%df %s", - gimp_unit_get_digits (gdisp->gimage->unit), - gimp_unit_get_symbol (gdisp->gimage->unit)); - d = (gimp_unit_get_factor (gdisp->gimage->unit) * - sqrt (SQR (dx / gdisp->gimage->xresolution) + - SQR (dy / gdisp->gimage->yresolution))); - - g_snprintf (status_str, STATUSBAR_SIZE, format_str, d); - g_free (format_str); - } - - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - paint_core->context_id, status_str); - - if (paint_core->core->gc == NULL) - { - draw_core_start (paint_core->core, gdisp->canvas->window, tool); - } - else - { - /* is this a bad hack ? */ - paint_core->core->paused_count = 0; - draw_core_resume (paint_core->core, tool); - } - } - /* If Ctrl or Mod1 is pressed, pick colors */ - else if (paint_core->pick_colors && - !(mevent->state & GDK_SHIFT_MASK) && - (mevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) - { - ctype = GIMP_COLOR_PICKER_CURSOR; - } - /* Set toggle cursors for various paint tools */ - else if (tool->toggled) - { - switch (tool->type) - { - case ERASER: - ctype = GIMP_MOUSE_CURSOR; - cmodifier = CURSOR_MODIFIER_MINUS; - break; - case CONVOLVE: - ctype = GIMP_MOUSE_CURSOR; - cmodifier = CURSOR_MODIFIER_MINUS; - break; - case DODGEBURN: - ctype = GIMP_MOUSE_CURSOR; - ctoggle = TRUE; - break; - default: - ctype = GIMP_MOUSE_CURSOR; - break; - } - } - /* Normal operation -- no modifier pressed or first stroke */ - else - { - gint off_x, off_y; - - gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); - gdisplay_untransform_coords (gdisp, - (double) mevent->x, (double) mevent->y, - &x, &y, TRUE, FALSE); - - if (x >= off_x && y >= off_y && - x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && - y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) - { - /* One more test--is there a selected region? - * if so, is cursor inside? - */ - if (gimage_mask_is_empty (gdisp->gimage)) - ctype = GIMP_MOUSE_CURSOR; - else if (gimage_mask_value (gdisp->gimage, x, y)) - ctype = GIMP_MOUSE_CURSOR; - } - } - gdisplay_install_tool_cursor (gdisp, ctype, - ctype == GIMP_COLOR_PICKER_CURSOR ? - COLOR_PICKER : tool->type, - cmodifier, - ctoggle); - } -} - -void -paint_core_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - PaintCore *paint_core; - GimpDrawable *drawable; - - paint_core = (PaintCore *) tool->private; - drawable = gimp_image_active_drawable (gdisp->gimage); - - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - (* paint_core->paint_func) (paint_core, drawable, FINISH_PAINT); - draw_core_stop (paint_core->core, tool); - paint_core_cleanup (); - break; - - default: - break; - } -} - -void -paint_core_draw (Tool *tool) -{ - GDisplay *gdisp; - PaintCore *paint_core; - gint tx1, ty1, tx2, ty2; - - paint_core = (PaintCore *) tool->private; - - /* if shift was never used, paint_core->core->gc is NULL - and we don't care about a redraw */ - if (paint_core->core->gc != NULL) - { - gdisp = tool->gdisp; - - gdisplay_transform_coords (gdisp, paint_core->lastx, paint_core->lasty, - &tx1, &ty1, 1); - gdisplay_transform_coords (gdisp, paint_core->curx, paint_core->cury, - &tx2, &ty2, 1); - - /* Only draw line if it's in the visible area - * thus preventing from drawing rubbish - */ - - if (tx2 > 0 && ty2 > 0) - { - gint offx, offy; - - /* Adjust coords to start drawing from center of pixel if zoom > 1 */ - offx = (int) SCALEFACTOR_X (gdisp) >> 1; - offy = (int) SCALEFACTOR_Y (gdisp) >> 1; - tx1 += offx; - ty1 += offy; - tx2 += offx; - ty2 += offy; - - /* Draw start target */ - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, - tx1 - (TARGET_WIDTH >> 1), ty1, - tx1 + (TARGET_WIDTH >> 1), ty1); - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, - tx1, ty1 - (TARGET_HEIGHT >> 1), - tx1, ty1 + (TARGET_HEIGHT >> 1)); - - /* Draw end target */ - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, - tx2 - (TARGET_WIDTH >> 1), ty2, - tx2 + (TARGET_WIDTH >> 1), ty2); - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, - tx2, ty2 - (TARGET_HEIGHT >> 1), - tx2, ty2 + (TARGET_HEIGHT >> 1)); - - /* Draw the line between the start and end coords */ - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, - tx1, ty1, tx2, ty2); - } - } - return; -} - -Tool * -paint_core_new (ToolType type) -{ - Tool *tool; - PaintCore *private; - - tool = tools_new_tool (type); - private = g_new0 (PaintCore, 1); - - private->core = draw_core_new (paint_core_draw); - - private->pick_colors = FALSE; - private->flags = 0; - private->context_id = 0; - - tool->private = (void *) private; - tool->button_press_func = paint_core_button_press; - tool->button_release_func = paint_core_button_release; - tool->motion_func = paint_core_motion; - tool->cursor_update_func = paint_core_cursor_update; - tool->control_func = paint_core_control; - - return tool; -} - -void -paint_core_free (Tool *tool) -{ - PaintCore * paint_core; - - paint_core = (PaintCore *) tool->private; - - /* Make sure the selection core is not visible */ - if (tool->state == ACTIVE && paint_core->core) - draw_core_stop (paint_core->core, tool); - - /* Free the selection core */ - if (paint_core->core) - draw_core_free (paint_core->core); - - /* Cleanup memory */ - paint_core_cleanup (); - - /* Free the paint core */ - g_free (paint_core); -} - -gboolean -paint_core_init (PaintCore *paint_core, - GimpDrawable *drawable, - gdouble x, - gdouble y) -{ - static GimpBrush *brush = NULL; - - paint_core->curx = x; - paint_core->cury = y; - - /* Set up some defaults for non-gui use */ - if (paint_core == &non_gui_paint_core) - { - paint_core->startpressure = paint_core->lastpressure = paint_core->curpressure = 0.5; - paint_core->startxtilt = paint_core->lastxtilt = paint_core->curxtilt = 0; - paint_core->startytilt = paint_core->lastytilt = paint_core->curytilt = 0; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->startwheel = paint_core->lastwheel = paint_core->curwheel = 0.5; -#endif /* GTK_HAVE_SIX_VALUATORS */ - } - - /* Each buffer is the same size as the maximum bounds of the active brush... */ - if (brush && brush != gimp_context_get_brush (NULL)) - { - gtk_signal_disconnect_by_func (GTK_OBJECT (brush), - GTK_SIGNAL_FUNC (paint_core_invalidate_cache), - NULL); - gtk_object_unref (GTK_OBJECT (brush)); - } - if (!(brush = gimp_context_get_brush (NULL))) - { - g_message (_("No brushes available for use with this tool.")); - return FALSE; - } - - gtk_object_ref (GTK_OBJECT (brush)); - gtk_signal_connect (GTK_OBJECT (brush), "dirty", - GTK_SIGNAL_FUNC (paint_core_invalidate_cache), - NULL); - - paint_core->spacing = (double) gimp_brush_get_spacing (brush) / 100.0; - - paint_core->brush = brush; - - /* free the block structures */ - if (undo_tiles) - tile_manager_destroy (undo_tiles); - if (canvas_tiles) - tile_manager_destroy (canvas_tiles); - - /* Allocate the undo structure */ - undo_tiles = tile_manager_new (gimp_drawable_width (drawable), - gimp_drawable_height (drawable), - gimp_drawable_bytes (drawable)); - - /* Allocate the canvas blocks structure */ - canvas_tiles = tile_manager_new (gimp_drawable_width (drawable), - gimp_drawable_height (drawable), 1); - - /* Get the initial undo extents */ - paint_core->x1 = paint_core->x2 = paint_core->curx; - paint_core->y1 = paint_core->y2 = paint_core->cury; - paint_core->distance = 0.0; - paint_core->pixel_dist = 0.0; - - return TRUE; -} - -void -paint_core_interpolate (PaintCore *paint_core, - GimpDrawable *drawable) -{ - GimpBrush *current_brush; - GimpVector2 delta; - gdouble dpressure, dxtilt, dytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - gdouble dwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - /* double spacing; */ - /* double lastscale, curscale; */ - gdouble n; - gdouble left; - gdouble t; - gdouble initial; - gdouble dist; - gdouble total; - gdouble pixel_dist; - gdouble pixel_initial; - gdouble xd, yd; - gdouble mag; - - delta.x = paint_core->curx - paint_core->lastx; - delta.y = paint_core->cury - paint_core->lasty; - dpressure = paint_core->curpressure - paint_core->lastpressure; - dxtilt = paint_core->curxtilt - paint_core->lastxtilt; - dytilt = paint_core->curytilt - paint_core->lastytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - dwheel = paint_core->curwheel - paint_core->lastwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - -/* return if there has been no motion */ -#ifdef GTK_HAVE_SIX_VALUATORS - if (!delta.x && !delta.y && !dpressure && !dxtilt && !dytilt && !dwheel) -#else /* !GTK_HAVE_SIX_VALUATORS */ - if (!delta.x && !delta.y && !dpressure && !dxtilt && !dytilt) -#endif /* GTK_HAVE_SIX_VALUATORS */ - return; - - /* calculate the distance traveled in the coordinate space of the brush */ - mag = gimp_vector2_length (&(paint_core->brush->x_axis)); - xd = gimp_vector2_inner_product (&delta, - &(paint_core->brush->x_axis)) / (mag*mag); - - mag = gimp_vector2_length (&(paint_core->brush->y_axis)); - yd = gimp_vector2_inner_product (&delta, - &(paint_core->brush->y_axis)) / (mag*mag); - - dist = 0.5 * sqrt (xd*xd + yd*yd); - total = dist + paint_core->distance; - initial = paint_core->distance; - - pixel_dist = gimp_vector2_length (&delta); - pixel_initial = paint_core->pixel_dist; - - /* FIXME: need to adapt the spacing to the size */ - /* lastscale = MIN (paint_core->lastpressure, 1/256); */ - /* curscale = MIN (paint_core->curpressure, 1/256); */ - /* spacing = paint_core->spacing * sqrt (0.5 * (lastscale + curscale)); */ - - while (paint_core->distance < total) - { - n = (gint) (paint_core->distance / paint_core->spacing + 1.0 + EPSILON); - left = n * paint_core->spacing - paint_core->distance; - - paint_core->distance += left; - - if (paint_core->distance <= (total+EPSILON)) - { - t = (paint_core->distance - initial) / dist; - - paint_core->curx = paint_core->lastx + delta.x * t; - paint_core->cury = paint_core->lasty + delta.y * t; - paint_core->pixel_dist = pixel_initial + pixel_dist * t; - paint_core->curpressure = paint_core->lastpressure + dpressure * t; - paint_core->curxtilt = paint_core->lastxtilt + dxtilt * t; - paint_core->curytilt = paint_core->lastytilt + dytilt * t; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = paint_core->lastwheel + dwheel * t; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - /* save the current brush */ - current_brush = paint_core->brush; - - if (paint_core->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) - paint_core->brush = - (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_core->brush) - ->klass)->select_brush) (paint_core); - (* paint_core->paint_func) (paint_core, drawable, MOTION_PAINT); - - /* restore the current brush pointer */ - paint_core->brush = current_brush; - } - } - - paint_core->distance = total; - paint_core->pixel_dist = pixel_initial + pixel_dist; - paint_core->curx = paint_core->lastx + delta.x; - paint_core->cury = paint_core->lasty + delta.y; - paint_core->curpressure = paint_core->lastpressure + dpressure; - paint_core->curxtilt = paint_core->lastxtilt + dxtilt; - paint_core->curytilt = paint_core->lastytilt + dytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = paint_core->lastwheel + dwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ -} - -void -paint_core_finish (PaintCore *paint_core, - GimpDrawable *drawable, - gint tool_ID) -{ - GImage *gimage; - PaintUndo *pu; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - /* Determine if any part of the image has been altered-- - * if nothing has, then just return... - */ - - if ((paint_core->x2 == paint_core->x1) || - (paint_core->y2 == paint_core->y1)) - return; - - undo_push_group_start (gimage, PAINT_CORE_UNDO); - - pu = g_new (PaintUndo, 1); - pu->tool_ID = tool_ID; - pu->lastx = paint_core->startx; - pu->lasty = paint_core->starty; - pu->lastpressure = paint_core->startpressure; - pu->lastxtilt = paint_core->startxtilt; - pu->lastytilt = paint_core->startytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - pu->lastwheel = paint_core->startwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - /* Push a paint undo */ - undo_push_paint (gimage, pu); - - /* push an undo */ - drawable_apply_image (drawable, paint_core->x1, paint_core->y1, - paint_core->x2, paint_core->y2, undo_tiles, TRUE); - undo_tiles = NULL; - - /* push the group end */ - undo_push_group_end (gimage); - - /* invalidate the drawable--have to do it here, because - * it is not done during the actual painting. - */ - gimp_drawable_invalidate_preview (drawable, TRUE); -} - -void -paint_core_cleanup (void) -{ - /* CLEANUP */ - /* If the undo tiles exist, nuke them */ - if (undo_tiles) - { - tile_manager_destroy (undo_tiles); - undo_tiles = NULL; - } - - /* If the canvas blocks exist, nuke them */ - if (canvas_tiles) - { - tile_manager_destroy (canvas_tiles); - canvas_tiles = NULL; - } - - /* Free the temporary buffers if they exist */ - free_paint_buffers (); -} - -void -paint_core_get_color_from_gradient (PaintCore *paint_core, - gdouble gradient_length, - GimpRGB *color, - GradientPaintMode mode) -{ - gdouble y; - gdouble distance; /* distance in current brush stroke */ - - distance = paint_core->pixel_dist; - y = ((double) distance / gradient_length); - - /* for the once modes, set y close to 1.0 after the first chunk */ - if ( (mode == ONCE_FORWARD || mode == ONCE_BACKWARDS) && y >= 1.0 ) - y = 0.9999999; - - if ( (((int)y & 1) && mode != LOOP_SAWTOOTH) || mode == ONCE_BACKWARDS ) - y = 1.0 - (y - (int)y); - else - y = y - (int)y; - - gradient_get_color_at (gimp_context_get_gradient (NULL), y, color); -} - - -/************************/ -/* Painting functions */ -/************************/ - -TempBuf * -paint_core_get_paint_area (PaintCore *paint_core, - GimpDrawable *drawable, - gdouble scale) -{ - gint x, y; - gint x1, y1, x2, y2; - gint bytes; - gint dwidth, dheight; - gint bwidth, bheight; - - bytes = gimp_drawable_has_alpha (drawable) ? - gimp_drawable_bytes (drawable) : gimp_drawable_bytes (drawable) + 1; - - paint_core_calculate_brush_size (paint_core->brush->mask, scale, - &bwidth, &bheight); - - /* adjust the x and y coordinates to the upper left corner of the brush */ - x = (gint) floor (paint_core->curx) - (bwidth >> 1); - y = (gint) floor (paint_core->cury) - (bheight >> 1); - - dwidth = gimp_drawable_width (drawable); - dheight = gimp_drawable_height (drawable); - - x1 = CLAMP (x - 1, 0, dwidth); - y1 = CLAMP (y - 1, 0, dheight); - x2 = CLAMP (x + bwidth + 1, 0, dwidth); - y2 = CLAMP (y + bheight + 1, 0, dheight); - - /* configure the canvas buffer */ - if ((x2 - x1) && (y2 - y1)) - canvas_buf = temp_buf_resize (canvas_buf, bytes, x1, y1, - (x2 - x1), (y2 - y1)); - else - return NULL; - - return canvas_buf; -} - -TempBuf * -paint_core_get_orig_image (PaintCore *paint_core, - GimpDrawable *drawable, - gint x1, - gint y1, - gint x2, - gint y2) -{ - PixelRegion srcPR; - PixelRegion destPR; - Tile *undo_tile; - gint h; - gint refd; - gint pixelwidth; - gint dwidth; - gint dheight; - guchar *s; - guchar *d; - gpointer pr; - - orig_buf = temp_buf_resize (orig_buf, gimp_drawable_bytes (drawable), - x1, y1, (x2 - x1), (y2 - y1)); - - dwidth = gimp_drawable_width (drawable); - dheight = gimp_drawable_height (drawable); - - x1 = CLAMP (x1, 0, dwidth); - y1 = CLAMP (y1, 0, dheight); - x2 = CLAMP (x2, 0, dwidth); - y2 = CLAMP (y2, 0, dheight); - - /* configure the pixel regions */ - pixel_region_init (&srcPR, gimp_drawable_data (drawable), x1, y1, - (x2 - x1), (y2 - y1), FALSE); - destPR.bytes = orig_buf->bytes; - destPR.x = 0; destPR.y = 0; - destPR.w = (x2 - x1); destPR.h = (y2 - y1); - destPR.rowstride = orig_buf->bytes * orig_buf->width; - destPR.data = temp_buf_data (orig_buf) + - (y1 - orig_buf->y) * destPR.rowstride + (x1 - orig_buf->x) * destPR.bytes; - - for (pr = pixel_regions_register (2, &srcPR, &destPR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - /* If the undo tile corresponding to this location is valid, use it */ - undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y, - FALSE, FALSE); - if (tile_is_valid (undo_tile) == TRUE) - { - refd = 1; - undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y, - TRUE, FALSE); - s = (unsigned char*)tile_data_pointer (undo_tile, 0, 0) + - srcPR.rowstride * (srcPR.y % TILE_HEIGHT) + - srcPR.bytes * (srcPR.x % TILE_WIDTH); /* dubious... */ - } - else - { - refd = 0; - s = srcPR.data; - } - - d = destPR.data; - pixelwidth = srcPR.w * srcPR.bytes; - h = srcPR.h; - while (h --) - { - memcpy (d, s, pixelwidth); - s += srcPR.rowstride; - d += destPR.rowstride; - } - - if (refd) - tile_release (undo_tile, FALSE); - } - - return orig_buf; -} - -void -paint_core_paste_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - LayerModeEffects paint_mode, - BrushApplicationMode brush_hardness, - gdouble brush_scale, - PaintApplicationMode mode) -{ - MaskBuf *brush_mask; - - /* get the brush mask */ - brush_mask = paint_core_get_brush_mask (paint_core, - brush_hardness, brush_scale); - - /* paste the canvas buf */ - paint_core_paste (paint_core, brush_mask, drawable, - brush_opacity, image_opacity, paint_mode, mode); -} - -/* Similar to paint_core_paste_canvas, but replaces the alpha channel - rather than using it to composite (i.e. transparent over opaque - becomes transparent rather than opauqe. */ -void -paint_core_replace_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - BrushApplicationMode brush_hardness, - gdouble brush_scale, - PaintApplicationMode mode) -{ - MaskBuf *brush_mask; - - /* get the brush mask */ - brush_mask = - paint_core_get_brush_mask (paint_core, brush_hardness, brush_scale); - - /* paste the canvas buf */ - paint_core_replace (paint_core, brush_mask, drawable, - brush_opacity, image_opacity, mode); -} - - -static void -paint_core_invalidate_cache (GimpBrush *brush, - gpointer data) -{ - /* Make sure we don't cache data for a brush that has changed */ - if (last_brush_mask == brush->mask) - cache_invalid = TRUE; -} - -/************************************************************ - * LOCAL FUNCTION DEFINITIONS * - ************************************************************/ - -static void -paint_core_calculate_brush_size (MaskBuf *mask, - gdouble scale, - gint *width, - gint *height) -{ - scale = CLAMP (scale, 0.0, 1.0); - - if (current_device == GDK_CORE_POINTER) - { - *width = mask->width; - *height = mask->height; - } - else - { - gdouble ratio; - - if (scale < 1 / 256) - ratio = 1 / 16; - else - ratio = sqrt (scale); - - *width = MAX ((gint) (mask->width * ratio + 0.5), 1); - *height = MAX ((gint) (mask->height * ratio + 0.5), 1); - } -} - -static MaskBuf * -paint_core_subsample_mask (MaskBuf *mask, - gdouble x, - gdouble y) -{ - MaskBuf *dest; - gdouble left; - guchar *m; - guchar *d; - const gint *k; - gint index1; - gint index2; - const gint *kernel; - gint new_val; - gint i, j; - gint r, s; - - x += (x < 0) ? mask->width : 0; - left = x - floor (x); - index1 = (gint) (left * (gdouble) (SUBSAMPLE + 1)); - - y += (y < 0) ? mask->height : 0; - left = y - floor (y); - index2 = (gint) (left * (gdouble) (SUBSAMPLE + 1)); - - kernel = subsample[index2][index1]; - - if (mask == last_brush_mask && !cache_invalid) - { - if (kernel_brushes[index2][index1]) - return kernel_brushes[index2][index1]; - } - else - { - for (i = 0; i <= SUBSAMPLE; i++) - for (j = 0; j <= SUBSAMPLE; j++) - { - if (kernel_brushes[i][j]) - mask_buf_free (kernel_brushes[i][j]); - - kernel_brushes[i][j] = NULL; - } - - last_brush_mask = mask; - cache_invalid = FALSE; - } - - dest = kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, - mask->height + 2); - - m = mask_buf_data (mask); - for (i = 0; i < mask->height; i++) - { - for (j = 0; j < mask->width; j++) - { - k = kernel; - for (r = 0; r < KERNEL_HEIGHT; r++) - { - d = mask_buf_data (dest) + (i+r) * dest->width + j; - s = KERNEL_WIDTH; - while (s--) - { - new_val = *d + ((*m * *k++ + 128) >> 8); - *d++ = MIN (new_val, 255); - } - } - m++; - } - } - - return dest; -} - -/* #define FANCY_PRESSURE */ - -static MaskBuf * -paint_core_pressurize_mask (MaskBuf *brush_mask, - gdouble x, - gdouble y, - gdouble pressure) -{ - static MaskBuf *last_brush = NULL; - static guchar mapi[256]; - guchar *source; - guchar *dest; - MaskBuf *subsample_mask; - gint i; -#ifdef FANCY_PRESSURE - static gdouble map[256]; - gdouble ds, s, c; -#endif - - /* Get the raw subsampled mask */ - subsample_mask = paint_core_subsample_mask (brush_mask, x, y); - - /* Special case pressure = 0.5 */ - if ((int)(pressure * 100 + 0.5) == 50) - return subsample_mask; - - /* Make sure we have the right sized buffer */ - if (brush_mask != last_brush) - { - if (pressure_brush) - mask_buf_free (pressure_brush); - - pressure_brush = mask_buf_new (brush_mask->width + 2, - brush_mask->height + 2); - } - -#ifdef FANCY_PRESSURE - /* Create the pressure profile - - It is: I'(I) = tanh(20*(pressure-0.5)*I) : pressure > 0.5 - I'(I) = 1 - tanh(20*(0.5-pressure)*(1-I)) : pressure < 0.5 - - It looks like: - - low pressure medium pressure high pressure - - | / -- - | / / - / / | - -- / | - - */ - - ds = (pressure - 0.5)*(20./256.); - s = 0; - c = 1.0; - - if (ds > 0) - { - for (i=0;i<256;i++) - { - map[i] = s/c; - s += c*ds; - c += s*ds; - } - for (i=0;i<256;i++) - mapi[i] = (int)(255*map[i]/map[255]); - } - else - { - ds = -ds; - for (i=255;i>=0;i--) - { - map[i] = s/c; - s += c*ds; - c += s*ds; - } - for (i=0;i<256;i++) - mapi[i] = (int)(255*(1-map[i]/map[0])); - } -#else /* ! FANCY_PRESSURE */ - - for (i = 0; i < 256; i++) - { - gint tmp = (pressure / 0.5) * i; - - if (tmp > 255) - mapi[i] = 255; - else - mapi[i] = tmp; - } - -#endif /* FANCY_PRESSURE */ - - /* Now convert the brush */ - - source = mask_buf_data (subsample_mask); - dest = mask_buf_data (pressure_brush); - - i = subsample_mask->width * subsample_mask->height; - while (i--) - { - *dest++ = mapi[(*source++)]; - } - - return pressure_brush; -} - -static MaskBuf * -paint_core_solidify_mask (MaskBuf *brush_mask) -{ - static MaskBuf *last_brush = NULL; - gint i; - gint j; - guchar *data; - guchar *src; - - if (brush_mask == last_brush && !cache_invalid) - return solid_brush; - - last_brush = brush_mask; - - if (solid_brush) - mask_buf_free (solid_brush); - - solid_brush = mask_buf_new (brush_mask->width + 2, brush_mask->height + 2); - - /* get the data and advance one line into it */ - data = mask_buf_data (solid_brush) + solid_brush->width; - src = mask_buf_data (brush_mask); - - for (i = 0; i < brush_mask->height; i++) - { - data++; - for (j = 0; j < brush_mask->width; j++) - { - *data++ = (*src++) ? OPAQUE_OPACITY : TRANSPARENT_OPACITY; - } - data++; - } - - return solid_brush; -} - -static MaskBuf * -paint_core_scale_mask (MaskBuf *brush_mask, - gdouble scale) -{ - static MaskBuf *last_brush = NULL; - static gint last_width = 0.0; - static gint last_height = 0.0; - gint dest_width; - gint dest_height; - - scale = CLAMP (scale, 0.0, 1.0); - - if (scale == 0.0) - return NULL; - - if (scale == 1.0) - return brush_mask; - - paint_core_calculate_brush_size (brush_mask, scale, - &dest_width, &dest_height); - - if (brush_mask == last_brush && !cache_invalid && - dest_width == last_width && dest_height == last_height) - return scale_brush; - - if (scale_brush) - mask_buf_free (scale_brush); - - last_brush = brush_mask; - last_width = dest_width; - last_height = dest_height; - - scale_brush = brush_scale_mask (brush_mask, dest_width, dest_height); - cache_invalid = TRUE; - - return scale_brush; -} - -static MaskBuf * -paint_core_scale_pixmap (MaskBuf *brush_mask, - gdouble scale) -{ - static MaskBuf *last_brush = NULL; - static gint last_width = 0.0; - static gint last_height = 0.0; - gint dest_width; - gint dest_height; - - scale = CLAMP (scale, 0.0, 1.0); - - if (scale == 0.0) - return NULL; - - if (scale == 1.0) - return brush_mask; - - paint_core_calculate_brush_size (brush_mask, scale, - &dest_width, &dest_height); - - if (brush_mask == last_brush && !cache_invalid && - dest_width == last_width && dest_height == last_height) - return scale_pixmap; - - if (scale_pixmap) - mask_buf_free (scale_pixmap); - - last_brush = brush_mask; - last_width = dest_width; - last_height = dest_height; - - scale_pixmap = brush_scale_pixmap (brush_mask, dest_width, dest_height); - cache_invalid = TRUE; - - return scale_pixmap; -} - -static MaskBuf * -paint_core_get_brush_mask (PaintCore *paint_core, - BrushApplicationMode brush_hardness, - gdouble scale) -{ - MaskBuf *mask; - - if (current_device == GDK_CORE_POINTER) - mask = paint_core->brush->mask; - else - mask = paint_core_scale_mask (paint_core->brush->mask, scale); - - switch (brush_hardness) - { - case SOFT: - mask = paint_core_subsample_mask (mask, - paint_core->curx, paint_core->cury); - break; - case HARD: - mask = paint_core_solidify_mask (mask); - break; - case PRESSURE: - mask = paint_core_pressurize_mask (mask, - paint_core->curx, paint_core->cury, - paint_core->curpressure); - break; - default: - break; - } - - return mask; -} - -static void -paint_core_paste (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - LayerModeEffects paint_mode, - PaintApplicationMode mode) -{ - GimpImage *gimage; - PixelRegion srcPR; - TileManager *alt = NULL; - gint offx; - gint offy; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - /* set undo blocks */ - set_undo_tiles (drawable, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - /* If the mode is CONSTANT: - * combine the canvas buf, the brush mask to the canvas tiles - */ - if (mode == CONSTANT) - { - /* initialize any invalid canvas tiles */ - set_canvas_tiles (canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - brush_to_canvas_tiles (paint_core, brush_mask, brush_opacity); - canvas_tiles_to_canvas_buf (paint_core); - alt = undo_tiles; - } - /* Otherwise: - * combine the canvas buf and the brush mask to the canvas buf - */ - else - { - brush_to_canvas_buf (paint_core, brush_mask, brush_opacity); - } - - /* intialize canvas buf source pixel regions */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - /* apply the paint area to the gimage */ - gimp_image_apply_image (gimage, drawable, &srcPR, - FALSE, image_opacity, paint_mode, - alt, /* specify an alternative src1 */ - canvas_buf->x, canvas_buf->y); - - /* Update the undo extents */ - paint_core->x1 = MIN (paint_core->x1, canvas_buf->x); - paint_core->y1 = MIN (paint_core->y1, canvas_buf->y); - paint_core->x2 = MAX (paint_core->x2, (canvas_buf->x + canvas_buf->width)); - paint_core->y2 = MAX (paint_core->y2, (canvas_buf->y + canvas_buf->height)); - - /* Update the gimage--it is important to call gdisplays_update_area - * instead of drawable_update because we don't want the drawable - * preview to be constantly invalidated - */ - gimp_drawable_offsets (drawable, &offx, &offy); - gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, - canvas_buf->width, canvas_buf->height); -} - -/* This works similarly to paint_core_paste. However, instead of combining - the canvas to the paint core drawable using one of the combination - modes, it uses a "replace" mode (i.e. transparent pixels in the - canvas erase the paint core drawable). - - When not drawing on alpha-enabled images, it just paints using NORMAL - mode. -*/ -static void -paint_core_replace (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - PaintApplicationMode mode) -{ - GimpImage *gimage; - PixelRegion srcPR; - PixelRegion maskPR; - TileManager *alt = NULL; - gint offx; - gint offy; - - if (! gimp_drawable_has_alpha (drawable)) - { - paint_core_paste (paint_core, brush_mask, drawable, - brush_opacity, image_opacity, NORMAL_MODE, - mode); - return; - } - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - /* set undo blocks */ - set_undo_tiles (drawable, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - if (mode == CONSTANT) - { - /* initialize any invalid canvas tiles */ - set_canvas_tiles (canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - /* combine the brush mask and the canvas tiles */ - brush_to_canvas_tiles (paint_core, brush_mask, brush_opacity); - - /* set the alt source as the unaltered undo_tiles */ - alt = undo_tiles; - - /* initialize the maskPR from the canvas tiles */ - pixel_region_init (&maskPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, FALSE); - } - else - { - /* The mask is just the brush mask */ - maskPR.bytes = 1; - maskPR.x = 0; - maskPR.y = 0; - maskPR.w = canvas_buf->width; - maskPR.h = canvas_buf->height; - maskPR.rowstride = maskPR.bytes * brush_mask->width; - maskPR.data = mask_buf_data (brush_mask); - } - - /* intialize canvas buf source pixel regions */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - /* apply the paint area to the gimage */ - gimp_image_replace_image (gimage, drawable, &srcPR, - FALSE, image_opacity, - &maskPR, - canvas_buf->x, canvas_buf->y); - - /* Update the undo extents */ - paint_core->x1 = MIN (paint_core->x1, canvas_buf->x); - paint_core->y1 = MIN (paint_core->y1, canvas_buf->y); - paint_core->x2 = MAX (paint_core->x2, (canvas_buf->x + canvas_buf->width)); - paint_core->y2 = MAX (paint_core->y2, (canvas_buf->y + canvas_buf->height)); - - /* Update the gimage--it is important to call gdisplays_update_area - * instead of drawable_update because we don't want the drawable - * preview to be constantly invalidated - */ - gimp_drawable_offsets (drawable, &offx, &offy); - gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, - canvas_buf->width, canvas_buf->height); -} - -static void -canvas_tiles_to_canvas_buf (PaintCore *paint_core) -{ - PixelRegion srcPR; - PixelRegion maskPR; - - /* combine the canvas tiles and the canvas buf */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - pixel_region_init (&maskPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, FALSE); - - /* apply the canvas tiles to the canvas buf */ - apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); -} - -static void -brush_to_canvas_tiles (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity) -{ - PixelRegion srcPR; - PixelRegion maskPR; - gint x; - gint y; - gint xoff; - gint yoff; - - /* combine the brush mask and the canvas tiles */ - pixel_region_init (&srcPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, TRUE); - - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); - xoff = (x < 0) ? -x : 0; - yoff = (y < 0) ? -y : 0; - - maskPR.bytes = 1; - maskPR.x = 0; - maskPR.y = 0; - maskPR.w = srcPR.w; - maskPR.h = srcPR.h; - maskPR.rowstride = maskPR.bytes * brush_mask->width; - maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; - - /* combine the mask to the canvas tiles */ - combine_mask_and_region (&srcPR, &maskPR, brush_opacity); -} - -static void -brush_to_canvas_buf (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity) -{ - PixelRegion srcPR; - PixelRegion maskPR; - gint x; - gint y; - gint xoff; - gint yoff; - - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); - xoff = (x < 0) ? -x : 0; - yoff = (y < 0) ? -y : 0; - - /* combine the canvas buf and the brush mask to the canvas buf */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - maskPR.bytes = 1; - maskPR.x = 0; - maskPR.y = 0; - maskPR.w = srcPR.w; - maskPR.h = srcPR.h; - maskPR.rowstride = maskPR.bytes * brush_mask->width; - maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; - - /* apply the mask */ - apply_mask_to_region (&srcPR, &maskPR, brush_opacity); -} - -#if 0 -static void -paint_to_canvas_tiles (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity) -{ - PixelRegion srcPR; - PixelRegion maskPR; - gint x; - gint y; - gint xoff; - gint yoff; - - /* combine the brush mask and the canvas tiles */ - pixel_region_init (&srcPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, TRUE); - - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); - xoff = (x < 0) ? -x : 0; - yoff = (y < 0) ? -y : 0; - - maskPR.bytes = 1; - maskPR.x = 0; - maskPR.y = 0; - maskPR.w = srcPR.w; - maskPR.h = srcPR.h; - maskPR.rowstride = maskPR.bytes * brush_mask->width; - maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; - - /* combine the mask and canvas tiles */ - combine_mask_and_region (&srcPR, &maskPR, brush_opacity); - - /* combine the canvas tiles and the canvas buf */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - pixel_region_init (&maskPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, FALSE); - - /* apply the canvas tiles to the canvas buf */ - apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); -} - -static void -paint_to_canvas_buf (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity) -{ - PixelRegion srcPR; - PixelRegion maskPR; - gint x; - gint y; - gint xoff; - gint yoff; - - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); - xoff = (x < 0) ? -x : 0; - yoff = (y < 0) ? -y : 0; - - - /* combine the canvas buf and the brush mask to the canvas buf */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - maskPR.bytes = 1; - maskPR.x = 0; - maskPR.y = 0; - maskPR.w = srcPR.w; - maskPR.h = srcPR.h; - maskPR.rowstride = maskPR.bytes * brush_mask->width; - maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; - - /* apply the mask */ - apply_mask_to_region (&srcPR, &maskPR, brush_opacity); -} -#endif - -static void -set_undo_tiles (GimpDrawable *drawable, - gint x, - gint y, - gint w, - gint h) -{ - gint i; - gint j; - Tile *src_tile; - Tile *dest_tile; - - if (undo_tiles == NULL) - { - g_warning ("set_undo_tiles: undo_tiles is null"); - return; - } - - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - { - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - dest_tile = tile_manager_get_tile (undo_tiles, j, i, FALSE, FALSE); - if (tile_is_valid (dest_tile) == FALSE) - { - src_tile = tile_manager_get_tile (gimp_drawable_data (drawable), - j, i, TRUE, FALSE); - tile_manager_map_tile (undo_tiles, j, i, src_tile); - tile_release (src_tile, FALSE); - } - } - } -} - -static void -set_canvas_tiles (gint x, - gint y, - gint w, - gint h) -{ - gint i; - gint j; - Tile *tile; - - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - { - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (canvas_tiles, j, i, FALSE, FALSE); - if (tile_is_valid (tile) == FALSE) - { - tile = tile_manager_get_tile (canvas_tiles, j, i, TRUE, TRUE); - memset (tile_data_pointer (tile, 0, 0), 0, tile_size (tile)); - tile_release (tile, TRUE); - } - } - } -} - - -/*****************************************************/ -/* Paint buffers utility functions */ -/*****************************************************/ - - -static void -free_paint_buffers (void) -{ - if (orig_buf) - temp_buf_free (orig_buf); - orig_buf = NULL; - - if (canvas_buf) - temp_buf_free (canvas_buf); - canvas_buf = NULL; -} - - -/**************************************************/ -/* Brush pipe utility functions */ -/**************************************************/ - -void -paint_core_color_area_with_pixmap (PaintCore *paint_core, - GimpImage *dest, - GimpDrawable *drawable, - TempBuf *area, - gdouble scale, - BrushApplicationMode mode) -{ - PixelRegion destPR; - void *pr; - guchar *d; - gint ulx; - gint uly; - gint offsetx; - gint offsety; - gint y; - TempBuf *pixmap_mask; - TempBuf *brush_mask; - - g_return_if_fail (GIMP_IS_BRUSH (paint_core->brush)); - g_return_if_fail (paint_core->brush->pixmap != NULL); - - /* scale the brushes */ - pixmap_mask = paint_core_scale_pixmap (paint_core->brush->pixmap, scale); - - if (mode == SOFT) - brush_mask = paint_core_scale_mask (paint_core->brush->mask, scale); - else - brush_mask = NULL; - - destPR.bytes = area->bytes; - destPR.x = 0; - destPR.y = 0; - destPR.w = area->width; - destPR.h = area->height; - destPR.rowstride = destPR.bytes * area->width; - destPR.data = temp_buf_data (area); - - pr = pixel_regions_register (1, &destPR); - - /* Calculate upper left corner of brush as in - * paint_core_get_paint_area. Ugly to have to do this here, too. - */ - - ulx = (gint) floor (paint_core->curx) - (pixmap_mask->width >> 1); - uly = (gint) floor (paint_core->cury) - (pixmap_mask->height >> 1); - - offsetx = area->x - ulx; - offsety = area->y - uly; - - for (; pr != NULL; pr = pixel_regions_process (pr)) - { - d = destPR.data; - for (y = 0; y < destPR.h; y++) - { - paint_line_pixmap_mask (dest, drawable, pixmap_mask, brush_mask, - d, offsetx, y + offsety, - destPR.bytes, destPR.w, mode); - d += destPR.rowstride; - } - } -} - -static void -paint_line_pixmap_mask (GimpImage *dest, - GimpDrawable *drawable, - TempBuf *pixmap_mask, - TempBuf *brush_mask, - guchar *d, - gint x, - gint y, - gint bytes, - gint width, - BrushApplicationMode mode) -{ - guchar *b; - guchar *p; - guchar *mask; - gdouble alpha; - gdouble factor = 0.00392156986; /* 1.0 / 255.0 */ - gint x_index; - gint i,byte_loop; - - /* Make sure x, y are positive */ - while (x < 0) - x += pixmap_mask->width; - while (y < 0) - y += pixmap_mask->height; - - /* Point to the approriate scanline */ - b = temp_buf_data (pixmap_mask) + - (y % pixmap_mask->height) * pixmap_mask->width * pixmap_mask->bytes; - - if (mode == SOFT && brush_mask) - { - /* ditto, except for the brush mask, so we can pre-multiply the alpha value */ - mask = temp_buf_data (brush_mask) + - (y % brush_mask->height) * brush_mask->width; - for (i = 0; i < width; i++) - { - /* attempt to avoid doing this calc twice in the loop */ - x_index = ((i + x) % pixmap_mask->width); - p = b + x_index * pixmap_mask->bytes; - d[bytes-1] = mask[x_index]; - - /* multiply alpha into the pixmap data */ - /* maybe we could do this at tool creation or brush switch time? */ - /* and compute it for the whole brush at once and cache it? */ - alpha = d[bytes-1] * factor; - if(alpha) - for (byte_loop = 0; byte_loop < bytes - 1; byte_loop++) - d[byte_loop] *= alpha; - - /* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */ - gimp_image_transform_color (dest, drawable, p, d, RGB); - d += bytes; - } - } - else - { - for (i = 0; i < width; i++) - { - /* attempt to avoid doing this calc twice in the loop */ - x_index = ((i + x) % pixmap_mask->width); - p = b + x_index * pixmap_mask->bytes; - d[bytes-1] = 255; - - /* multiply alpha into the pixmap data */ - /* maybe we could do this at tool creation or brush switch time? */ - /* and compute it for the whole brush at once and cache it? */ - gimp_image_transform_color (dest, drawable, p, d, RGB); - d += bytes; - } - } -} diff --git a/app/paint_core.h b/app/paint_core.h deleted file mode 100644 index e7dd38e62b..0000000000 --- a/app/paint_core.h +++ /dev/null @@ -1,194 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PAINT_CORE_H__ -#define __PAINT_CORE_H__ - - -/* the different states that the painting function can be called with */ - -typedef enum /*< skip >*/ -{ - INIT_PAINT, /* Setup PaintFunc internals */ - MOTION_PAINT, /* PaintFunc performs motion-related rendering */ - PAUSE_PAINT, /* Unused. Reserved */ - RESUME_PAINT, /* Unused. Reserved */ - FINISH_PAINT, /* Cleanup and/or reset PaintFunc operation */ - PRETRACE_PAINT, /* PaintFunc performs window tracing activity prior to rendering */ - POSTTRACE_PAINT /* PaintFunc performs window tracing activity following rendering */ -} PaintState; - -typedef enum /*< skip >*/ -{ - TOOL_CAN_HANDLE_CHANGING_BRUSH = 0x0001, /* Set for tools that don't mind - * if the brush changes while - * painting. - */ - - TOOL_TRACES_ON_WINDOW /* Set for tools that perform temporary - * rendering directly to the window. These - * require sequencing with gdisplay_flush() - * routines. See clone.c for example. - */ -} ToolFlags; - -typedef gpointer (* PaintFunc) (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState paint_state); - -struct _PaintCore -{ - DrawCore * core; /* Core select object */ - - gdouble startx; /* starting x coord */ - gdouble starty; /* starting y coord */ - gdouble startpressure; /* starting pressure */ - gdouble startxtilt; /* starting xtilt */ - gdouble startytilt; /* starting ytilt */ -#ifdef GTK_HAVE_SIX_VALUATORS - gdouble startwheel; /* starting wheel */ -#endif /* GTK_HAVE_SIX_VALUATORS */ - - gdouble curx; /* current x coord */ - gdouble cury; /* current y coord */ - gdouble curpressure; /* current pressure */ - gdouble curxtilt; /* current xtilt */ - gdouble curytilt; /* current ytilt */ -#ifdef GTK_HAVE_SIX_VALUATORS - gdouble curwheel; /* current wheel */ -#endif /* GTK_HAVE_SIX_VALUATORS */ - - gdouble lastx; /* last x coord */ - gdouble lasty; /* last y coord */ - gdouble lastpressure; /* last pressure */ - gdouble lastxtilt; /* last xtilt */ - gdouble lastytilt; /* last ytilt */ -#ifdef GTK_HAVE_SIX_VALUATORS - gdouble lastwheel; /* last wheel */ -#endif /* GTK_HAVE_SIX_VALUATORS */ - - gint state; /* state of buttons and keys */ - - gdouble distance; /* distance traveled by brush */ - gdouble pixel_dist; /* distance in pixels */ - gdouble spacing; /* spacing */ - - gint x1, y1; /* image space coordinate */ - gint x2, y2; /* image space coords */ - - GimpBrush * brush; /* current brush */ - - PaintFunc paint_func; /* painting function */ - - gboolean pick_colors; /* pick color if ctrl or alt is pressed */ - gboolean pick_state; /* was ctrl or alt pressed when clicked? */ - ToolFlags flags; /* tool flags, see ToolFlags above */ - - guint context_id; /* for the statusbar */ -}; - -extern PaintCore non_gui_paint_core; - -/* Special undo type */ -typedef struct _PaintUndo PaintUndo; - -struct _PaintUndo -{ - gint tool_ID; - gdouble lastx; - gdouble lasty; - gdouble lastpressure; - gdouble lastxtilt; - gdouble lastytilt; -#ifdef GTK_HAVE_SIX_VALUATORS - gdouble lastwheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ -}; - -/* paint tool action functions */ -void paint_core_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -void paint_core_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -void paint_core_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -void paint_core_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); - -void paint_core_control (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -/* paint tool functions */ -void paint_core_no_draw (Tool *tool); -Tool * paint_core_new (ToolType type); -void paint_core_free (Tool *tool); -int paint_core_init (PaintCore *paint_core, - GimpDrawable *drawable, - gdouble x, - gdouble y); -void paint_core_interpolate (PaintCore *paint_core, - GimpDrawable *drawable); -void paint_core_finish (PaintCore *paint_core, - GimpDrawable *drawable, - gint tool_ID); -void paint_core_cleanup (void); - -void paint_core_get_color_from_gradient (PaintCore *paint_core, - gdouble gradient_length, - GimpRGB *color, - GradientPaintMode mode); - -/* paint tool painting functions */ -TempBuf * paint_core_get_paint_area (PaintCore *paint_core, - GimpDrawable *drawable, - gdouble scale); -TempBuf * paint_core_get_orig_image (PaintCore *paint_core, - GimpDrawable *drawable, - gint x1, - gint y1, - gint x2, - gint y2); -void paint_core_paste_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - LayerModeEffects paint_mode, - BrushApplicationMode brush_hardness, - gdouble brush_scale, - PaintApplicationMode mode); -void paint_core_replace_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - BrushApplicationMode brush_hardness, - gdouble brush_scale, - PaintApplicationMode mode); -void paint_core_color_area_with_pixmap (PaintCore *paint_core, - GimpImage *dest, - GimpDrawable *drawable, - TempBuf *area, - gdouble scale, - BrushApplicationMode mode); - - -#endif /* __PAINT_CORE_H__ */ diff --git a/app/paint_core_kernels.h b/app/paint_core_kernels.h deleted file mode 100644 index 8cb65d32eb..0000000000 --- a/app/paint_core_kernels.h +++ /dev/null @@ -1,49 +0,0 @@ -/* paint_core_kernels.h - * - * This file was generated using kernelgen as found in the tools dir. - * (threshold = 0.25) - */ - -#define KERNEL_WIDTH 3 -#define KERNEL_HEIGHT 3 -#define SUBSAMPLE 4 - - -/* Brush pixel subsampling kernels */ -static const int subsample[5][5][9] = { - { - { 64, 64, 0, 64, 64, 0, 0, 0, 0, }, - { 25, 102, 0, 25, 102, 0, 0, 0, 0, }, - { 0, 128, 0, 0, 128, 0, 0, 0, 0, }, - { 0, 102, 25, 0, 102, 25, 0, 0, 0, }, - { 0, 64, 64, 0, 64, 64, 0, 0, 0, } - }, - { - { 25, 25, 0, 102, 102, 0, 0, 0, 0, }, - { 6, 43, 0, 43, 162, 0, 0, 0, 0, }, - { 0, 50, 0, 0, 205, 0, 0, 0, 0, }, - { 0, 43, 6, 0, 162, 43, 0, 0, 0, }, - { 0, 25, 25, 0, 102, 102, 0, 0, 0, } - }, - { - { 0, 0, 0, 128, 128, 0, 0, 0, 0, }, - { 0, 0, 0, 50, 205, 0, 0, 0, 0, }, - { 0, 0, 0, 0, 256, 0, 0, 0, 0, }, - { 0, 0, 0, 0, 205, 50, 0, 0, 0, }, - { 0, 0, 0, 0, 128, 128, 0, 0, 0, } - }, - { - { 0, 0, 0, 102, 102, 0, 25, 25, 0, }, - { 0, 0, 0, 43, 162, 0, 6, 43, 0, }, - { 0, 0, 0, 0, 205, 0, 0, 50, 0, }, - { 0, 0, 0, 0, 162, 43, 0, 43, 6, }, - { 0, 0, 0, 0, 102, 102, 0, 25, 25, } - }, - { - { 0, 0, 0, 64, 64, 0, 64, 64, 0, }, - { 0, 0, 0, 25, 102, 0, 25, 102, 0, }, - { 0, 0, 0, 0, 128, 0, 0, 128, 0, }, - { 0, 0, 0, 0, 102, 25, 0, 102, 25, }, - { 0, 0, 0, 0, 64, 64, 0, 64, 64, } - } -}; diff --git a/app/paint_options.h b/app/paint_options.h deleted file mode 100644 index 5c99bf1b76..0000000000 --- a/app/paint_options.h +++ /dev/null @@ -1,108 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef __PAINT_OPTIONS_H__ -#define __PAINT_OPTIONS_H__ - -#include "tools.h" -#include "tool_options.h" - -/* the paint options structures */ -typedef struct _PaintPressureOptions PaintPressureOptions; -struct _PaintPressureOptions -{ - GtkWidget *frame; - - gboolean opacity; - gboolean opacity_d; - GtkWidget *opacity_w; - - gboolean pressure; - gboolean pressure_d; - GtkWidget *pressure_w; - - gboolean rate; - gboolean rate_d; - GtkWidget *rate_w; - - gboolean size; - gboolean size_d; - GtkWidget *size_w; - - gboolean color; - gboolean color_d; - GtkWidget *color_w; -}; - -/* the paint options structures */ -typedef struct _PaintOptions PaintOptions; -struct _PaintOptions -{ - ToolOptions tool_options; - - /* vbox for the common paint options */ - GtkWidget *paint_vbox; - - /* a widget to be shown if we are in global mode */ - GtkWidget *global; - - /* options used by all paint tools */ - GtkObject *opacity_w; - GtkWidget *paint_mode_w; - - /* this tool's private context */ - GimpContext *context; - - /* the incremental toggle */ - gboolean incremental; - gboolean incremental_d; - GtkWidget *incremental_w; - - /* the pressure-sensitivity options */ - PaintPressureOptions *pressure_options; -}; - - -/* the default pressure_options for non_gui use */ -extern PaintPressureOptions non_gui_pressure_options; - - -/* paint tool options functions */ - -PaintOptions *paint_options_new (ToolType tool_type, - ToolOptionsResetFunc reset_func); - -void paint_options_reset (PaintOptions *options); - -/* to be used by "derived" paint options only */ -void paint_options_init (PaintOptions *options, - ToolType tool_type, - ToolOptionsResetFunc reset_func); - - -/* functions for the global paint options */ - -/* switch between global and per-tool paint options */ -void paint_options_set_global (gboolean global); - - -/* a utility function which returns a paint mode menu */ -GtkWidget * paint_mode_menu_new (GtkSignalFunc callback, - gpointer data, - LayerModeEffects initial); - -#endif /* __PAINT_OPTIONS_H__ */ diff --git a/app/paintbrush.c b/app/paintbrush.c deleted file mode 100644 index 5d9cee29be..0000000000 --- a/app/paintbrush.c +++ /dev/null @@ -1,775 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimpbrushlist.h" -#include "gimpbrush.h" -#include "gimpcontext.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "gradient.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "paintbrush.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpmath.h" -#include "libgimp/gimpunitmenu.h" - -#include "libgimp/gimpintl.h" - - -/* defines */ -#define PAINT_LEFT_THRESHOLD 0.05 - -/* defaults for the tool options */ -#define PAINTBRUSH_DEFAULT_INCREMENTAL FALSE -#define PAINTBRUSH_DEFAULT_USE_FADE FALSE -#define PAINTBRUSH_DEFAULT_FADE_OUT 100.0 -#define PAINTBRUSH_DEFAULT_FADE_UNIT GIMP_UNIT_PIXEL -#define PAINTBRUSH_DEFAULT_USE_GRADIENT FALSE -#define PAINTBRUSH_DEFAULT_GRADIENT_LENGTH 100.0 -#define PAINTBRUSH_DEFAULT_GRADIENT_UNIT GIMP_UNIT_PIXEL -#define PAINTBRUSH_DEFAULT_GRADIENT_TYPE LOOP_TRIANGLE - -/* the paintbrush structures */ - -typedef struct _PaintbrushOptions PaintbrushOptions; - -struct _PaintbrushOptions -{ - PaintOptions paint_options; - - gboolean use_fade; - gboolean use_fade_d; - GtkWidget *use_fade_w; - - gdouble fade_out; - gdouble fade_out_d; - GtkObject *fade_out_w; - - GimpUnit fade_unit; - GimpUnit fade_unit_d; - GtkWidget *fade_unit_w; - - gboolean use_gradient; - gboolean use_gradient_d; - GtkWidget *use_gradient_w; - - gdouble gradient_length; - gdouble gradient_length_d; - GtkObject *gradient_length_w; - - GimpUnit gradient_unit; - GimpUnit gradient_unit_d; - GtkWidget *gradient_unit_w; - - gint gradient_type; - gint gradient_type_d; - GtkWidget *gradient_type_w; -}; - -/* the paint brush tool options */ -static PaintbrushOptions * paintbrush_options = NULL; - -/* local variables */ -static gdouble non_gui_fade_out; -static gdouble non_gui_gradient_length; -static gint non_gui_gradient_type; -static gdouble non_gui_incremental; -static GimpUnit non_gui_fade_unit; -static GimpUnit non_gui_gradient_unit; - - -/* forward function declarations */ -static void paintbrush_motion (PaintCore *, - GimpDrawable *, - PaintPressureOptions *, - gdouble , - gdouble , - PaintApplicationMode , - GradientPaintMode ); -static gpointer paintbrush_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); - - -/* functions */ - -static void -paintbrush_gradient_toggle_callback (GtkWidget *widget, - gpointer data) -{ - PaintbrushOptions *options = paintbrush_options; - - static gboolean incremental_save = FALSE; - - gimp_toggle_button_update (widget, data); - - if (paintbrush_options->use_gradient) - { - incremental_save = options->paint_options.incremental; - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (options->paint_options.incremental_w), TRUE); - } - else - { - gtk_toggle_button_set_active - (GTK_TOGGLE_BUTTON (options->paint_options.incremental_w), - incremental_save); - } -} - -static void -paintbrush_options_reset (void) -{ - PaintbrushOptions *options = paintbrush_options; - GtkWidget *spinbutton; - gint digits; - - paint_options_reset ((PaintOptions *) options); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_fade_w), - options->use_fade_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->fade_out_w), - options->fade_out_d); - gimp_unit_menu_set_unit (GIMP_UNIT_MENU (options->fade_unit_w), - options->fade_unit_d); - digits = ((options->fade_unit_d == GIMP_UNIT_PIXEL) ? 0 : - ((options->fade_unit_d == GIMP_UNIT_PERCENT) ? 2 : - (MIN (6, MAX (3, gimp_unit_get_digits (options->fade_unit_d)))))); - spinbutton = gtk_object_get_data (GTK_OBJECT (options->fade_unit_w), "set_digits"); - gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), digits); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_gradient_w), - options->use_gradient_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->gradient_length_w), - options->gradient_length_d); - gimp_unit_menu_set_unit (GIMP_UNIT_MENU (options->gradient_unit_w), - options->gradient_unit_d); - digits = ((options->gradient_unit_d == GIMP_UNIT_PIXEL) ? 0 : - ((options->gradient_unit_d == GIMP_UNIT_PERCENT) ? 2 : - (MIN (6, MAX (3, gimp_unit_get_digits (options->gradient_unit_d)))))); - spinbutton = gtk_object_get_data (GTK_OBJECT (options->gradient_unit_w), "set_digits"); - gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), digits); - - options->gradient_type = options->gradient_type_d; - - gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w), - options->gradient_type_d); -} - -static PaintbrushOptions * -paintbrush_options_new (void) -{ - PaintbrushOptions *options; - - GtkWidget *vbox; - GtkWidget *abox; - GtkWidget *table; - GtkWidget *type_label; - GtkWidget *spinbutton; - - /* the new paint tool options structure */ - options = g_new (PaintbrushOptions, 1); - paint_options_init ((PaintOptions *) options, - PAINTBRUSH, - paintbrush_options_reset); - - options->use_fade = - options->use_fade_d = PAINTBRUSH_DEFAULT_USE_FADE; - options->fade_out = - options->fade_out_d = PAINTBRUSH_DEFAULT_FADE_OUT; - options->fade_unit = - options->fade_unit_d = PAINTBRUSH_DEFAULT_FADE_UNIT; - options->use_gradient = - options->use_gradient_d = PAINTBRUSH_DEFAULT_USE_GRADIENT; - options->gradient_length = - options->gradient_length_d = PAINTBRUSH_DEFAULT_GRADIENT_LENGTH; - options->gradient_unit = - options->gradient_unit_d = PAINTBRUSH_DEFAULT_GRADIENT_UNIT; - options->gradient_type = - options->gradient_type_d = PAINTBRUSH_DEFAULT_GRADIENT_TYPE; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - table = gtk_table_new (3, 3, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); - gtk_table_set_row_spacing (GTK_TABLE (table), 1, 3); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - /* the use fade toggle */ - abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); - gtk_table_attach (GTK_TABLE (table), abox, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (abox); - - options->use_fade_w = - gtk_check_button_new_with_label (_("Fade Out")); - gtk_container_add (GTK_CONTAINER (abox), options->use_fade_w); - gtk_signal_connect (GTK_OBJECT (options->use_fade_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->use_fade); - gtk_widget_show (options->use_fade_w); - - /* the fade-out sizeentry */ - options->fade_out_w = - gtk_adjustment_new (options->fade_out_d, 1e-5, 32767.0, 1.0, 50.0, 0.0); - spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (options->fade_out_w), 1.0, 0.0); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), GTK_SHADOW_NONE); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_widget_set_usize (spinbutton, 75, 0); - gtk_signal_connect (GTK_OBJECT (options->fade_out_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->fade_out); - gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 0, 1); - gtk_widget_show (spinbutton); - - /* the fade-out unitmenu */ - options->fade_unit_w = - gimp_unit_menu_new ("%a", options->fade_unit_d, TRUE, TRUE, TRUE); - gtk_signal_connect (GTK_OBJECT (options->fade_unit_w), "unit_changed", - GTK_SIGNAL_FUNC (gimp_unit_menu_update), - &options->fade_unit); - gtk_object_set_data (GTK_OBJECT (options->fade_unit_w), "set_digits", spinbutton); - gtk_table_attach (GTK_TABLE (table), options->fade_unit_w, 2, 3, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (options->fade_unit_w); - - /* automatically set the sensitive state of the fadeout stuff */ - gtk_widget_set_sensitive (spinbutton, options->use_fade_d); - gtk_widget_set_sensitive (options->fade_unit_w, options->use_fade_d); - gtk_object_set_data (GTK_OBJECT (options->use_fade_w), - "set_sensitive", spinbutton); - gtk_object_set_data (GTK_OBJECT (spinbutton), - "set_sensitive", options->fade_unit_w); - - /* the use gradient toggle */ - abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); - gtk_table_attach (GTK_TABLE (table), abox, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (abox); - - options->use_gradient_w = - gtk_check_button_new_with_label (_("Gradient")); - gtk_container_add (GTK_CONTAINER (abox), options->use_gradient_w); - gtk_signal_connect (GTK_OBJECT (options->use_gradient_w), "toggled", - GTK_SIGNAL_FUNC (paintbrush_gradient_toggle_callback), - &options->use_gradient); - gtk_widget_show (options->use_gradient_w); - - /* the gradient length scale */ - options->gradient_length_w = - gtk_adjustment_new (options->gradient_length_d, 1e-5, 32767.0, 1.0, 50.0, 0.0); - spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (options->gradient_length_w), 1.0, 0.0); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), GTK_SHADOW_NONE); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_widget_set_usize (spinbutton, 75, 0); - gtk_signal_connect (GTK_OBJECT (options->gradient_length_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->gradient_length); - gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 1, 2); - gtk_widget_show (spinbutton); - - /* the gradient unitmenu */ - options->gradient_unit_w = - gimp_unit_menu_new ("%a", options->gradient_unit_d, TRUE, TRUE, TRUE); - gtk_signal_connect (GTK_OBJECT (options->gradient_unit_w), "unit_changed", - GTK_SIGNAL_FUNC (gimp_unit_menu_update), - &options->gradient_unit); - gtk_object_set_data (GTK_OBJECT (options->gradient_unit_w), "set_digits", - spinbutton); - gtk_table_attach (GTK_TABLE (table), options->gradient_unit_w, 2, 3, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (options->gradient_unit_w); - - /* the gradient type */ - type_label = gtk_label_new (_("Type:")); - gtk_misc_set_alignment (GTK_MISC (type_label), 1.0, 0.5); - gtk_table_attach (GTK_TABLE (table), type_label, 0, 1, 2, 3, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (type_label); - - abox = gtk_alignment_new (0.0, 0.5, 0.0, 0.0); - gtk_table_attach_defaults (GTK_TABLE (table), abox, 1, 3, 2, 3); - gtk_widget_show (abox); - - options->gradient_type_w = gimp_option_menu_new2 - (FALSE, gimp_menu_item_update, - &options->gradient_type, (gpointer) options->gradient_type_d, - - _("Once Forward"), (gpointer) ONCE_FORWARD, NULL, - _("Once Backward"), (gpointer) ONCE_BACKWARDS, NULL, - _("Loop Sawtooth"), (gpointer) LOOP_SAWTOOTH, NULL, - _("Loop Triangle"), (gpointer) LOOP_TRIANGLE, NULL, - - NULL); - gtk_container_add (GTK_CONTAINER (abox), options->gradient_type_w); - gtk_widget_show (options->gradient_type_w); - - gtk_widget_show (table); - - /* automatically set the sensitive state of the gradient stuff */ - gtk_widget_set_sensitive (spinbutton, options->use_gradient_d); - gtk_widget_set_sensitive (spinbutton, options->use_gradient_d); - gtk_widget_set_sensitive (options->gradient_unit_w, options->use_gradient_d); - gtk_widget_set_sensitive (options->gradient_type_w, options->use_gradient_d); - gtk_widget_set_sensitive (type_label, options->use_gradient_d); - gtk_widget_set_sensitive (options->paint_options.incremental_w, - ! options->use_gradient_d); - gtk_object_set_data (GTK_OBJECT (options->use_gradient_w), "set_sensitive", - spinbutton); - gtk_object_set_data (GTK_OBJECT (spinbutton), "set_sensitive", - options->gradient_unit_w); - gtk_object_set_data (GTK_OBJECT (options->gradient_unit_w), "set_sensitive", - options->gradient_type_w); - gtk_object_set_data (GTK_OBJECT (options->gradient_type_w), "set_sensitive", - type_label); - gtk_object_set_data (GTK_OBJECT (options->use_gradient_w), "inverse_sensitive", - options->paint_options.incremental_w); - - return options; -} - -#define TIMED_BRUSH 0 - -static gpointer -paintbrush_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - GDisplay *gdisp = gdisplay_active (); - double fade_out; - double gradient_length; - double unit_factor; - - g_return_val_if_fail (gdisp != NULL, NULL); - -#if TIMED_BRUSH - static GTimer *timer = NULL; -#endif - switch (state) - { - case INIT_PAINT: -#if TIMED_BRUSH - timer = g_timer_new(); - g_timer_start(timer); -#endif /* TIMED_BRUSH */ - break; - - case MOTION_PAINT: - switch (paintbrush_options->fade_unit) - { - case GIMP_UNIT_PIXEL: - fade_out = paintbrush_options->fade_out; - break; - case GIMP_UNIT_PERCENT: - fade_out = MAX (gdisp->gimage->width, gdisp->gimage->height) * - paintbrush_options->fade_out / 100; - break; - default: - unit_factor = gimp_unit_get_factor (paintbrush_options->fade_unit); - fade_out = paintbrush_options->fade_out * - MAX (gdisp->gimage->xresolution, gdisp->gimage->yresolution) / unit_factor; - break; - } - - switch (paintbrush_options->gradient_unit) - { - case GIMP_UNIT_PIXEL: - gradient_length = paintbrush_options->gradient_length; - break; - case GIMP_UNIT_PERCENT: - gradient_length = MAX (gdisp->gimage->width, gdisp->gimage->height) * - paintbrush_options->gradient_length / 100; - break; - default: - unit_factor = gimp_unit_get_factor (paintbrush_options->gradient_unit); - gradient_length = paintbrush_options->gradient_length * - MAX (gdisp->gimage->xresolution, gdisp->gimage->yresolution) / unit_factor; - break; - } - - paintbrush_motion (paint_core, drawable, - paintbrush_options->paint_options.pressure_options, - paintbrush_options->use_fade ? fade_out : 0, - paintbrush_options->use_gradient ? gradient_length : 0, - paintbrush_options->paint_options.incremental, - paintbrush_options->gradient_type); - break; - - case FINISH_PAINT : -#if TIMED_BRUSH - if (timer) - { - g_timer_stop(timer); - g_print ("painting took %f:\n", g_timer_elapsed(timer, NULL)); - g_timer_destroy(timer); - timer = NULL; - } -#endif /* TIMED_BRUSH */ - break; - - default : - break; - } - - return NULL; -} - - -Tool * -tools_new_paintbrush () -{ - Tool * tool; - PaintCore * private; - - /* The tool options */ - if (! paintbrush_options) - { - paintbrush_options = paintbrush_options_new (); - tools_register (PAINTBRUSH, (ToolOptions *) paintbrush_options); - - /* press all default buttons */ - paintbrush_options_reset (); - } - - tool = paint_core_new (PAINTBRUSH); - - private = (PaintCore *) tool->private; - private->paint_func = paintbrush_paint_func; - private->pick_colors = TRUE; - private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - return tool; -} - - -void -tools_free_paintbrush (Tool *tool) -{ - paint_core_free (tool); -} - - -static void -paintbrush_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - double fade_out, - double gradient_length, - PaintApplicationMode incremental, - GradientPaintMode gradient_type) -{ - GImage *gimage; - TempBuf *area; - gdouble x, paint_left; - gdouble position; - guchar local_blend = OPAQUE_OPACITY; - guchar temp_blend = OPAQUE_OPACITY; - guchar col[MAX_CHANNELS]; - GimpRGB color; - gint mode; - gint opacity; - gdouble scale; - PaintApplicationMode paint_appl_mode = incremental ? INCREMENTAL : CONSTANT; - - position = 0.0; - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - if (pressure_options->color) - gradient_length = 1.0; /* not really used, only for if cases */ - - /* Get a region which can be used to paint to */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - /* factor in the fade out value */ - if (fade_out) - { - /* Model the amount of paint left as a gaussian curve */ - x = ((double) paint_core->pixel_dist / fade_out); - paint_left = exp (- x * x * 5.541); /* ln (1/255) */ - local_blend = (int) (255 * paint_left); - } - - if (local_blend) - { - /* set the alpha channel */ - temp_blend = local_blend; - mode = gradient_type; - - if (gradient_length) - { - if (pressure_options->color) - gradient_get_color_at (gimp_context_get_gradient (NULL), - paint_core->curpressure, &color); - else - paint_core_get_color_from_gradient (paint_core, gradient_length, - &color, mode); - - temp_blend = (gint) ((color.a * local_blend)); - - gimp_rgb_get_uchar (&color, - &col[RED_PIX], - &col[GREEN_PIX], - &col[BLUE_PIX]); - col[ALPHA_PIX] = OPAQUE_OPACITY; - - /* always use incremental mode with gradients */ - /* make the gui cool later */ - paint_appl_mode = INCREMENTAL; - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - } - /* we check to see if this is a pixmap, if so composite the - pixmap image into the are instead of the color */ - else if (paint_core->brush && paint_core->brush->pixmap) - { - paint_core_color_area_with_pixmap (paint_core, gimage, drawable, - area, - scale, SOFT); - paint_appl_mode = INCREMENTAL; - } - else - { - gimp_image_get_foreground (gimage, drawable, col); - col[area->bytes - 1] = OPAQUE_OPACITY; - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - } - - opacity = (gdouble)temp_blend; - if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; - - paint_core_paste_canvas (paint_core, drawable, - MIN (opacity, 255), - gimp_context_get_opacity (NULL) * 255, - gimp_context_get_paint_mode (NULL), - pressure_options->pressure ? PRESSURE : SOFT, - scale, paint_appl_mode); - } -} - - -static gpointer -paintbrush_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - GImage *gimage; - gdouble fade_out; - gdouble gradient_length; - gdouble unit_factor; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return NULL; - - switch (non_gui_fade_unit) - { - case GIMP_UNIT_PIXEL: - fade_out = non_gui_fade_out; - break; - case GIMP_UNIT_PERCENT: - fade_out = MAX (gimage->width, gimage->height) * - non_gui_fade_out / 100; - break; - default: - unit_factor = gimp_unit_get_factor (non_gui_fade_unit); - fade_out = non_gui_fade_out * - MAX (gimage->xresolution, gimage->yresolution) / unit_factor; - break; - } - - switch (non_gui_gradient_unit) - { - case GIMP_UNIT_PIXEL: - gradient_length = non_gui_gradient_length; - break; - case GIMP_UNIT_PERCENT: - gradient_length = MAX (gimage->width, gimage->height) * - non_gui_gradient_length / 100; - break; - default: - unit_factor = gimp_unit_get_factor (non_gui_gradient_unit); - gradient_length = non_gui_gradient_length * - MAX (gimage->xresolution, gimage->yresolution) / unit_factor; - break; - } - - paintbrush_motion (paint_core,drawable, - &non_gui_pressure_options, - fade_out, - gradient_length, - non_gui_incremental, - non_gui_gradient_type); - - return NULL; -} - -gboolean -paintbrush_non_gui_default (GimpDrawable *drawable, - int num_strokes, - double *stroke_array) -{ - PaintbrushOptions *options = paintbrush_options; - gdouble fade_out = PAINTBRUSH_DEFAULT_FADE_OUT; - gboolean incremental = PAINTBRUSH_DEFAULT_INCREMENTAL; - gboolean use_gradient = PAINTBRUSH_DEFAULT_USE_GRADIENT; - gboolean use_fade = PAINTBRUSH_DEFAULT_USE_FADE; - gdouble gradient_length = PAINTBRUSH_DEFAULT_GRADIENT_LENGTH; - gint gradient_type = PAINTBRUSH_DEFAULT_GRADIENT_TYPE; - GimpUnit fade_unit = PAINTBRUSH_DEFAULT_FADE_UNIT; - GimpUnit gradient_unit = PAINTBRUSH_DEFAULT_GRADIENT_UNIT; - gint i; - - if (options) - { - fade_out = options->fade_out; - incremental = options->paint_options.incremental; - use_gradient = options->use_gradient; - gradient_length = options->gradient_length; - gradient_type = options->gradient_type; - use_fade = options->use_fade; - fade_unit = options->fade_unit; - gradient_unit = options->gradient_unit; - } - - if (use_gradient == FALSE) - gradient_length = 0.0; - - if (use_fade == FALSE) - fade_out = 0.0; - - /* Hmmm... PDB paintbrush should have gradient type added to it!*/ - /* thats why the code below is duplicated. - */ - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - non_gui_fade_out = fade_out; - non_gui_gradient_length = gradient_length; - non_gui_gradient_type = gradient_type; - non_gui_incremental = incremental; - non_gui_fade_unit = fade_unit; - non_gui_gradient_unit = gradient_unit; - - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = paintbrush_non_gui_paint_func; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - non_gui_paint_core.flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - paintbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - return TRUE; - } - else - return FALSE; -} - -gboolean -paintbrush_non_gui (GimpDrawable *drawable, - int num_strokes, - double *stroke_array, - double fade_out, - int method, - double gradient_length) -{ - int i; - - /* Code duplicated above */ - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - non_gui_fade_out = fade_out; - non_gui_gradient_length = gradient_length; - non_gui_gradient_type = LOOP_TRIANGLE; - non_gui_incremental = method; - - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = paintbrush_non_gui_paint_func; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - non_gui_paint_core.flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - if (num_strokes == 1) - paintbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - return TRUE; - } - else - return FALSE; -} diff --git a/app/paintbrush.h b/app/paintbrush.h deleted file mode 100644 index 4ce8b274a9..0000000000 --- a/app/paintbrush.h +++ /dev/null @@ -1,37 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PAINTBRUSH_H__ -#define __PAINTBRUSH_H__ - - -gboolean paintbrush_non_gui (GimpDrawable *, - gint , - gdouble *, - gdouble , - gint , - gdouble ); -gboolean paintbrush_non_gui_default (GimpDrawable *, - gint , - gdouble *); - -Tool * tools_new_paintbrush (void); -void tools_free_paintbrush (Tool *tool); - - -#endif /* __PAINTBRUSH_H__ */ diff --git a/app/path.c b/app/path.c index f62e0550ef..dcf2e83348 100644 --- a/app/path.c +++ b/app/path.c @@ -25,13 +25,14 @@ #include #include "apptypes.h" -#include "bezier_selectP.h" #include "gdisplay.h" #include "gimpimage.h" #include "path.h" #include "pathP.h" #include "paths_dialog.h" +#include "tools/bezier_selectP.h" + #include "libgimp/gimpmath.h" diff --git a/app/path_tool.c b/app/path_tool.c deleted file mode 100644 index f25924ddaa..0000000000 --- a/app/path_tool.c +++ /dev/null @@ -1,1900 +0,0 @@ -/* The GIMP -- an image manipulation program - * - * This file Copyright (C) 1999 Simon Budig - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Complete new path-tool by Simon Budig - * - * a path manipulation core independent of the underlying formula: - * implement bezier-curves, intelligent scissors-curves, splines... - * - * A Path is a collection of curves, which are constructed from - * segments between two anchors. - */ - -#include -/* #include "appenv.h" - */ - -#include "draw_core.h" -#include "cursorutil.h" -#include "path_tool.h" -#include "path_toolP.h" -#include "path_curves.h" - -#include "config.h" -#include "libgimp/gimpintl.h" - -/* - * Every new curve-type has to have a parameter between 0 and 1, and - * should go from a starting to a target point. - */ - - - -/* Some defines... */ - -#define PATH_TOOL_WIDTH 8 -#define PATH_TOOL_HALFWIDTH 4 - -/* local function prototypes */ - - -/* Small functions to determine coordinates, iterate over path/curve/segment */ - -void path_segment_get_coordinates (PathSegment *, - gdouble, - gint *, - gint *); -void path_traverse_path (Path *, - PathTraverseFunc, - CurveTraverseFunc, - SegmentTraverseFunc, - gpointer); -void path_traverse_curve (Path *, - PathCurve *, - CurveTraverseFunc, - SegmentTraverseFunc, - gpointer); -void path_traverse_segment (Path *, - PathCurve *, - PathSegment *, - SegmentTraverseFunc, - gpointer); -gdouble path_locate_point (Path *, - PathCurve **, - PathSegment **, - gint, - gint, - gint, - gint, - gint); - -/* Tools to manipulate paths, curves, segments */ - -PathCurve * path_add_curve (Path *, - gint, - gint); -PathSegment * path_append_segment (Path *, - PathCurve *, - SegmentType, - gint, - gint); -PathSegment * path_prepend_segment (Path *, - PathCurve *, - SegmentType, - gint, - gint); -PathSegment * path_split_segment (PathSegment *, - gdouble); -void path_join_curves (PathSegment *, - PathSegment *); -void path_flip_curve (PathCurve *); -void path_free_path (Path *); -void path_free_curve (PathCurve *); -void path_free_segment (PathSegment *); -void path_delete_segment (PathSegment *); -void path_print (Path *); -void path_offset_active (Path *, gdouble, gdouble); -void path_set_flags (PathTool *, - Path *, - PathCurve *, - PathSegment *, - guint32, - guint32); - -/* High level image-manipulation functions */ - -void path_stroke (PathTool *, - Path *); -void path_to_selection (PathTool *, - Path *); - -/* Functions necessary for the tool */ - -void path_tool_button_press (Tool *, GdkEventButton *, gpointer); -void path_tool_button_release (Tool *, GdkEventButton *, gpointer); -void path_tool_motion (Tool *, GdkEventMotion *, gpointer); -void path_tool_cursor_update (Tool *, GdkEventMotion *, gpointer); -void path_tool_control (Tool *, ToolAction, gpointer); -void path_tool_draw (Tool *); -void path_tool_draw_curve (Tool *, PathCurve *); -void path_tool_draw_segment (Tool *, PathSegment *); - -gdouble path_tool_on_curve (Tool *, gint, gint, gint, - Path**, PathCurve**, PathSegment**); -gboolean path_tool_on_anchors (Tool *, gint, gint, gint, - Path**, PathCurve**, PathSegment**); -gint path_tool_on_handles (Tool *, gint, gint, gint, - Path **, PathCurve **, PathSegment **); - -gint path_tool_button_press_canvas (Tool *, GdkEventButton *, GDisplay *); -gint path_tool_button_press_anchor (Tool *, GdkEventButton *, GDisplay *); -gint path_tool_button_press_handle (Tool *, GdkEventButton *, GDisplay *); -gint path_tool_button_press_curve (Tool *, GdkEventButton *, GDisplay *); -void path_tool_motion_anchor (Tool *, GdkEventMotion *, GDisplay *); -void path_tool_motion_handle (Tool *, GdkEventMotion *, GDisplay *); -void path_tool_motion_curve (Tool *, GdkEventMotion *, GDisplay *); - - -/* the path tool options */ -static ToolOptions *path_options = NULL; - - -/* - * - * - * Here we go! - * - * - */ - -/* - * These functions are for applying a function over a complete - * path/curve/segment. They can pass information to each other - * with a arbitrary data structure - * - * The idea behind the three different functions is: - * if pathfunc != NULL - * call pathfunc for every curve - * else - * if curvefunc != NULL - * call curvefunc for every segment - * else - * call segmentfunc for every point - * - */ - -void -path_traverse_path (Path *path, - PathTraverseFunc pathfunc, - CurveTraverseFunc curvefunc, - SegmentTraverseFunc segmentfunc, - gpointer data) -{ - PathCurve *cur_curve; - - if (path && path->curves) - { - cur_curve = path->curves; - if (pathfunc) - do { - (* pathfunc) (path, cur_curve, data); - cur_curve = cur_curve->next; - } while (cur_curve && cur_curve != path->curves); - else - do { - path_traverse_curve (path, cur_curve, curvefunc, segmentfunc, data); - cur_curve = cur_curve->next; - } while (cur_curve && cur_curve != path->curves); - } -} - - -void -path_traverse_curve (Path *path, - PathCurve *curve, - CurveTraverseFunc curvefunc, - SegmentTraverseFunc segmentfunc, - gpointer data) -{ - PathSegment *cur_segment; - - if (curve && curve->segments) - { - cur_segment = curve->segments; - if (curvefunc) - do { - (* curvefunc) (path, curve, cur_segment, data); - cur_segment = cur_segment->next; - } while (cur_segment && cur_segment != curve->segments); - else - do { - path_traverse_segment (path, curve, cur_segment, segmentfunc, data); - cur_segment = cur_segment->next; - } while (cur_segment && cur_segment != curve->segments); - } -} - -void -path_traverse_segment (Path *path, - PathCurve *curve, - PathSegment *segment, - SegmentTraverseFunc function, - gpointer data) -{ -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_traverse_segment\n"); -#endif PATH_TOOL_DEBUG - - /* XXX: here we need path_curve_get_point(s) */ - - /* Something like: - * for i = 1 to subsamples { - * (x,y) = get_coordinates(i / subsamples) - * (* function) (....) - * } - */ -} - -/************************************************************** - * Helper functions for manipulating the data-structures: - */ - -PathCurve * -path_add_curve (Path * cur_path, - gint x, - gint y) -{ - PathCurve * tmp = cur_path->curves; - PathCurve * new_curve = NULL; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_add_curve\n"); -#endif PATH_TOOL_DEBUG - - if (cur_path) { - new_curve = g_new (PathCurve, 1); - - new_curve->parent = cur_path; - new_curve->next = tmp; - new_curve->prev = NULL; - new_curve->cur_segment = NULL; - new_curve->segments = NULL; - - if (tmp) tmp->prev = new_curve; - - cur_path->curves = cur_path->cur_curve = new_curve; - - new_curve->segments = path_prepend_segment (cur_path, new_curve, SEGMENT_BEZIER, x, y); - } -#ifdef PATH_TOOL_DEBUG - else - fprintf (stderr, "Fatal Error: path_add_curve called without valid path\n"); -#endif PATH_TOOL_DEBUG - - return new_curve; -} - - -PathSegment * -path_append_segment (Path * cur_path, - PathCurve * cur_curve, - SegmentType type, - gint x, - gint y) -{ - PathSegment * tmp = cur_curve->segments; - PathSegment * new_segment = NULL; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_append_segment\n"); -#endif PATH_TOOL_DEBUG - - if (cur_curve) { - tmp = cur_curve->segments; - while (tmp && tmp->next && tmp->next != cur_curve->segments) { - tmp = tmp->next; - } - - if (tmp == NULL || tmp->next == NULL) { - new_segment = g_new (PathSegment, 1); - - new_segment->type = type; - new_segment->x = x; - new_segment->y = y; - new_segment->flags = 0; - new_segment->parent = cur_curve; - new_segment->next = NULL; - new_segment->prev = tmp; - new_segment->data = NULL; - - if (tmp) - tmp->next = new_segment; - - cur_curve->cur_segment = new_segment; - - path_curve_init_segment (new_segment); - - } -#ifdef PATH_TOOL_DEBUG - else - fprintf(stderr, "Fatal Error: path_append_segment called with a closed curve\n"); -#endif PATH_TOOL_DEBUG - } -#ifdef PATH_TOOL_DEBUG - else - fprintf(stderr, "Fatal Error: path_append_segment called without valid curve\n"); -#endif PATH_TOOL_DEBUG - - return new_segment; -} - - -PathSegment * -path_prepend_segment (Path * cur_path, - PathCurve * cur_curve, - SegmentType type, - gint x, - gint y) -{ - PathSegment * tmp = cur_curve->segments; - PathSegment * new_segment = NULL; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_prepend_segment\n"); -#endif PATH_TOOL_DEBUG - - if (cur_curve) { - tmp = cur_curve->segments; - - if (tmp == NULL || tmp->prev == NULL) { - new_segment = g_new (PathSegment, 1); - - new_segment->type = type; - new_segment->x = x; - new_segment->y = y; - new_segment->flags = 0; - new_segment->parent = cur_curve; - new_segment->next = tmp; - new_segment->prev = NULL; - new_segment->data = NULL; - - if (tmp) - tmp->prev = new_segment; - - cur_curve->segments = new_segment; - cur_curve->cur_segment = new_segment; - - path_curve_init_segment (new_segment); - } -#ifdef PATH_TOOL_DEBUG - else - fprintf(stderr, "Fatal Error: path_prepend_segment called with a closed curve\n"); -#endif PATH_TOOL_DEBUG - } -#ifdef PATH_TOOL_DEBUG - else - fprintf(stderr, "Fatal Error: path_prepend_segment called without valid curve\n"); -#endif PATH_TOOL_DEBUG - - return new_segment; -} - -PathSegment * -path_split_segment (PathSegment *segment, - gdouble position) -{ - PathSegment * new_segment = NULL; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_split_segment\n"); -#endif PATH_TOOL_DEBUG - if (segment && segment->next) { - new_segment = g_new (PathSegment, 1); - - new_segment->type = segment->type; - /* XXX: Giving PathTool as NULL Pointer! */ - path_curve_get_point (NULL, segment, position, &(new_segment->x), &(new_segment->y)); - new_segment->flags = 0; - new_segment->parent = segment->parent; - new_segment->next = segment->next; - new_segment->prev = segment; - new_segment->data = NULL; - - path_curve_init_segment (new_segment); - - new_segment->next->prev = new_segment; - segment->next = new_segment; - - return new_segment; - - } -#ifdef PATH_TOOL_DEBUG - else - fprintf(stderr, "path_split_segment without valid segment\n"); -#endif PATH_TOOL_DEBUG - return NULL; - -} - -/* - * Join two arbitrary endpoints and free the parent from the second - * segment, if it differs from the first parents. - */ - -void -path_join_curves (PathSegment *segment1, - PathSegment *segment2) -{ - PathCurve *curve1, *curve2; - PathSegment *tmp; - - if ((segment1->next && segment1->prev) || (segment2->next && segment2->prev)) { -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "Fatal Error: path_join_curves called with a closed segment\n"); -#endif PATH_TOOL_DEBUG - return; - } - if (segment1->parent == segment2->parent) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Joining beginning and end of the same curve...\n"); -#endif PATH_TOOL_DEBUG - if (segment2->next == NULL) { - segment2->next = segment1; - segment1->prev = segment2; - } else { - segment2->prev = segment1; - segment1->next = segment2; - } -/* XXX: Probably some segment-updates needed */ - return; - } - - if (segment1->next == NULL && segment2->next == NULL) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Flipping second curve (next, next)...\n"); -#endif PATH_TOOL_DEBUG - path_flip_curve (segment2->parent); - /* segment2 = segment2->parent->segments; - */ - } - - if (segment1->prev == NULL && segment2->prev == NULL) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Flipping second curve (prev, prev)...\n"); -#endif PATH_TOOL_DEBUG - path_flip_curve (segment2->parent); - /* segment2 = segment2->parent->segments; - * while (segment2->next) - * segment2 = segment2->next; - */ - } - - if (segment1->next == NULL && segment2->prev == NULL) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Appending second to first curve...\n"); -#endif PATH_TOOL_DEBUG - curve1 = segment1->parent; - curve2 = segment2->parent; - - segment1->next = segment2; - segment2->prev = segment1; - - curve2->segments = NULL; - - if (curve2->prev) - curve2->prev->next = curve2->next; - if (curve2->next) - curve2->next->prev = curve2->prev; - - if (curve2->parent->curves == curve2) - curve2->parent->curves = curve2->next; - - path_free_curve (curve2); - - tmp = segment2; - - while (tmp) { - tmp->parent = curve1; - tmp = tmp->next; - } -/* XXX: Probably some segment-updates needed */ - return; - } - - if (segment1->prev == NULL && segment2->next == NULL) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Prepending second to first curve...\n"); -#endif PATH_TOOL_DEBUG - curve1 = segment1->parent; - curve2 = segment2->parent; - - segment1->prev = segment2; - segment2->next = segment1; - - curve2->segments = NULL; - if (curve2->prev) - curve2->prev->next = curve2->next; - if (curve2->next) - curve2->next->prev = curve2->prev; - if (curve2->parent->curves == curve2) - curve2->parent->curves = curve2->next; - path_free_curve (curve2); - - tmp = segment2; - - while (tmp) { - tmp->parent = curve1; - curve1->segments = tmp; - tmp = tmp->prev; - } - return; -/* XXX: Probably some segment-updates needed */ - } - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Cant join these curves yet...\nThis should not happen."); - return; -#endif PATH_TOOL_DEBUG - -} - -/* - * This function reverses the order of the anchors. This is - * necessary for some joining operations. - */ -void -path_flip_curve (PathCurve *curve) -{ - gpointer *end_data; - SegmentType end_type; - - PathSegment *tmp, *tmp2; - - if (!curve && !curve->segments) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_flip_curve: No curve o no segments to flip!\n"); -#endif PATH_TOOL_DEBUG - return; - } - - tmp = curve->segments; - - while (tmp->next) - tmp = tmp->next; - - end_data = tmp->data; - end_type = tmp->type; - - tmp->parent->segments = tmp; - - while (tmp) { - tmp2 = tmp->next; - tmp->next = tmp->prev; - tmp->prev = tmp2; - if (tmp->next) { - tmp->type = tmp->next->type; - tmp->data = tmp->next->data; - } else { - tmp->type = end_type; - tmp->data = end_data; - } - path_curve_flip_segment (tmp); - tmp = tmp->next; - } -} - - -void -path_free_path (Path * path) -{ - PathCurve *tmp1, *tmp2; - - if (path) - { - tmp2 = path->curves; - - while ((tmp1 = tmp2) != NULL) - { - tmp2 = tmp1->next; - path_free_curve (tmp1); - } - g_string_free(path->name, TRUE); - g_free(path); - } -} - -void -path_free_curve (PathCurve *curve) -{ - PathSegment *tmp1, *tmp2; - - if (curve) - { - tmp2 = curve->segments; - - /* break closed curves */ - if (tmp2 && tmp2->prev) - tmp2->prev->next = NULL; - - while ((tmp1 = tmp2) != NULL) - { - tmp2 = tmp1->next; - path_free_segment (tmp1); - } - g_free(curve); - } -} - -void -path_free_segment (PathSegment *segment) -{ - if (segment) - { - /* Clear the active flag to keep path_tool->single_active_segment - * consistent */ - - - path_set_flags (segment->parent->parent->path_tool, segment->parent->parent, - segment->parent, segment, 0, SEGMENT_ACTIVE); - - path_curve_cleanup_segment(segment); - - g_free (segment); - } -} - -void -path_delete_curve (PathCurve *curve) -{ - if (curve) - { - if (curve->next) - curve->next->prev = curve->prev; - if (curve->prev) - curve->prev->next = curve->next; - - if (curve == curve->parent->curves) { - curve->parent->curves = curve->next; - } - - path_free_curve (curve); - } -} - -void -path_delete_segment (PathSegment *segment) -{ - if (segment) - { - if (segment->next) - segment->next->prev = segment->prev; - if (segment->prev) - segment->prev->next = segment->next; - - /* If the remaining curve is closed and has a - * single point only, open it. - */ - if (segment->next == segment->prev && segment->next) - segment->next->next = segment->next->prev = NULL; - - if (segment == segment->parent->segments) - segment->parent->segments = segment->next; - - if (segment->parent->segments == NULL) - path_delete_curve (segment->parent); - - path_free_segment (segment); - - /* - * here we have to update the surrounding segments - */ -/* XXX: Please add path_curve_update_segment here */ - } -} - - -/* - * A function to determine, which object is hit by the cursor - */ - -gint -path_tool_cursor_position (Tool *tool, - gint x, - gint y, - gint halfwidth, - Path **pathP, - PathCurve **curveP, - PathSegment **segmentP, - gdouble *positionP, - gint *handle_idP) -{ - gdouble pos; - gint handle_id; - - if (path_tool_on_anchors (tool, x, y, halfwidth, pathP, curveP, segmentP)) - return ON_ANCHOR; - - handle_id = path_tool_on_handles (tool, x, y, halfwidth, pathP, curveP, segmentP); - if (handle_id) { - if (handle_idP) (*handle_idP) = handle_id; - return ON_HANDLE; - } - - pos = path_tool_on_curve (tool, x, y, halfwidth, pathP, curveP, segmentP); - if (pos >= 0 && pos <= 1) { - if (positionP) (*positionP) = pos; - return ON_CURVE; - } - - - return ON_CANVAS; -} - - -/************************************************************** - * The click-callbacks for the tool - */ - -void -path_tool_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - PathTool * path_tool; - gint grab_pointer=0; - gint x, y, halfwidth, dummy; - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_tool_button_press\n"); -#endif PATH_TOOL_DEBUG - - path_tool = (PathTool *) tool->private; - tool->gdisp = gdisp; - - /* Transform window-coordinates to canvas-coordinates */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0); -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "Clickcoordinates %d, %d\n",x,y); -#endif PATH_TOOL_DEBUG - path_tool->click_x = x; - path_tool->click_y = y; - path_tool->click_modifier = bevent->state; - /* get halfwidth in image coord */ - gdisplay_untransform_coords (gdisp, bevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); - halfwidth -= x; - path_tool->click_halfwidth = halfwidth; - - if (!path_tool->cur_path->curves) - draw_core_start (path_tool->core, gdisp->canvas->window, tool); - - /* determine point, where clicked, - * switch accordingly. - */ - - path_tool->click_type = path_tool_cursor_position (tool, x, y, halfwidth, - &(path_tool->click_path), - &(path_tool->click_curve), - &(path_tool->click_segment), - &(path_tool->click_position), - &(path_tool->click_handle_id)); - - switch (path_tool->click_type) - { - case ON_CANVAS: - grab_pointer = path_tool_button_press_canvas(tool, bevent, gdisp); - break; - - case ON_ANCHOR: - grab_pointer = path_tool_button_press_anchor(tool, bevent, gdisp); - break; - - case ON_HANDLE: - grab_pointer = path_tool_button_press_handle(tool, bevent, gdisp); - break; - - case ON_CURVE: - grab_pointer = path_tool_button_press_curve(tool, bevent, gdisp); - break; - - default: - g_message("Huh? Whats happening here? (button_press_*)"); - } - - if (grab_pointer) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - -} - -gint -path_tool_button_press_anchor (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - static guint32 last_click_time=0; - gboolean doubleclick=FALSE; - PathTool *path_tool = tool->private; - - Path * cur_path = path_tool->cur_path; - PathSegment *p_sas; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_tool_button_press_anchor:\n"); -#endif PATH_TOOL_DEBUG - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Fatal error: No current Path\n"); -#endif PATH_TOOL_DEBUG - return 0; - } - - /* - * We have to determine, if this was a doubleclick for ourself, because - * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to - * the switch statement confuses some tools. - */ - if (bevent->time - last_click_time < 250) { - doubleclick=TRUE; -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Doppelclick!\n"); -#endif PATH_TOOL_DEBUG - } else - doubleclick=FALSE; - last_click_time = bevent->time; - - - draw_core_pause (path_tool->core, tool); - - /* The user pressed on an anchor: - * normally this activates this anchor - * + SHIFT toggles the activity of an anchor. - * if this anchor is at the end of an open curve and the other - * end is active, close the curve. - * - * Doubleclick (de)activates the whole curve (not Path!). - */ - - p_sas = path_tool->single_active_segment; - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "p_sas: %p\n", p_sas); -#endif PATH_TOOL_DEBUG - - if (path_tool->click_modifier & GDK_SHIFT_MASK) { - if (path_tool->active_count == 1 && p_sas && p_sas != path_tool->click_segment && - (p_sas->next == NULL || p_sas->prev == NULL) && - (path_tool->click_segment->next == NULL || path_tool->click_segment->prev == NULL)) { - /* - * if this is the end of an open curve and the single active segment was another - * open end, connect those ends. - */ - path_join_curves (path_tool->click_segment, p_sas); - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, 0, SEGMENT_ACTIVE); - } - - if (doubleclick) - /* - * Doubleclick set the whole curve to the same state, depending on the - * state of the clicked anchor. - */ - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, SEGMENT_ACTIVE, 0); - else - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - NULL, 0, SEGMENT_ACTIVE); - else - /* - * Toggle the state of the clicked anchor. - */ - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment, 0, SEGMENT_ACTIVE); - else - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment, SEGMENT_ACTIVE, 0); - } - /* - * Delete anchors, when CONTROL is pressed - */ - else if (path_tool->click_modifier & GDK_CONTROL_MASK) - { - if (path_tool->click_segment->flags & SEGMENT_ACTIVE) - { - if (path_tool->click_segment->prev) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment->prev, SEGMENT_ACTIVE, 0); - else if (path_tool->click_segment->next) - path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve, - path_tool->click_segment->next, SEGMENT_ACTIVE, 0); - } - - path_delete_segment (path_tool->click_segment); - path_tool->click_segment = NULL; - /* Maybe CTRL-ALT Click should remove the whole curve? Or the active points? */ - } - else if (!(path_tool->click_segment->flags & SEGMENT_ACTIVE)) - { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0); - } - - - draw_core_resume(path_tool->core, tool); - - return grab_pointer; -} - - -gint -path_tool_button_press_handle (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - static guint32 last_click_time=0; - gboolean doubleclick=FALSE; - PathTool *path_tool = tool->private; - - Path * cur_path = path_tool->cur_path; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_tool_button_press_handle:\n"); -#endif PATH_TOOL_DEBUG - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Fatal error: No current Path\n"); -#endif PATH_TOOL_DEBUG - return 0; - } - - /* - * We have to determine, if this was a doubleclick for ourself, because - * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to - * the switch statement confuses some tools. - */ - if (bevent->time - last_click_time < 250) { - doubleclick=TRUE; -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Doppelclick!\n"); -#endif PATH_TOOL_DEBUG - } else - doubleclick=FALSE; - last_click_time = bevent->time; - - return grab_pointer; -} - -gint -path_tool_button_press_canvas (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - PathTool *path_tool = tool->private; - - Path * cur_path = path_tool->cur_path; - PathCurve * cur_curve; - PathSegment * cur_segment; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_tool_button_press_canvas:\n"); -#endif PATH_TOOL_DEBUG - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Fatal error: No current Path\n"); -#endif PATH_TOOL_DEBUG - return 0; - } - - draw_core_pause (path_tool->core, tool); - - if (path_tool->active_count == 1 && path_tool->single_active_segment != NULL - && (path_tool->single_active_segment->prev == NULL || path_tool->single_active_segment->next == NULL)) { - cur_segment = path_tool->single_active_segment; - cur_curve = cur_segment->parent; - - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - - if (cur_segment->next == NULL) - cur_curve->cur_segment = path_append_segment(cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y); - else - cur_curve->cur_segment = path_prepend_segment(cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y); - if (cur_curve->cur_segment) { - path_set_flags (path_tool, cur_path, cur_curve, cur_curve->cur_segment, SEGMENT_ACTIVE, 0); - } - } else { - if (path_tool->active_count == 0) { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - cur_path->cur_curve = path_add_curve(cur_path, path_tool->click_x, path_tool->click_y); - path_set_flags (path_tool, cur_path, cur_path->cur_curve, cur_path->cur_curve->segments, SEGMENT_ACTIVE, 0); - } else { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - } - } - - draw_core_resume(path_tool->core, tool); - - return 0; -} - -gint -path_tool_button_press_curve (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - PathTool *path_tool = tool->private; - - Path * cur_path = path_tool->cur_path; - PathSegment * cur_segment; - gint grab_pointer; - -#ifdef PATH_TOOL_DEBUG - fprintf(stderr, "path_tool_button_press_curve:\n"); -#endif PATH_TOOL_DEBUG - - grab_pointer = 1; - - if (!cur_path) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Fatal error: No current Path\n"); -#endif PATH_TOOL_DEBUG - return 0; - } - - draw_core_pause (path_tool->core, tool); - - if (path_tool->click_modifier & GDK_SHIFT_MASK) { - cur_segment = path_curve_insert_anchor (path_tool, path_tool->click_segment, path_tool->click_position); - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, cur_segment, SEGMENT_ACTIVE, 0); - path_tool->click_type = ON_ANCHOR; - path_tool->click_segment = cur_segment; - - } else { - path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0); - path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment->next, SEGMENT_ACTIVE, 0); - } - draw_core_resume(path_tool->core, tool); - - return 0; -} - -void -path_tool_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_tool_button_release\n"); -#endif PATH_TOOL_DEBUG - - path_tool = (PathTool *) tool->private; - - path_tool->state &= ~PATH_TOOL_DRAG; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); -} - - -/************************************************************** - * The motion-callbacks for the tool - */ - -void -path_tool_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - PathTool * path_tool; - - if (gtk_events_pending()) return; - - path_tool = (PathTool *) tool->private; - - switch (path_tool->click_type) { - case ON_ANCHOR: - path_tool_motion_anchor (tool, mevent, gdisp); - break; - case ON_HANDLE: - path_tool_motion_handle (tool, mevent, gdisp); - break; - case ON_CURVE: - path_tool_motion_curve (tool, mevent, gdisp); - break; - default: - return; - } - -} - -void -path_tool_motion_anchor (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - PathTool * path_tool; - gdouble dx, dy, d; - gint x,y; - static gint dxsum = 0; - static gint dysum = 0; - - path_tool = (PathTool *) tool->private; - - /* - * Dont do anything, if the user clicked with pressed CONTROL-Key, - * because he deleted an anchor. - */ - if (path_tool->click_modifier & GDK_CONTROL_MASK) - return; - - if (!(path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - dx = x - path_tool->click_x - dxsum; - dy = y - path_tool->click_y - dysum; - - /* restrict to horizontal/vertical lines, if modifiers are pressed - * I'm not sure, if this is intuitive for the user. Esp. When moving - * an endpoint of an curve I'd expect, that the *line* is - * horiz/vertical - not the delta to the point, where the point was - * originally... - */ - if (mevent->state & GDK_MOD1_MASK) - { - if (mevent->state & GDK_CONTROL_MASK) - { - d = (fabs(dx) + fabs(dy)) / 2; - d = (fabs(x - path_tool->click_x) + fabs(y - path_tool->click_y)) / 2; - - dx = ((x < path_tool->click_x) ? -d : d ) - dxsum; - dy = ((y < path_tool->click_y) ? -d : d ) - dysum; - } - else - dx = - dxsum; - } - else if (mevent->state & GDK_CONTROL_MASK) - dy = - dysum; - - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - draw_core_pause(path_tool->core, tool); - - path_offset_active (path_tool->cur_path, dx, dy); - - dxsum += dx; - dysum += dy; - - draw_core_resume (path_tool->core, tool); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; - -} - -void -path_tool_motion_handle (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - PathTool * path_tool; - gdouble dx, dy; - gint x,y; - static gint dxsum = 0; - static gint dysum = 0; - - path_tool = (PathTool *) tool->private; - - /* - * Dont do anything, if the user clicked with pressed CONTROL-Key, - * because he moved the handle to the anchor an anchor. - * XXX: Not yet! :-) - */ - if (path_tool->click_modifier & GDK_CONTROL_MASK) - return; - - if (!(path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - dx = x - path_tool->click_x - dxsum; - dy = y - path_tool->click_y - dysum; - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - draw_core_pause(path_tool->core, tool); - - path_curve_drag_handle (path_tool, path_tool->click_segment, dx, dy, path_tool->click_handle_id); - - dxsum += dx; - dysum += dy; - - draw_core_resume (path_tool->core, tool); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; - -} - - -void -path_tool_motion_curve (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - PathTool * path_tool; - gdouble dx, dy; - gint x,y; - static gint dxsum = 0; - static gint dysum = 0; - - path_tool = (PathTool *) tool->private; - - if (!(path_tool->state & PATH_TOOL_DRAG)) - { - path_tool->state |= PATH_TOOL_DRAG; - dxsum = 0; - dysum = 0; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - - dx = x - path_tool->click_x - dxsum; - dy = y - path_tool->click_y - dysum; - - path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE; - - draw_core_pause(path_tool->core, tool); - - path_curve_drag_segment (path_tool, path_tool->click_segment, path_tool->click_position, dx, dy); - - dxsum += dx; - dysum += dy; - - draw_core_resume (path_tool->core, tool); - - path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE; - -} - - -void -path_tool_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - PathTool *path_tool; - gint x, y, halfwidth, dummy, cursor_location; - -#ifdef PATH_TOOL_DEBUG - /* fprintf (stderr, "path_tool_cursor_update\n"); - */ -#endif PATH_TOOL_DEBUG - - path_tool = (PathTool *) tool->private; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - /* get halfwidth in image coord */ - gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0); - halfwidth -= x; - - cursor_location = path_tool_cursor_position (tool, x, y, halfwidth, NULL, NULL, NULL, NULL, NULL); - - switch (cursor_location) { - case ON_CANVAS: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR); - break; - case ON_ANCHOR: - gdisplay_install_tool_cursor (gdisp, GDK_FLEUR); - break; - case ON_HANDLE: - gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR); - break; - case ON_CURVE: - gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR); - break; - default: - gdisplay_install_tool_cursor (gdisp, GDK_QUESTION_ARROW); - break; - } -} - -/************************************************************** - * Tool-control functions - */ - -void -path_tool_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_tool_control\n"); -#endif PATH_TOOL_DEBUG - - path_tool = (PathTool *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (path_tool->core, tool); - break; - - case RESUME: - draw_core_resume (path_tool->core, tool); - break; - - case HALT: -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_tool_control: HALT\n"); -#endif PATH_TOOL_DEBUG - draw_core_stop (path_tool->core, tool); - tool->state = INACTIVE; - break; - - default: - break; - } -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_tool_control: end\n"); -#endif PATH_TOOL_DEBUG -} - -Tool * -tools_new_path_tool (void) -{ - Tool * tool; - PathTool * private; - - /* The tool options */ - if (! path_options) - { - path_options = tool_options_new (_("Path Tool")); - tools_register (PATH_TOOL, (ToolOptions *) path_options); - } - - tool = tools_new_tool (PATH_TOOL); - private = g_new0 (PathTool, 1); - - private->click_type = ON_CANVAS; - private->click_x = 0; - private->click_y = 0; - private->click_halfwidth = 0; - private->click_modifier = 0; - private->click_path = NULL; - private->click_curve = NULL; - private->click_segment = NULL; - private->click_position = -1; - - private->active_count = 0; - private->single_active_segment = NULL; - - private->state = 0; - private->draw = PATH_TOOL_REDRAW_ALL; - private->core = draw_core_new (path_tool_draw); - private->cur_path = g_new0(Path, 1); - private->scanlines = NULL; - - - tool->private = (void *) private; - - tool->button_press_func = path_tool_button_press; - tool->button_release_func = path_tool_button_release; - tool->motion_func = path_tool_motion; - tool->cursor_update_func = path_tool_cursor_update; - tool->control_func = path_tool_control; - - private->cur_path->curves = NULL; - private->cur_path->cur_curve = NULL; - private->cur_path->name = g_string_new("Path 0"); - private->cur_path->state = 0; - private->cur_path->path_tool = private; - - return tool; -} - -void -tools_free_path_tool (Tool *tool) -{ - GDisplay * gdisp; - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "tools_free_path_tool start\n"); -#endif PATH_TOOL_DEBUG - path_tool = (PathTool *) tool->private; - gdisp = tool->gdisp; - - if (tool->state == ACTIVE) - { - draw_core_stop (path_tool->core, tool); - } - - path_free_path (path_tool->cur_path); - - draw_core_free (path_tool->core); - - g_free (path_tool); -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "tools_free_path_tool end\n"); -#endif PATH_TOOL_DEBUG - -} - - -/************************************************************** - * Set of function to determine, if the click was on a segment - */ - -typedef struct { - Tool *tool; - Path *path; - PathCurve *curve; - PathSegment *segment; - gint testx; - gint testy; - gint halfwidth; - gint distance; - gdouble position; - gboolean found; -} Path_on_curve_type; - -/* This is a CurveTraverseFunc */ -void -path_tool_on_curve_helper (Path *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - gint distance; - gdouble position; - Path_on_curve_type *data = (Path_on_curve_type *) ptr; - - if (segment && segment->next && data && data->distance > 0) - { - position = path_curve_on_segment (data->tool, segment, data->testx, data->testy, data->halfwidth, &distance); - if (position >= 0 && distance < data->distance ) - { - data->path = path; - data->curve = curve; - data->segment = segment; - data->distance = distance; - data->position = position; - data->found = TRUE; - } - } -} - -gdouble -path_tool_on_curve (Tool *tool, - gint x, - gint y, - gint halfwidth, - Path **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP) -{ - Path_on_curve_type *data = g_new (Path_on_curve_type, 1); - gdouble position; - - data->tool = tool; - data->path = NULL; - data->segment = NULL; - data->segment = NULL; - data->testx = x; - data->testy = y; - data->halfwidth = halfwidth; - data->distance = halfwidth * halfwidth + 1; - data->position = -1; - data->found = FALSE; - - path_traverse_path (((PathTool *) data->tool->private)->cur_path, NULL, path_tool_on_curve_helper, NULL, data); - - if (ret_pathP) *ret_pathP = data->path; - if (ret_curveP) *ret_curveP = data->curve; - if (ret_segmentP) *ret_segmentP = data->segment; - - position = data->position; - - g_free(data); - - return position; - -} - -/************************************************************** - * Set of function to determine, if the click was on an anchor - */ - -typedef struct { - Path *path; - PathCurve *curve; - PathSegment *segment; - gint testx; - gint testy; - gint distance; - gboolean found; -} Path_on_anchors_type; - -/* This is a CurveTraverseFunc */ -void -path_tool_on_anchors_helper (Path *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - gint distance; - Path_on_anchors_type *data = (Path_on_anchors_type *) ptr; - - if (segment && data && data->distance > 0) - { - distance = ((data->testx - segment->x) * (data->testx - segment->x) + - (data->testy - segment->y) * (data->testy - segment->y)); - - if ( distance < data->distance ) - { - data->path = path; - data->curve = curve; - data->segment = segment; - data->distance = distance; - data->found = TRUE; - } - } -} - -gboolean -path_tool_on_anchors (Tool *tool, - gint x, - gint y, - gint halfwidth, - Path **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP) -{ - Path_on_anchors_type *data = g_new (Path_on_anchors_type, 1); - gboolean ret_found; - - data->path = NULL; - data->curve = NULL; - data->segment = NULL; - data->testx = x; - data->testy = y; - data->distance = halfwidth * halfwidth + 1; - data->found = FALSE; - - path_traverse_path (((PathTool *) tool->private)->cur_path, NULL, path_tool_on_anchors_helper, NULL, data); - - if (ret_pathP) *ret_pathP = data->path; - if (ret_curveP) *ret_curveP = data->curve; - if (ret_segmentP) *ret_segmentP = data->segment; - - ret_found = data->found; - - g_free(data); - - return ret_found; - -} - -/************************************************************** - * Set of function to determine, if the click was on an handle - */ - -typedef struct { - Path *path; - PathCurve *curve; - PathSegment *segment; - gint testx; - gint testy; - gint halfwidth; - gint handle_id; - gboolean found; -} Path_on_handles_type; - -/* This is a CurveTraverseFunc */ -void -path_tool_on_handles_helper (Path *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - Path_on_handles_type *data = (Path_on_handles_type *) ptr; - gint handle; - - if (segment && data && !data->found) - { - handle = path_curve_on_handle (NULL, segment, data->testx, data->testy, - data->halfwidth); - if (handle) - { - data->path = path; - data->curve = curve; - data->segment = segment; - data->handle_id = handle; - data->found = TRUE; - } - } -} - -gint -path_tool_on_handles (Tool *tool, - gint x, - gint y, - gint halfwidth, - Path **ret_pathP, - PathCurve **ret_curveP, - PathSegment **ret_segmentP) -{ - Path_on_handles_type *data = g_new (Path_on_handles_type, 1); - gint handle_ret; - - data->path = NULL; - data->curve = NULL; - data->segment = NULL; - data->testx = x; - data->testy = y; - data->halfwidth = halfwidth; - data->handle_id = 0; - data->found = FALSE; - - path_traverse_path (((PathTool *) tool->private)->cur_path, NULL, path_tool_on_handles_helper, NULL, data); - - if (ret_pathP) *ret_pathP = data->path; - if (ret_curveP) *ret_curveP = data->curve; - if (ret_segmentP) *ret_segmentP = data->segment; - - handle_ret = data->handle_id; - - g_free(data); - - return handle_ret; -} - - -/************************************************************** - * Set of function to offset all active anchors - */ - -typedef struct { - gdouble dx; - gdouble dy; -} Path_offset_active_type; - -/* This is a CurveTraverseFunc */ -void -path_offset_active_helper (Path *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - Path_offset_active_type *data = (Path_offset_active_type *) ptr; - - if (segment && data && (segment->flags & SEGMENT_ACTIVE)) { - segment->x += data->dx; - segment->y += data->dy; - } -/* XXX: Do a segment_update here! */ -} - -void -path_offset_active (Path *path, - gdouble dx, - gdouble dy) -{ - Path_offset_active_type *data = g_new (Path_offset_active_type, 1); - data->dx = dx; - data->dy = dy; - - if (path) - path_traverse_path (path, NULL, path_offset_active_helper, NULL, data); - - g_free(data); -} - - -/************************************************************** - * Set of function to set the state of all anchors - */ - -typedef struct { - guint32 bits_set; - guint32 bits_clear; - PathTool *path_tool; -} Path_set_flags_type; - -/* This is a CurveTraverseFunc */ -void -path_set_flags_helper (Path *path, - PathCurve *curve, - PathSegment *segment, - gpointer ptr) -{ - Path_set_flags_type *tmp = (Path_set_flags_type *) ptr; - guint32 oldflags; - guint tmp_uint; - - if (segment) { - oldflags = segment->flags; - segment->flags &= ~(tmp->bits_clear); - segment->flags |= tmp->bits_set; - - /* - * Some black magic: We try to remember, which is the single active segment. - * We count, how many segments are active (in path_tool->active_count) and - * XOR path_tool->single_active_segment every time we select or deselect - * an anchor. So if exactly one anchor is active, path_tool->single_active_segment - * points to it. - */ - - /* If SEGMENT_ACTIVE state has changed change the PathTool data accordingly.*/ - if (((segment->flags ^ oldflags) & SEGMENT_ACTIVE) && tmp && tmp->path_tool) { - if (segment->flags & SEGMENT_ACTIVE) - tmp->path_tool->active_count++; - else - tmp->path_tool->active_count--; - - /* Does this work on all (16|32|64)-bit Machines? */ - - tmp_uint = GPOINTER_TO_UINT(tmp->path_tool->single_active_segment); - tmp_uint ^= GPOINTER_TO_UINT(segment); - tmp->path_tool->single_active_segment = GUINT_TO_POINTER(tmp_uint); - } - } -} - -void -path_set_flags (PathTool *path_tool, - Path *path, - PathCurve *curve, - PathSegment *segment, - guint32 bits_set, - guint32 bits_clear) -{ - Path_set_flags_type *tmp = g_new (Path_set_flags_type, 1); - tmp->bits_set=bits_set; - tmp->bits_clear=bits_clear; - tmp->path_tool = path_tool; - - if (segment) - path_set_flags_helper (path, curve, segment, tmp); - else if (curve) - path_traverse_curve (path, curve, path_set_flags_helper, NULL, tmp); - else if (path) - path_traverse_path (path, NULL, path_set_flags_helper, NULL, tmp); - - g_free (tmp); -} - - -/************************************************************** - * Set of functions to draw the segments to the window - */ - -/* This is a CurveTraverseFunc */ -void -path_tool_draw_helper (Path *path, - PathCurve *curve, - PathSegment *segment, - gpointer tool_ptr) -{ - Tool * tool = (Tool *) tool_ptr; - GDisplay * gdisp; - PathTool * path_tool; - DrawCore * core; - gint x1, y1; - gboolean draw = TRUE; - - if (!tool) { -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "Fatal Error: path_tool_draw_segment called without valid tool *\n"); -#endif PATH_TOOL_DEBUG - return; - } - - gdisp = tool->gdisp; - - path_tool = (PathTool *) tool->private; - core = path_tool->core; - - if (path_tool->draw & PATH_TOOL_REDRAW_ACTIVE) - draw = (segment->flags & SEGMENT_ACTIVE || (segment->next && segment->next->flags & SEGMENT_ACTIVE)); - - if (segment && draw) - { - gdisplay_transform_coords (gdisp, (gint) segment->x, (gint) segment->y, &x1, &y1, FALSE); - if (segment->flags & SEGMENT_ACTIVE) - gdk_draw_arc (core->win, core->gc, 0, - x1 - PATH_TOOL_HALFWIDTH, y1 - PATH_TOOL_HALFWIDTH, - PATH_TOOL_WIDTH, PATH_TOOL_WIDTH, 0, 23040); - else - gdk_draw_arc (core->win, core->gc, 1, - x1 - PATH_TOOL_HALFWIDTH, y1 - PATH_TOOL_HALFWIDTH, - PATH_TOOL_WIDTH, PATH_TOOL_WIDTH, 0, 23040); - - path_curve_draw_handles (tool, segment); - - if (segment->next) - { - path_curve_draw_segment (tool, segment); - } - } -#ifdef PATH_TOOL_DEBUG - else if (!segment) - fprintf(stderr, "path_tool_draw_segment: no segment to draw\n"); -#endif PATH_TOOL_DEBUG -} - -void -path_tool_draw (Tool *tool) -{ - GDisplay * gdisp; - Path * cur_path; - PathTool * path_tool; - -#ifdef PATH_TOOL_DEBUG - fprintf (stderr, "path_tool_draw\n"); -#endif PATH_TOOL_DEBUG - - gdisp = tool->gdisp; - path_tool = tool->private; - cur_path = path_tool->cur_path; - - path_traverse_path (cur_path, NULL, path_tool_draw_helper, NULL, tool); - -#ifdef PATH_TOOL_DEBUG - /* fprintf (stderr, "path_tool_draw end.\n"); - */ -#endif PATH_TOOL_DEBUG - -} - - diff --git a/app/path_tool.h b/app/path_tool.h deleted file mode 100644 index 158e244599..0000000000 --- a/app/path_tool.h +++ /dev/null @@ -1,33 +0,0 @@ -/* The GIMP -- an image manipulation program - * - * This file Copyright (C) 1999 Simon Budig - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PATH_TOOL_H__ -#define __PATH_TOOL_H__ - -#include "tools.h" - -/* path functions */ - -Tool * tools_new_path_tool (void); -void tools_free_path_tool (Tool *); - - -#endif /* __PATH_TOOL_H__ */ - - diff --git a/app/path_toolP.h b/app/path_toolP.h deleted file mode 100644 index 73cde47273..0000000000 --- a/app/path_toolP.h +++ /dev/null @@ -1,134 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef __PATH_TOOLP_H__ -#define __PATH_TOOLP_H__ - -#undef PATH_TOOL_DEBUG - -#include "draw_core.h" - -#ifdef PATH_TOOL_DEBUG -#include -#endif - -#define IMAGE_COORDS 1 -#define AA_IMAGE_COORDS 2 -#define SCREEN_COORDS 3 - -#define SEGMENT_ACTIVE 1 - -#define PATH_TOOL_DRAG 1 - -#define PATH_TOOL_REDRAW_ALL 1 -#define PATH_TOOL_REDRAW_ACTIVE 2 -#define PATH_TOOL_REDRAW_HANDLES 4 - -#define SUBDIVIDE 1000 - -typedef enum { SEGMENT_LINE=0, SEGMENT_BEZIER} SegmentType; - -enum { ON_ANCHOR, ON_HANDLE, ON_CURVE, ON_CANVAS }; - -typedef struct _path_segment PathSegment; -typedef struct _path_curve PathCurve; -typedef struct _path Path; - -typedef struct _path_tool PathTool; - -struct _path_segment -{ - SegmentType type; /* What type of segment */ - gdouble x, y; /* location of starting-point in image space */ - gpointer data; /* Additional data, dependant of segment-type */ - - guint32 flags; /* Various Flags: Is the Segment active? */ - - PathCurve *parent; /* the parent Curve */ - PathSegment *next; /* Next Segment or NULL */ - PathSegment *prev; /* Previous Segment or NULL */ - -}; - - -struct _path_curve -{ - PathSegment *segments; /* The segments of the curve */ - PathSegment *cur_segment; /* the current segment */ - Path *parent; /* the parent Path */ - PathCurve *next; /* Next Curve or NULL */ - PathCurve *prev; /* Previous Curve or NULL */ -}; - - -struct _path -{ - PathCurve *curves; /* the curves */ - PathCurve *cur_curve; /* the current curve */ - GString *name; /* the name of the path */ - guint32 state; /* is the path locked? */ - PathTool *path_tool; /* The parent Path Tool */ -}; - - -struct _path_tool -{ - gint click_type; /* where did the user click? */ - gint click_x; /* X-coordinate of the click */ - gint click_y; /* Y-coordinate of the click */ - gint click_halfwidth; - guint click_modifier; /* what modifiers were pressed? */ - Path *click_path; /* On which Path/Curve/Segment */ - PathCurve *click_curve; /* was the click? */ - PathSegment *click_segment; - gdouble click_position; /* The position on the segment */ - gint click_handle_id; /* The handle ID of the segment */ - - gint active_count; /* How many segments are active? */ - /* - * WARNING: single_active_segment may contain non NULL Values - * which point to the nirvana. But they are important! - * The pointer is garantueed to be valid, when active_count==1 - */ - PathSegment *single_active_segment; /* The only active segment */ - - gint state; /* state of tool */ - gint draw; /* all or part */ - DrawCore *core; /* Core drawing object */ - Path *cur_path; /* the current active path */ - GSList **scanlines; /* used in converting a path */ -}; - -typedef void -(*PathTraverseFunc) (Path *, - PathCurve *, - gpointer); -typedef void -(*CurveTraverseFunc) (Path *, - PathCurve *, - PathSegment *, - gpointer); -typedef void -(*SegmentTraverseFunc) (Path *, - PathCurve *, - PathSegment *, - gint, - gint, - gpointer); - -#endif /* __PATH_TOOLP_H__ */ - diff --git a/app/paths_dialog.c b/app/paths_dialog.c index 005e05b006..0f8d019397 100644 --- a/app/paths_dialog.c +++ b/app/paths_dialog.c @@ -45,8 +45,6 @@ #include "lc_dialogP.h" #include "menus.h" #include "ops_buttons.h" -#include "bezier_select.h" -#include "bezier_selectP.h" #include "path.h" #include "pathP.h" #include "path_transform.h" @@ -55,6 +53,9 @@ #include "plug_in.h" #include "undo.h" +#include "tools/bezier_select.h" +#include "tools/bezier_selectP.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpintl.h" diff --git a/app/paths_dialogP.h b/app/paths_dialogP.h index 19f7c09c09..7785e29250 100644 --- a/app/paths_dialogP.h +++ b/app/paths_dialogP.h @@ -15,10 +15,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #ifndef __PATHS_DIALOG_P_H__ #define __PATHS_DIALOG_P_H__ -#include "bezier_selectP.h" void paths_newpoint_current (BezierSelect *, GDisplay *); void paths_first_button_press (BezierSelect *, GDisplay *); @@ -27,4 +27,5 @@ Path * paths_get_bzpaths (void); void paths_set_bzpaths (GImage *, Path *); void paths_dialog_set_default_op (void); + #endif /* __PATHS_DIALOG_P_H__ */ diff --git a/app/pdb/color_cmds.c b/app/pdb/color_cmds.c index 2c1e196086..168802a6c5 100644 --- a/app/pdb/color_cmds.c +++ b/app/pdb/color_cmds.c @@ -26,8 +26,6 @@ #include "apptypes.h" #include "procedural_db.h" -#include "color_balance.h" -#include "curves.h" #include "desaturate.h" #include "drawable.h" #include "equalize.h" @@ -35,14 +33,16 @@ #include "gimphistogram.h" #include "gimpimage.h" #include "gimplut.h" -#include "histogram_tool.h" #include "histogramwidget.h" -#include "hue_saturation.h" #include "invert.h" #include "lut_funcs.h" #include "pixel_processor.h" #include "pixel_region.h" -#include "threshold.h" +#include "tools/color_balance.h" +#include "tools/curves.h" +#include "tools/histogram_tool.h" +#include "tools/hue_saturation.h" +#include "tools/threshold.h" static ProcRecord brightness_contrast_proc; static ProcRecord levels_proc; diff --git a/app/pdb/text_tool_cmds.c b/app/pdb/text_tool_cmds.c index db394a52d8..bdb665522c 100644 --- a/app/pdb/text_tool_cmds.c +++ b/app/pdb/text_tool_cmds.c @@ -31,7 +31,7 @@ #include "appenv.h" #include "drawable.h" #include "layer.h" -#include "text_tool.h" +#include "tools/text_tool.h" #include "libgimp/gimplimits.h" diff --git a/app/pdb/tools_cmds.c b/app/pdb/tools_cmds.c index 6991aa5587..7aeee4654d 100644 --- a/app/pdb/tools_cmds.c +++ b/app/pdb/tools_cmds.c @@ -26,33 +26,33 @@ #include "apptypes.h" #include "procedural_db.h" -#include "airbrush.h" -#include "blend.h" -#include "bucket_fill.h" -#include "by_color_select.h" -#include "clone.h" -#include "color_picker.h" -#include "convolve.h" -#include "crop.h" -#include "dodgeburn.h" #include "drawable.h" -#include "ellipse_select.h" -#include "eraser.h" -#include "flip_tool.h" -#include "free_select.h" -#include "fuzzy_select.h" #include "gimpimage.h" -#include "paintbrush.h" -#include "pencil.h" -#include "perspective_tool.h" -#include "rect_select.h" -#include "rotate_tool.h" -#include "scale_tool.h" -#include "shear_tool.h" -#include "smudge.h" #include "tile_manager.h" #include "tile_manager_pvt.h" -#include "transform_core.h" +#include "tools/airbrush.h" +#include "tools/blend.h" +#include "tools/bucket_fill.h" +#include "tools/by_color_select.h" +#include "tools/clone.h" +#include "tools/color_picker.h" +#include "tools/convolve.h" +#include "tools/crop.h" +#include "tools/dodgeburn.h" +#include "tools/ellipse_select.h" +#include "tools/eraser.h" +#include "tools/flip_tool.h" +#include "tools/free_select.h" +#include "tools/fuzzy_select.h" +#include "tools/paintbrush.h" +#include "tools/pencil.h" +#include "tools/perspective_tool.h" +#include "tools/rect_select.h" +#include "tools/rotate_tool.h" +#include "tools/scale_tool.h" +#include "tools/shear_tool.h" +#include "tools/smudge.h" +#include "tools/transform_core.h" #include "undo.h" static ProcRecord airbrush_proc; diff --git a/app/pencil.c b/app/pencil.c deleted file mode 100644 index 59915c5289..0000000000 --- a/app/pencil.c +++ /dev/null @@ -1,267 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimpbrush.h" -#include "gimpcontext.h" -#include "gimpimage.h" -#include "gradient.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "paint_options.h" -#include "paintbrush.h" -#include "pencil.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" -#include "tool_options.h" - - -#define PENCIL_INCREMENTAL_DEFAULT FALSE - -/* the pencil tool options */ -typedef struct _PencilOptions PencilOptions; - -struct _PencilOptions -{ - PaintOptions paint_options; -}; - - -/* forward function declarations */ -static void pencil_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - gboolean ); -static gpointer pencil_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); - - -static PencilOptions *pencil_options = NULL; - -static gboolean non_gui_incremental = FALSE; -static void pencil_options_reset (void); - - -/* functions */ - -gpointer -pencil_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - switch (state) - { - case INIT_PAINT: - break; - - case MOTION_PAINT: - pencil_motion (paint_core, drawable, - pencil_options->paint_options.pressure_options, - pencil_options->paint_options.incremental); - break; - - case FINISH_PAINT: - break; - - default: - break; - } - - return NULL; -} - -static PencilOptions * -pencil_options_new (void) -{ - PencilOptions *options; - - options = g_new (PencilOptions, 1); - paint_options_init ((PaintOptions *) options, - PENCIL, - pencil_options_reset); - - return options; -} - -static void -pencil_options_reset (void) -{ - paint_options_reset ((PaintOptions *) pencil_options); -} - -Tool * -tools_new_pencil (void) -{ - Tool * tool; - PaintCore * private; - - /* The tool options */ - if (!pencil_options) - { - pencil_options = pencil_options_new (); - tools_register (PENCIL, (ToolOptions *) pencil_options); - pencil_options_reset(); - } - - tool = paint_core_new (PENCIL); - - private = (PaintCore *) tool->private; - private->paint_func = pencil_paint_func; - private->pick_colors = TRUE; - private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - return tool; -} - -void -tools_free_pencil (Tool *tool) -{ - paint_core_free (tool); -} - -static void -pencil_motion (PaintCore *paint_core, - GimpDrawable *drawable, - PaintPressureOptions *pressure_options, - gboolean increment) -{ - GImage *gimage; - TempBuf *area; - guchar col[MAX_CHANNELS]; - gint opacity; - gdouble scale; - PaintApplicationMode paint_appl_mode = increment ? INCREMENTAL : CONSTANT; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - if (pressure_options->size) - scale = paint_core->curpressure; - else - scale = 1.0; - - /* Get a region which can be used to paint to */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) - return; - - /* color the pixels */ - if (pressure_options->color) - { - GimpRGB color; - - gradient_get_color_at (gimp_context_get_gradient (NULL), - paint_core->curpressure, &color); - - gimp_rgba_get_uchar (&color, - &col[RED_PIX], - &col[GREEN_PIX], - &col[BLUE_PIX], - &col[ALPHA_PIX]); - - paint_appl_mode = INCREMENTAL; - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - } - else if (paint_core->brush && paint_core->brush->pixmap) - { - /* if its a pixmap, do pixmap stuff */ - paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area, - scale, HARD); - paint_appl_mode = INCREMENTAL; - } - else - { - gimp_image_get_foreground (gimage, drawable, col); - col[area->bytes - 1] = OPAQUE_OPACITY; - color_pixels (temp_buf_data (area), col, - area->width * area->height, area->bytes); - } - - opacity = 255 * gimp_context_get_opacity (NULL); - if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; - - /* paste the newly painted canvas to the gimage which is being worked on */ - paint_core_paste_canvas (paint_core, drawable, - MIN (opacity, 255), - (int) (gimp_context_get_opacity (NULL) * 255), - gimp_context_get_paint_mode (NULL), - HARD, scale, paint_appl_mode); -} - -static gpointer -pencil_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - pencil_motion (paint_core, drawable, &non_gui_pressure_options, - non_gui_incremental); - - return NULL; -} - - -gboolean -pencil_non_gui (GimpDrawable *drawable, - int num_strokes, - double *stroke_array) -{ - int i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = pencil_non_gui_paint_func; - - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; - - pencil_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - return TRUE; - } - else - return FALSE; -} diff --git a/app/pencil.h b/app/pencil.h deleted file mode 100644 index 888d3832ea..0000000000 --- a/app/pencil.h +++ /dev/null @@ -1,31 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PENCIL_H__ -#define __PENCIL_H__ - - -gboolean pencil_non_gui (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array); - -Tool * tools_new_pencil (void); -void tools_free_pencil (Tool *tool); - - -#endif /* __PENCIL_H__ */ diff --git a/app/perspective_tool.c b/app/perspective_tool.c deleted file mode 100644 index e85daef5da..0000000000 --- a/app/perspective_tool.c +++ /dev/null @@ -1,325 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimpprogress.h" -#include "gimpui.h" -#include "info_dialog.h" -#include "perspective_tool.h" -#include "selection.h" -#include "tile_manager_pvt.h" -#include "tools.h" -#include "transform_core.h" -#include "transform_tool.h" -#include "undo.h" - -#include "libgimp/gimpintl.h" - - -/* forward function declarations */ -static TileManager * perspective_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state); -static void perspective_tool_recalc (Tool *tool, - GDisplay *gdisp); -static void perspective_tool_motion (Tool *tool, - GDisplay *gdisp); -static void perspective_info_update (Tool *tool); - - -/* storage for information dialog fields */ -static gchar matrix_row_buf [3][MAX_INFO_BUF]; - - -static TileManager * -perspective_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - switch (state) - { - case TRANSFORM_INIT: - if (!transform_info) - { - transform_info = - info_dialog_new (_("Perspective Transform Information"), - gimp_standard_help_func, - "tools/transform_perspective.html"); - info_dialog_add_label (transform_info, _("Matrix:"), - matrix_row_buf[0]); - info_dialog_add_label (transform_info, "", matrix_row_buf[1]); - info_dialog_add_label (transform_info, "", matrix_row_buf[2]); - } - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), TRUE); - - transform_core->trans_info [X0] = (double) transform_core->x1; - transform_core->trans_info [Y0] = (double) transform_core->y1; - transform_core->trans_info [X1] = (double) transform_core->x2; - transform_core->trans_info [Y1] = (double) transform_core->y1; - transform_core->trans_info [X2] = (double) transform_core->x1; - transform_core->trans_info [Y2] = (double) transform_core->y2; - transform_core->trans_info [X3] = (double) transform_core->x2; - transform_core->trans_info [Y3] = (double) transform_core->y2; - - return NULL; - break; - - case TRANSFORM_MOTION: - perspective_tool_motion (tool, gdisp); - perspective_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_RECALC: - perspective_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_FINISH: - /* Let the transform core handle the inverse mapping */ - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), FALSE); - return - perspective_tool_perspective (gdisp->gimage, - gimp_image_active_drawable (gdisp->gimage), - gdisp, - transform_core->original, - transform_tool_smoothing (), - transform_core->transform); - break; - } - - return NULL; -} - -Tool * -tools_new_perspective_tool (void) -{ - Tool *tool; - TransformCore *private; - - tool = transform_core_new (PERSPECTIVE, TRUE); - - private = tool->private; - - /* set the rotation specific transformation attributes */ - private->trans_func = perspective_tool_transform; - private->trans_info[X0] = 0; - private->trans_info[Y0] = 0; - private->trans_info[X1] = 0; - private->trans_info[Y1] = 0; - private->trans_info[X2] = 0; - private->trans_info[Y2] = 0; - private->trans_info[X3] = 0; - private->trans_info[Y3] = 0; - - /* assemble the transformation matrix */ - gimp_matrix3_identity (private->transform); - - return tool; -} - -void -tools_free_perspective_tool (Tool *tool) -{ - transform_core_free (tool); -} - -static void -perspective_info_update (Tool *tool) -{ - TransformCore *transform_core; - gint i; - - transform_core = (TransformCore *) tool->private; - - for (i = 0; i < 3; i++) - { - gchar *p = matrix_row_buf[i]; - gint j; - - for (j = 0; j < 3; j++) - { - p += g_snprintf (p, MAX_INFO_BUF - (p - matrix_row_buf[i]), - "%10.3g", transform_core->transform[i][j]); - } - } - - info_dialog_update (transform_info); - info_dialog_popup (transform_info); - - return; -} - -static void -perspective_tool_motion (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gint diff_x, diff_y; - - transform_core = (TransformCore *) tool->private; - - diff_x = transform_core->curx - transform_core->lastx; - diff_y = transform_core->cury - transform_core->lasty; - - switch (transform_core->function) - { - case TRANSFORM_HANDLE_1: - transform_core->trans_info [X0] += diff_x; - transform_core->trans_info [Y0] += diff_y; - break; - case TRANSFORM_HANDLE_2: - transform_core->trans_info [X1] += diff_x; - transform_core->trans_info [Y1] += diff_y; - break; - case TRANSFORM_HANDLE_3: - transform_core->trans_info [X2] += diff_x; - transform_core->trans_info [Y2] += diff_y; - break; - case TRANSFORM_HANDLE_4: - transform_core->trans_info [X3] += diff_x; - transform_core->trans_info [Y3] += diff_y; - break; - default: - break; - } -} - -static void -perspective_tool_recalc (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - GimpMatrix3 m; - gdouble cx, cy; - gdouble scalex, scaley; - - transform_core = (TransformCore *) tool->private; - - /* determine the perspective transform that maps from - * the unit cube to the trans_info coordinates - */ - perspective_find_transform (transform_core->trans_info, m); - - cx = transform_core->x1; - cy = transform_core->y1; - scalex = 1.0; - scaley = 1.0; - - if (transform_core->x2 - transform_core->x1) - scalex = 1.0 / (transform_core->x2 - transform_core->x1); - if (transform_core->y2 - transform_core->y1) - scaley = 1.0 / (transform_core->y2 - transform_core->y1); - - /* assemble the transformation matrix */ - gimp_matrix3_identity (transform_core->transform); - gimp_matrix3_translate (transform_core->transform, -cx, -cy); - gimp_matrix3_scale (transform_core->transform, scalex, scaley); - gimp_matrix3_mult (m, transform_core->transform); - - /* transform the bounding box */ - transform_core_transform_bounding_box (tool); - - /* update the information dialog */ - perspective_info_update (tool); -} - -void -perspective_find_transform (gdouble *coords, - GimpMatrix3 matrix) -{ - gdouble dx1, dx2, dx3, dy1, dy2, dy3; - gdouble det1, det2; - - dx1 = coords[X1] - coords[X3]; - dx2 = coords[X2] - coords[X3]; - dx3 = coords[X0] - coords[X1] + coords[X3] - coords[X2]; - - dy1 = coords[Y1] - coords[Y3]; - dy2 = coords[Y2] - coords[Y3]; - dy3 = coords[Y0] - coords[Y1] + coords[Y3] - coords[Y2]; - - /* Is the mapping affine? */ - if ((dx3 == 0.0) && (dy3 == 0.0)) - { - matrix[0][0] = coords[X1] - coords[X0]; - matrix[0][1] = coords[X3] - coords[X1]; - matrix[0][2] = coords[X0]; - matrix[1][0] = coords[Y1] - coords[Y0]; - matrix[1][1] = coords[Y3] - coords[Y1]; - matrix[1][2] = coords[Y0]; - matrix[2][0] = 0.0; - matrix[2][1] = 0.0; - } - else - { - det1 = dx3 * dy2 - dy3 * dx2; - det2 = dx1 * dy2 - dy1 * dx2; - matrix[2][0] = det1 / det2; - det1 = dx1 * dy3 - dy1 * dx3; - det2 = dx1 * dy2 - dy1 * dx2; - matrix[2][1] = det1 / det2; - - matrix[0][0] = coords[X1] - coords[X0] + matrix[2][0] * coords[X1]; - matrix[0][1] = coords[X2] - coords[X0] + matrix[2][1] * coords[X2]; - matrix[0][2] = coords[X0]; - - matrix[1][0] = coords[Y1] - coords[Y0] + matrix[2][0] * coords[Y1]; - matrix[1][1] = coords[Y2] - coords[Y0] + matrix[2][1] * coords[Y2]; - matrix[1][2] = coords[Y0]; - } - - matrix[2][2] = 1.0; -} - -TileManager * -perspective_tool_perspective (GImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix) -{ - GimpProgress *progress; - TileManager *ret; - - progress = progress_start (gdisp, _("Perspective..."), FALSE, NULL, NULL); - - ret = transform_core_do (gimage, drawable, float_tiles, - interpolation, matrix, - progress ? progress_update_and_flush : - (GimpProgressFunc) NULL, - progress); - - if (progress) - progress_end (progress); - - return ret; -} diff --git a/app/perspective_tool.h b/app/perspective_tool.h deleted file mode 100644 index 39f31518ab..0000000000 --- a/app/perspective_tool.h +++ /dev/null @@ -1,36 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PERSPECTIVE_TOOL_H__ -#define __PERSPECTIVE_TOOL_H__ - - -TileManager * perspective_tool_perspective (GimpImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix); -void perspective_find_transform (gdouble *coords, - GimpMatrix3 matrix); - -Tool * tools_new_perspective_tool (void); -void tools_free_perspective_tool (Tool *tool); - - -#endif /* __PERSPECTIVE_TOOL_H__ */ diff --git a/app/posterize.c b/app/posterize.c deleted file mode 100644 index 14d0b9b1db..0000000000 --- a/app/posterize.c +++ /dev/null @@ -1,402 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimpimage.h" -#include "gimplut.h" -#include "gimpui.h" -#include "image_map.h" -#include "lut_funcs.h" -#include "posterize.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpintl.h" - - -/* the posterize structures */ - -typedef struct _Posterize Posterize; - -struct _Posterize -{ - gint x, y; /* coords for last mouse click */ -}; - -typedef struct _PosterizeDialog PosterizeDialog; - -struct _PosterizeDialog -{ - GtkWidget *shell; - - GtkAdjustment *levels_data; - - GimpDrawable *drawable; - ImageMap image_map; - - gint levels; - - gboolean preview; - - GimpLut *lut; -}; - - -/* posterize action functions */ -static void posterize_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static PosterizeDialog * posterize_dialog_new (void); - -static void posterize_preview (PosterizeDialog *pd); -static void posterize_reset_callback (GtkWidget *widget, - gpointer data); -static void posterize_ok_callback (GtkWidget *widget, - gpointer data); -static void posterize_cancel_callback (GtkWidget *widget, - gpointer data); -static void posterize_preview_update (GtkWidget *widget, - gpointer data); -static void posterize_levels_adjustment_update (GtkAdjustment *adjustment, - gpointer data); - - -/* the posterize tool options */ -static ToolOptions *posterize_options = NULL; - -/* the posterize tool dialog */ -static PosterizeDialog *posterize_dialog = NULL; - - -/* posterize select action functions */ - -static void -posterize_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - posterize_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_posterize (void) -{ - Tool * tool; - Posterize * private; - - /* The tool options */ - if (! posterize_options) - { - posterize_options = tool_options_new (("Posterize")); - tools_register (POSTERIZE, posterize_options); - } - - tool = tools_new_tool (POSTERIZE); - private = g_new0 (Posterize, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = posterize_control; - - return tool; -} - -void -posterize_dialog_hide (void) -{ - if (posterize_dialog) - posterize_cancel_callback (NULL, (gpointer) posterize_dialog); -} - -void -tools_free_posterize (Tool *tool) -{ - Posterize * post; - - post = (Posterize *) tool->private; - - /* Close the posterize dialog */ - posterize_dialog_hide (); - - g_free (post); -} - -void -posterize_initialize (GDisplay *gdisp) -{ - if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Posterize does not operate on indexed drawables.")); - return; - } - - /* The posterize dialog */ - if (!posterize_dialog) - posterize_dialog = posterize_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (posterize_dialog->shell)) - gtk_widget_show (posterize_dialog->shell); - - posterize_dialog->levels = 3; - - posterize_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - posterize_dialog->image_map = - image_map_create (gdisp, posterize_dialog->drawable); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (posterize_dialog->levels_data), 3); - - if (posterize_dialog->preview) - posterize_preview (posterize_dialog); -} - -/**********************/ -/* Posterize dialog */ -/**********************/ - -static PosterizeDialog * -posterize_dialog_new (void) -{ - PosterizeDialog *pd; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *spinbutton; - GtkWidget *toggle; - GtkObject *data; - - pd = g_new (PosterizeDialog, 1); - pd->preview = TRUE; - pd->levels = 3; - pd->lut = gimp_lut_new (); - - /* The shell and main vbox */ - pd->shell = - gimp_dialog_new (_("Posterize"), "posterize", - tools_help_func, NULL, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), posterize_ok_callback, - pd, NULL, NULL, TRUE, FALSE, - _("Reset"), posterize_reset_callback, - pd, NULL, NULL, TRUE, FALSE, - _("Cancel"), posterize_cancel_callback, - pd, NULL, NULL, FALSE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 2); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (pd->shell)->vbox), vbox); - - /* Horizontal box for levels text widget */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Posterize Levels:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* levels spinbutton */ - data = gtk_adjustment_new (3, 2, 256, 1.0, 10.0, 0.0); - pd->levels_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (pd->levels_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (pd->levels_data), "value_changed", - GTK_SIGNAL_FUNC (posterize_levels_adjustment_update), - pd); - - gtk_widget_show (spinbutton); - gtk_widget_show (hbox); - - /* Horizontal box for preview */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* The preview toggle */ - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pd->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (posterize_preview_update), - pd); - - gtk_widget_show (label); - gtk_widget_show (toggle); - gtk_widget_show (hbox); - - gtk_widget_show (vbox); - gtk_widget_show (pd->shell); - - return pd; -} - -static void -posterize_preview (PosterizeDialog *pd) -{ - if (!pd->image_map) - { - g_warning ("posterize_preview(): No image map"); - return; - } - - active_tool->preserve = TRUE; - posterize_lut_setup (pd->lut, pd->levels, gimp_drawable_bytes (pd->drawable)); - image_map_apply (pd->image_map, (ImageMapApplyFunc) gimp_lut_process_2, - (void *) pd->lut); - active_tool->preserve = FALSE; -} - -static void -posterize_reset_callback (GtkWidget *widget, - gpointer data) -{ - PosterizeDialog *pd; - - pd = (PosterizeDialog *) data; - - gtk_adjustment_set_value (GTK_ADJUSTMENT (pd->levels_data), 3); -} - -static void -posterize_ok_callback (GtkWidget *widget, - gpointer data) -{ - PosterizeDialog *pd; - - pd = (PosterizeDialog *) data; - - gimp_dialog_hide (pd->shell); - - active_tool->preserve = TRUE; - - if (!pd->preview) - { - posterize_lut_setup( pd->lut, pd->levels, - gimp_drawable_bytes (pd->drawable)); - image_map_apply (pd->image_map, (ImageMapApplyFunc) gimp_lut_process_2, - (gpointer) pd->lut); - } - - if (pd->image_map) - image_map_commit (pd->image_map); - - active_tool->preserve = FALSE; - - pd->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -posterize_cancel_callback (GtkWidget *widget, - gpointer data) -{ - PosterizeDialog *pd; - - pd = (PosterizeDialog *) data; - - gimp_dialog_hide (pd->shell); - - if (pd->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (pd->image_map); - active_tool->preserve = FALSE; - - pd->image_map = NULL; - gdisplays_flush (); - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -posterize_preview_update (GtkWidget *widget, - gpointer data) -{ - PosterizeDialog *pd; - - pd = (PosterizeDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - pd->preview = TRUE; - posterize_preview (pd); - } - else - { - pd->preview = FALSE; - if (pd->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (pd->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } -} - -static void -posterize_levels_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - PosterizeDialog *pd; - - pd = (PosterizeDialog *) data; - - if (pd->levels != adjustment->value) - { - pd->levels = adjustment->value; - - if (pd->preview) - posterize_preview (pd); - } -} diff --git a/app/posterize.h b/app/posterize.h deleted file mode 100644 index 3b16c85bb4..0000000000 --- a/app/posterize.h +++ /dev/null @@ -1,30 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __POSTERIZE_H__ -#define __POSTERIZE_H__ - - -Tool * tools_new_posterize (void); -void tools_free_posterize (Tool *tool); - -void posterize_dialog_hide (void); -void posterize_initialize (GDisplay *gdisp); - - -#endif /* __POSTERIZE_H__ */ diff --git a/app/rect_select.c b/app/rect_select.c deleted file mode 100644 index f7e6e21845..0000000000 --- a/app/rect_select.c +++ /dev/null @@ -1,741 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "channel.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "edit_selection.h" -#include "floating_sel.h" -#include "rect_select.h" -#include "rect_selectP.h" -#include "selection_options.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpunitmenu.h" - -#include "libgimp/gimpintl.h" - - -#define STATUSBAR_SIZE 128 - - -extern void ellipse_select (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - SelectOps op, - gboolean antialias, - gboolean feather, - gdouble feather_radius); - -static void selection_tool_update_op_state (RectSelect *rect_sel, - gint x, - gint y, - gint state, - GDisplay *gdisp); - - -/* the rectangular selection tool options */ -static SelectionOptions *rect_options = NULL; - -/* in gimp, ellipses are rectangular, too ;) */ -extern SelectionOptions *ellipse_options; - - -/*************************************/ -/* Rectangular selection apparatus */ - -void -rect_select (GimpImage *gimage, - gint x, - gint y, - gint w, - gint h, - SelectOps op, - gboolean feather, - gdouble feather_radius) -{ - Channel *new_mask; - - /* if applicable, replace the current selection */ - if (op == SELECTION_REPLACE) - gimage_mask_clear (gimage); - else - gimage_mask_undo (gimage); - - /* if feathering for rect, make a new mask with the - * rectangle and feather that with the old mask - */ - if (feather) - { - new_mask = channel_new_mask (gimage, gimage->width, gimage->height); - channel_combine_rect (new_mask, CHANNEL_OP_ADD, x, y, w, h); - channel_feather (new_mask, gimp_image_get_mask (gimage), - feather_radius, - feather_radius, - op, 0, 0); - channel_delete (new_mask); - } - else if (op == SELECTION_INTERSECT) - { - new_mask = channel_new_mask (gimage, gimage->width, gimage->height); - channel_combine_rect (new_mask, CHANNEL_OP_ADD, x, y, w, h); - channel_combine_mask (gimp_image_get_mask (gimage), new_mask, op, 0, 0); - channel_delete (new_mask); - } - else - channel_combine_rect (gimp_image_get_mask (gimage), op, x, y, w, h); -} - -void -rect_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - gchar select_mode[STATUSBAR_SIZE]; - gint x, y; - GimpUnit unit = GIMP_UNIT_PIXEL; - gdouble unit_factor; - - rect_sel = (RectSelect *) tool->private; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0); - - rect_sel->x = x; - rect_sel->y = y; - switch (tool->type) - { - case RECT_SELECT: - rect_sel->fixed_size = rect_options->fixed_size; - rect_sel->fixed_width = rect_options->fixed_width; - rect_sel->fixed_height = rect_options->fixed_height; - unit = rect_options->fixed_unit; - break; - case ELLIPSE_SELECT: - rect_sel->fixed_size = ellipse_options->fixed_size; - rect_sel->fixed_width = ellipse_options->fixed_width; - rect_sel->fixed_height = ellipse_options->fixed_height; - unit = ellipse_options->fixed_unit; - break; - default: - break; - } - - switch (unit) - { - case GIMP_UNIT_PIXEL: - break; - case GIMP_UNIT_PERCENT: - rect_sel->fixed_width = - gdisp->gimage->width * rect_sel->fixed_width / 100; - rect_sel->fixed_height = - gdisp->gimage->height * rect_sel->fixed_height / 100; - break; - default: - unit_factor = gimp_unit_get_factor (unit); - rect_sel->fixed_width = - rect_sel->fixed_width * gdisp->gimage->xresolution / unit_factor; - rect_sel->fixed_height = - rect_sel->fixed_height * gdisp->gimage->yresolution / unit_factor; - break; - } - - rect_sel->fixed_width = MAX (1, rect_sel->fixed_width); - rect_sel->fixed_height = MAX (1, rect_sel->fixed_height); - - rect_sel->w = 0; - rect_sel->h = 0; - - rect_sel->center = FALSE; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - switch (rect_sel->op) - { - case SELECTION_MOVE_MASK: - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE); - return; - case SELECTION_MOVE: - init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE); - return; - default: - break; - } - - /* initialize the statusbar display */ - rect_sel->context_id = - gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "selection"); - switch (rect_sel->op) - { - case SELECTION_ADD: - g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: ADD")); - break; - case SELECTION_SUB: - g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: SUBTRACT")); - break; - case SELECTION_INTERSECT: - g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: INTERSECT")); - break; - case SELECTION_REPLACE: - g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: REPLACE")); - break; - default: - break; - } - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - rect_sel->context_id, select_mode); - - draw_core_start (rect_sel->core, gdisp->canvas->window, tool); -} - -void -rect_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - gint x1, y1; - gint x2, y2; - gint w, h; - - rect_sel = (RectSelect *) tool->private; - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id); - - draw_core_stop (rect_sel->core, tool); - tool->state = INACTIVE; - - /* First take care of the case where the user "cancels" the action */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - x1 = (rect_sel->w < 0) ? rect_sel->x + rect_sel->w : rect_sel->x; - y1 = (rect_sel->h < 0) ? rect_sel->y + rect_sel->h : rect_sel->y; - w = (rect_sel->w < 0) ? -rect_sel->w : rect_sel->w; - h = (rect_sel->h < 0) ? -rect_sel->h : rect_sel->h; - - if ((!w || !h) && !rect_sel->fixed_size) - { - /* If there is a floating selection, anchor it */ - if (gimp_image_floating_sel (gdisp->gimage)) - floating_sel_anchor (gimp_image_floating_sel (gdisp->gimage)); - /* Otherwise, clear the selection mask */ - else - gimage_mask_clear (gdisp->gimage); - - gdisplays_flush (); - return; - } - - x2 = x1 + w; - y2 = y1 + h; - - switch (tool->type) - { - case RECT_SELECT: - rect_select (gdisp->gimage, - x1, y1, (x2 - x1), (y2 - y1), - rect_sel->op, - rect_options->feather, - rect_options->feather_radius); - break; - - case ELLIPSE_SELECT: - ellipse_select (gdisp->gimage, - x1, y1, (x2 - x1), (y2 - y1), - rect_sel->op, - ellipse_options->antialias, - ellipse_options->feather, - ellipse_options->feather_radius); - break; - default: - break; - } - - /* show selection on all views */ - gdisplays_flush (); - } -} - -void -rect_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - gchar size[STATUSBAR_SIZE]; - gint ox, oy; - gint x, y; - gint w, h, s; - gint tw, th; - gdouble ratio; - - rect_sel = (RectSelect *) tool->private; - - /* needed for immediate cursor update on modifier event */ - rect_sel->current_x = mevent->x; - rect_sel->current_y = mevent->y; - - if (tool->state != ACTIVE) - return; - - if (rect_sel->op == SELECTION_ANCHOR) - { - rect_sel->op = SELECTION_REPLACE; - - rect_select_cursor_update (tool, mevent, gdisp); - } - - draw_core_pause (rect_sel->core, tool); - - /* Calculate starting point */ - - if (rect_sel->center) - { - ox = rect_sel->x + rect_sel->w / 2; - oy = rect_sel->y + rect_sel->h / 2; - } - else - { - ox = rect_sel->x; - oy = rect_sel->y; - } - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0); - if (rect_sel->fixed_size) - { - if (mevent->state & GDK_SHIFT_MASK) - { - ratio = (double)(rect_sel->fixed_height / - (double)rect_sel->fixed_width); - tw = x - ox; - th = y - oy; - /* - * This is probably an inefficient way to do it, but it gives - * nicer, more predictable results than the original agorithm - */ - - if ((abs(th) < (ratio * abs(tw))) && (abs(tw) > (abs(th) / ratio))) - { - w = tw; - h = (int)(tw * ratio); - /* h should have the sign of th */ - if ((th < 0 && h > 0) || (th > 0 && h < 0)) - h = -h; - } - else - { - h = th; - w = (int)(th / ratio); - /* w should have the sign of tw */ - if ((tw < 0 && w > 0) || (tw > 0 && w < 0)) - w = -w; - } - } - else - { - w = (x - ox > 0 ? rect_sel->fixed_width : -rect_sel->fixed_width); - h = (y - oy > 0 ? rect_sel->fixed_height : -rect_sel->fixed_height); - } - } - else - { - w = (x - ox); - h = (y - oy); - } - - /* If the shift key is down, then make the rectangle square (or ellipse circular) */ - if ((mevent->state & GDK_SHIFT_MASK) && !rect_sel->fixed_size) - { - s = MAX (abs (w), abs (h)); - - if (w < 0) - w = -s; - else - w = s; - - if (h < 0) - h = -s; - else - h = s; - } - - /* If the control key is down, create the selection from the center out */ - if (mevent->state & GDK_CONTROL_MASK) - { - if (rect_sel->fixed_size) - { - if (mevent->state & GDK_SHIFT_MASK) - { - rect_sel->x = ox - w; - rect_sel->y = oy - h; - rect_sel->w = w * 2; - rect_sel->h = h * 2; - } - else - { - rect_sel->x = ox - w / 2; - rect_sel->y = oy - h / 2; - rect_sel->w = w; - rect_sel->h = h; - } - } - else - { - w = abs(w); - h = abs(h); - - rect_sel->x = ox - w; - rect_sel->y = oy - h; - rect_sel->w = 2 * w + 1; - rect_sel->h = 2 * h + 1; - } - rect_sel->center = TRUE; - } - else - { - rect_sel->x = ox; - rect_sel->y = oy; - rect_sel->w = w; - rect_sel->h = h; - - rect_sel->center = FALSE; - } - - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id); - if (gdisp->dot_for_dot) - { - g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str, - _("Selection: "), abs(rect_sel->w), " x ", abs(rect_sel->h)); - } - else /* show real world units */ - { - gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit); - - g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str, - _("Selection: "), - (gdouble) abs(rect_sel->w) * unit_factor / - gdisp->gimage->xresolution, - " x ", - (gdouble) abs(rect_sel->h) * unit_factor / - gdisp->gimage->yresolution); - } - gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id, - size); - - draw_core_resume (rect_sel->core, tool); -} - -void -rect_select_draw (Tool *tool) -{ - RectSelect *rect_sel; - gint x1, y1; - gint x2, y2; - - rect_sel = (RectSelect *) tool->private; - - x1 = MIN (rect_sel->x, rect_sel->x + rect_sel->w); - y1 = MIN (rect_sel->y, rect_sel->y + rect_sel->h); - x2 = MAX (rect_sel->x, rect_sel->x + rect_sel->w); - y2 = MAX (rect_sel->y, rect_sel->y + rect_sel->h); - - gdisplay_transform_coords (tool->gdisp, x1, y1, &x1, &y1, 0); - gdisplay_transform_coords (tool->gdisp, x2, y2, &x2, &y2, 0); - - gdk_draw_rectangle (rect_sel->core->win, - rect_sel->core->gc, 0, - x1, y1, (x2 - x1), (y2 - y1)); -} - -static void -selection_tool_update_op_state (RectSelect *rect_sel, - gint x, - gint y, - gint state, - GDisplay *gdisp) -{ - Layer *layer; - Layer *floating_sel; - gint tx, ty; - - if (active_tool->state == ACTIVE) - return; - - gdisplay_untransform_coords (gdisp, x, y, &tx, &ty, FALSE, FALSE); - - layer = gimp_image_pick_correlate_layer (gdisp->gimage, tx, ty); - floating_sel = gimp_image_floating_sel (gdisp->gimage); - - if (state & GDK_MOD1_MASK && - !gimage_mask_is_empty (gdisp->gimage)) - { - rect_sel->op = SELECTION_MOVE_MASK; /* move just the selection mask */ - } - else if (!(state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) && - layer && - (layer == floating_sel || - (gdisplay_mask_value (gdisp, x, y) && - floating_sel == NULL))) - { - rect_sel->op = SELECTION_MOVE; /* move the selection */ - } - else if ((state & GDK_SHIFT_MASK) && - !(state & GDK_CONTROL_MASK)) - { - rect_sel->op = SELECTION_ADD; /* add to the selection */ - } - else if ((state & GDK_CONTROL_MASK) && - !(state & GDK_SHIFT_MASK)) - { - rect_sel->op = SELECTION_SUB; /* subtract from the selection */ - } - else if ((state & GDK_CONTROL_MASK) && - (state & GDK_SHIFT_MASK)) - { - rect_sel->op = SELECTION_INTERSECT; /* intersect with selection */ - } - else if (floating_sel) - { - rect_sel->op = SELECTION_ANCHOR; /* anchor the selection */ - } - else - { - rect_sel->op = SELECTION_REPLACE; /* replace the selection */ - } -} - -void -rect_select_oper_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - - rect_sel = (RectSelect *) tool->private; - - rect_sel->current_x = mevent->x; - rect_sel->current_y = mevent->y; - - selection_tool_update_op_state (rect_sel, - rect_sel->current_x, - rect_sel->current_y, - mevent->state, gdisp); -} - -void -rect_select_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - gint state; - - state = kevent->state; - - switch (kevent->keyval) - { - case GDK_Alt_L: case GDK_Alt_R: - if (state & GDK_MOD1_MASK) - state &= ~GDK_MOD1_MASK; - else - state |= GDK_MOD1_MASK; - break; - - case GDK_Shift_L: case GDK_Shift_R: - if (state & GDK_SHIFT_MASK) - state &= ~GDK_SHIFT_MASK; - else - state |= GDK_SHIFT_MASK; - break; - - case GDK_Control_L: case GDK_Control_R: - if (state & GDK_CONTROL_MASK) - state &= ~GDK_CONTROL_MASK; - else - state |= GDK_CONTROL_MASK; - break; - } - - rect_sel = (RectSelect *) tool->private; - selection_tool_update_op_state (rect_sel, - rect_sel->current_x, - rect_sel->current_y, - state, gdisp); -} - -void -rect_select_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - - rect_sel = (RectSelect *) tool->private; - - switch (rect_sel->op) - { - case SELECTION_ADD: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - tool->type, - CURSOR_MODIFIER_PLUS, - FALSE); - break; - case SELECTION_SUB: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - tool->type, - CURSOR_MODIFIER_MINUS, - FALSE); - break; - case SELECTION_INTERSECT: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - tool->type, - CURSOR_MODIFIER_INTERSECT, - FALSE); - break; - case SELECTION_REPLACE: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - tool->type, - CURSOR_MODIFIER_NONE, - FALSE); - break; - case SELECTION_MOVE_MASK: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - tool->type, - CURSOR_MODIFIER_MOVE, - FALSE); - break; - case SELECTION_MOVE: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - MOVE, - CURSOR_MODIFIER_NONE, - FALSE); - break; - case SELECTION_ANCHOR: - gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR, - tool->type, - CURSOR_MODIFIER_ANCHOR, - FALSE); - break; - } -} - -void -rect_select_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - RectSelect *rect_sel; - - rect_sel = (RectSelect *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (rect_sel->core, tool); - break; - - case RESUME: - draw_core_resume (rect_sel->core, tool); - break; - - case HALT: - draw_core_stop (rect_sel->core, tool); - break; - - default: - break; - } -} - -static void -rect_select_options_reset (void) -{ - selection_options_reset (rect_options); -} - -Tool * -tools_new_rect_select (void) -{ - Tool * tool; - RectSelect * private; - - /* The tool options */ - if (! rect_options) - { - rect_options = - selection_options_new (RECT_SELECT, rect_select_options_reset); - tools_register (RECT_SELECT, (ToolOptions *) rect_options); - } - - tool = tools_new_tool (RECT_SELECT); - private = g_new0 (RectSelect, 1); - - private->core = draw_core_new (rect_select_draw); - private->x = private->y = 0; - private->w = private->h = 0; - private->op = SELECTION_REPLACE; - - tool->private = (void *) private; - - tool->button_press_func = rect_select_button_press; - tool->button_release_func = rect_select_button_release; - tool->motion_func = rect_select_motion; - tool->modifier_key_func = rect_select_modifier_update; - tool->cursor_update_func = rect_select_cursor_update; - tool->oper_update_func = rect_select_oper_update; - tool->control_func = rect_select_control; - - return tool; -} - -void -tools_free_rect_select (Tool *tool) -{ - RectSelect * rect_sel; - - rect_sel = (RectSelect *) tool->private; - - draw_core_free (rect_sel->core); - g_free (rect_sel); -} diff --git a/app/rect_select.h b/app/rect_select.h deleted file mode 100644 index 4ea51d7378..0000000000 --- a/app/rect_select.h +++ /dev/null @@ -1,61 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __RECT_SELECT_H__ -#define __RECT_SELECT_H__ - - -/* rect select action functions */ -void rect_select_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -void rect_select_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -void rect_select_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -void rect_select_modifier_update (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -void rect_select_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -void rect_select_oper_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -void rect_select_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -/* rect select functions */ -void rect_select_draw (Tool *tool); -void rect_select (GimpImage *gimage, - gint x, - gint y, - gint w, - gint g, - SelectOps op, - gboolean feather, - gdouble feather_radius); - -Tool * tools_new_rect_select (void); -void tools_free_rect_select (Tool *tool); - - -#endif /* __RECT_SELECT_H__ */ diff --git a/app/rect_selectP.h b/app/rect_selectP.h deleted file mode 100644 index cce1e57051..0000000000 --- a/app/rect_selectP.h +++ /dev/null @@ -1,47 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __RECT_SELECTP_H__ -#define __RECT_SELECTP_H__ - - -typedef struct _RectSelect RectSelect, EllipseSelect; - -struct _RectSelect -{ - DrawCore *core; /* Core select object */ - - SelectOps op; /* selection operation (SELECTION_ADD etc.) */ - - gint current_x; /* these values are updated on every motion event */ - gint current_y; /* (enables immediate cursor updating on modifier - * key events). */ - - gint x, y; /* upper left hand coordinate */ - gint w, h; /* width and height */ - gint center; /* is the selection being created from the - * center out? */ - - gint fixed_size; - gdouble fixed_width; - gdouble fixed_height; - guint context_id; /* for the statusbar */ -}; - - -#endif /* __RECT_SELECTP_H__ */ diff --git a/app/rotate_tool.c b/app/rotate_tool.c deleted file mode 100644 index 7904d828bc..0000000000 --- a/app/rotate_tool.c +++ /dev/null @@ -1,417 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimpprogress.h" -#include "gimpui.h" -#include "info_dialog.h" -#include "rotate_tool.h" -#include "selection.h" -#include "tile_manager_pvt.h" -#include "tools.h" -#include "tool_options.h" -#include "transform_core.h" -#include "transform_tool.h" -#include "undo.h" - -#include "libgimp/gimpsizeentry.h" -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* index into trans_info array */ -#define ANGLE 0 -#define REAL_ANGLE 1 -#define CENTER_X 2 -#define CENTER_Y 3 - -#define EPSILON 0.018 /* ~ 1 degree */ -#define FIFTEEN_DEG (G_PI / 12.0) - - -/* forward function declarations */ -static TileManager * rotate_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state); - -static void rotate_tool_recalc (Tool *tool, - GDisplay *gdisp); -static void rotate_tool_motion (Tool *tool, - GDisplay *gdisp); -static void rotate_info_update (Tool *tool); - -static void rotate_angle_changed (GtkWidget *entry, - gpointer data); -static void rotate_center_changed (GtkWidget *entry, - gpointer data); - - -/* variables local to this file */ -static gdouble angle_val; -static gdouble center_vals[2]; - -/* needed for size update */ -static GtkWidget *sizeentry = NULL; - - -static TileManager * -rotate_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state) -{ - TransformCore *transform_core; - GtkWidget *widget; - GtkWidget *spinbutton2; - - transform_core = (TransformCore *) tool->private; - - switch (state) - { - case TRANSFORM_INIT: - angle_val = 0.0; - center_vals[0] = transform_core->cx; - center_vals[1] = transform_core->cy; - - if (!transform_info) - { - transform_info = info_dialog_new (_("Rotation Information"), - gimp_standard_help_func, - "tools/transform_rotate.html"); - - widget = - info_dialog_add_spinbutton (transform_info, _("Angle:"), - &angle_val, - -180, 180, 1, 15, 1, 1, 2, - (GtkSignalFunc) rotate_angle_changed, - tool); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (widget), TRUE); - - /* this looks strange (-180, 181), but it works */ - widget = info_dialog_add_scale (transform_info, "", &angle_val, - -180, 181, 0.01, 0.1, 1, -1, - (GtkSignalFunc) rotate_angle_changed, - tool); - gtk_widget_set_usize (widget, 180, 0); - - spinbutton2 = - info_dialog_add_spinbutton (transform_info, _("Center X:"), NULL, - -1, 1, 1, 10, 1, 1, 2, NULL, NULL); - sizeentry = - info_dialog_add_sizeentry (transform_info, _("Y:"), - center_vals, 1, - gdisp->gimage->unit, "%a", - TRUE, TRUE, FALSE, - GIMP_SIZE_ENTRY_UPDATE_SIZE, - rotate_center_changed, tool); - - gimp_size_entry_add_field (GIMP_SIZE_ENTRY (sizeentry), - GTK_SPIN_BUTTON (spinbutton2), NULL); - - gtk_table_set_row_spacing (GTK_TABLE (transform_info->info_table), - 1, 6); - gtk_table_set_row_spacing (GTK_TABLE (transform_info->info_table), - 2, 0); - } - - gtk_signal_handler_block_by_data (GTK_OBJECT (sizeentry), tool); - - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), - gdisp->gimage->unit); - if (gdisp->dot_for_dot) - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), GIMP_UNIT_PIXEL); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0, - gdisp->gimage->xresolution, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 1, - gdisp->gimage->yresolution, FALSE); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0, - -65536, - 65536 + gdisp->gimage->width); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 1, - -65536, - 65536 + gdisp->gimage->height); - - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (sizeentry), 0, - transform_core->x1, transform_core->x2); - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (sizeentry), 1, - transform_core->y1, transform_core->y2); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, - center_vals[0]); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 1, - center_vals[1]); - - gtk_widget_set_sensitive (transform_info->shell, TRUE); - - gtk_signal_handler_unblock_by_data (GTK_OBJECT (sizeentry), tool); - - transform_core->trans_info[ANGLE] = angle_val; - transform_core->trans_info[REAL_ANGLE] = angle_val; - transform_core->trans_info[CENTER_X] = center_vals[0]; - transform_core->trans_info[CENTER_Y] = center_vals[1]; - - return NULL; - break; - - case TRANSFORM_MOTION: - rotate_tool_motion (tool, gdisp); - rotate_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_RECALC: - rotate_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_FINISH: - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), FALSE); - return rotate_tool_rotate (gdisp->gimage, - gimp_image_active_drawable (gdisp->gimage), - gdisp, - transform_core->trans_info[ANGLE], - transform_core->original, - transform_tool_smoothing (), - transform_core->transform); - break; - } - - return NULL; -} - -Tool * -tools_new_rotate_tool (void) -{ - Tool *tool; - TransformCore *private; - - tool = transform_core_new (ROTATE, TRUE); - - private = tool->private; - - /* set the rotation specific transformation attributes */ - private->trans_func = rotate_tool_transform; - private->trans_info[ANGLE] = 0.0; - private->trans_info[REAL_ANGLE] = 0.0; - private->trans_info[CENTER_X] = 0.0; - private->trans_info[CENTER_Y] = 0.0; - - /* assemble the transformation matrix */ - gimp_matrix3_identity (private->transform); - - return tool; -} - -void -tools_free_rotate_tool (Tool *tool) -{ - transform_core_free (tool); -} - -static void -rotate_info_update (Tool *tool) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - angle_val = gimp_rad_to_deg (transform_core->trans_info[ANGLE]); - center_vals[0] = transform_core->cx; - center_vals[1] = transform_core->cy; - - info_dialog_update (transform_info); - info_dialog_popup (transform_info); -} - -static void -rotate_angle_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - TransformCore *transform_core; - gdouble value; - - tool = (Tool *) data; - - if (tool) - { - transform_core = (TransformCore *) tool->private; - - value = gimp_deg_to_rad (GTK_ADJUSTMENT (widget)->value); - - if (value != transform_core->trans_info[ANGLE]) - { - draw_core_pause (transform_core->core, tool); - transform_core->trans_info[ANGLE] = value; - rotate_tool_recalc (tool, tool->gdisp); - draw_core_resume (transform_core->core, tool); - } - } -} - -static void -rotate_center_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - TransformCore *transform_core; - gint cx; - gint cy; - - tool = (Tool *) data; - - if (tool) - { - transform_core = (TransformCore *) tool->private; - - cx = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0)); - cy = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1)); - - if ((cx != transform_core->cx) || - (cy != transform_core->cy)) - { - draw_core_pause (transform_core->core, tool); - transform_core->cx = cx; - transform_core->cy = cy; - rotate_tool_recalc (tool, tool->gdisp); - draw_core_resume (transform_core->core, tool); - } - } -} - -static void -rotate_tool_motion (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gdouble angle1, angle2, angle; - gdouble cx, cy; - gdouble x1, y1, x2, y2; - - transform_core = (TransformCore *) tool->private; - - if (transform_core->function == TRANSFORM_HANDLE_CENTER) - { - transform_core->cx = transform_core->curx; - transform_core->cy = transform_core->cury; - - return; - } - - cx = transform_core->cx; - cy = transform_core->cy; - - x1 = transform_core->curx - cx; - x2 = transform_core->lastx - cx; - y1 = cy - transform_core->cury; - y2 = cy - transform_core->lasty; - - /* find the first angle */ - angle1 = atan2 (y1, x1); - - /* find the angle */ - angle2 = atan2 (y2, x2); - - angle = angle2 - angle1; - - if (angle > G_PI || angle < -G_PI) - angle = angle2 - ((angle1 < 0) ? 2.0 * G_PI + angle1 : angle1 - 2.0 * G_PI); - - /* increment the transform tool's angle */ - transform_core->trans_info[REAL_ANGLE] += angle; - - /* limit the angle to between 0 and 360 degrees */ - if (transform_core->trans_info[REAL_ANGLE] < - G_PI) - transform_core->trans_info[REAL_ANGLE] = - 2.0 * G_PI - transform_core->trans_info[REAL_ANGLE]; - else if (transform_core->trans_info[REAL_ANGLE] > G_PI) - transform_core->trans_info[REAL_ANGLE] = - transform_core->trans_info[REAL_ANGLE] - 2.0 * G_PI; - - /* constrain the angle to 15-degree multiples if ctrl is held down */ - if (transform_core->state & GDK_CONTROL_MASK) - transform_core->trans_info[ANGLE] = - FIFTEEN_DEG * (int) ((transform_core->trans_info[REAL_ANGLE] + - FIFTEEN_DEG / 2.0) / - FIFTEEN_DEG); - else - transform_core->trans_info[ANGLE] = transform_core->trans_info[REAL_ANGLE]; -} - -static void -rotate_tool_recalc (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gdouble cx, cy; - - transform_core = (TransformCore *) tool->private; - - cx = transform_core->cx; - cy = transform_core->cy; - - /* assemble the transformation matrix */ - gimp_matrix3_identity (transform_core->transform); - gimp_matrix3_translate (transform_core->transform, -cx, -cy); - gimp_matrix3_rotate (transform_core->transform, - transform_core->trans_info[ANGLE]); - gimp_matrix3_translate (transform_core->transform, +cx, +cy); - - /* transform the bounding box */ - transform_core_transform_bounding_box (tool); - - /* update the information dialog */ - rotate_info_update (tool); -} - -TileManager * -rotate_tool_rotate (GImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - gdouble angle, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix) -{ - GimpProgress *progress; - TileManager *ret; - - progress = progress_start (gdisp, _("Rotating..."), FALSE, NULL, NULL); - - ret = transform_core_do (gimage, drawable, float_tiles, - interpolation, matrix, - progress ? progress_update_and_flush : - (GimpProgressFunc) NULL, - progress); - - if (progress) - progress_end (progress); - - return ret; -} diff --git a/app/rotate_tool.h b/app/rotate_tool.h deleted file mode 100644 index 1411efe643..0000000000 --- a/app/rotate_tool.h +++ /dev/null @@ -1,35 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __ROTATE_TOOL_H__ -#define __ROTATE_TOOL_H__ - - -TileManager * rotate_tool_rotate (GimpImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - gdouble angle, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix); - -Tool * tools_new_rotate_tool (void); -void tools_free_rotate_tool (Tool *tool); - - -#endif /* __ROTATE_TOOL_H__ */ diff --git a/app/scale.c b/app/scale.c index f1d8c5763c..a88a56fc53 100644 --- a/app/scale.c +++ b/app/scale.c @@ -31,7 +31,8 @@ #include "gimprc.h" #include "nav_window.h" #include "scale.h" -#include "tools.h" + +#include "tools/tools.h" void diff --git a/app/scale_tool.c b/app/scale_tool.c deleted file mode 100644 index 8570557e8d..0000000000 --- a/app/scale_tool.c +++ /dev/null @@ -1,527 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimpprogress.h" -#include "gimpui.h" -#include "info_dialog.h" -#include "scale_tool.h" -#include "selection.h" -#include "tools.h" -#include "tool_options.h" -#include "transform_core.h" -#include "transform_tool.h" -#include "undo.h" - -#include "tile_manager_pvt.h" - -#include "libgimp/gimpmath.h" -#include "libgimp/gimplimits.h" -#include "libgimp/gimpintl.h" - - -/* forward function declarations */ -static TileManager * scale_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state); - -static void scale_tool_recalc (Tool *tool, - GDisplay *gdisp); -static void scale_tool_motion (Tool *tool, - GDisplay *gdisp); -static void scale_info_update (Tool *tool); - -static void scale_size_changed (GtkWidget *widget, - gpointer data); -static void scale_unit_changed (GtkWidget *widget, - gpointer data); - - -/* storage for information dialog fields */ -static gchar orig_width_buf[MAX_INFO_BUF]; -static gchar orig_height_buf[MAX_INFO_BUF]; -static gdouble size_vals[2]; -static gchar x_ratio_buf[MAX_INFO_BUF]; -static gchar y_ratio_buf[MAX_INFO_BUF]; - -/* needed for original size unit update */ -static GtkWidget *sizeentry = NULL; - - -static TileManager * -scale_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state) -{ - TransformCore *transform_core; - GtkWidget *spinbutton; - - transform_core = (TransformCore *) tool->private; - - switch (state) - { - case TRANSFORM_INIT: - size_vals[0] = transform_core->x2 - transform_core->x1; - size_vals[1] = transform_core->y2 - transform_core->y1; - - if (!transform_info) - { - transform_info = info_dialog_new (_("Scaling Information"), - gimp_standard_help_func, - "tools/transform_scale.html"); - - info_dialog_add_label (transform_info, _("Original Width:"), - orig_width_buf); - info_dialog_add_label (transform_info, _("Height:"), - orig_height_buf); - - spinbutton = - info_dialog_add_spinbutton (transform_info, _("Current Width:"), - NULL, -1, 1, 1, 10, 1, 1, 2, NULL, NULL); - sizeentry = - info_dialog_add_sizeentry (transform_info, _("Height:"), - size_vals, 1, - gdisp->gimage->unit, "%a", - TRUE, TRUE, FALSE, - GIMP_SIZE_ENTRY_UPDATE_SIZE, - scale_size_changed, tool); - gtk_signal_connect (GTK_OBJECT (sizeentry), "unit_changed", - scale_unit_changed, tool); - - gimp_size_entry_add_field (GIMP_SIZE_ENTRY (sizeentry), - GTK_SPIN_BUTTON (spinbutton), NULL); - - info_dialog_add_label (transform_info, _("Scale Ratio X:"), - x_ratio_buf); - info_dialog_add_label (transform_info, _("Y:"), - y_ratio_buf); - - gtk_table_set_row_spacing (GTK_TABLE (transform_info->info_table), - 1, 4); - gtk_table_set_row_spacing (GTK_TABLE (transform_info->info_table), - 2, 0); - } - - gtk_signal_handler_block_by_data (GTK_OBJECT (sizeentry), tool); - - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), - gdisp->gimage->unit); - if (gdisp->dot_for_dot) - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (sizeentry), GIMP_UNIT_PIXEL); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 0, - gdisp->gimage->xresolution, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (sizeentry), 1, - gdisp->gimage->yresolution, FALSE); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 0, - GIMP_MIN_IMAGE_SIZE, - GIMP_MAX_IMAGE_SIZE); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (sizeentry), 1, - GIMP_MIN_IMAGE_SIZE, - GIMP_MAX_IMAGE_SIZE); - - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (sizeentry), 0, - 0, size_vals[0]); - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (sizeentry), 1, - 0, size_vals[1]); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 0, - size_vals[0]); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (sizeentry), 1, - size_vals[1]); - - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), TRUE); - - gtk_signal_handler_unblock_by_data (GTK_OBJECT (sizeentry), tool); - - transform_core->trans_info [X0] = (double) transform_core->x1; - transform_core->trans_info [Y0] = (double) transform_core->y1; - transform_core->trans_info [X1] = (double) transform_core->x2; - transform_core->trans_info [Y1] = (double) transform_core->y2; - - return NULL; - break; - - case TRANSFORM_MOTION: - scale_tool_motion (tool, gdisp); - scale_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_RECALC: - scale_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_FINISH: - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), FALSE); - return scale_tool_scale (gdisp->gimage, - gimp_image_active_drawable (gdisp->gimage), - gdisp, - transform_core->trans_info, - transform_core->original, - transform_tool_smoothing (), - transform_core->transform); - break; - } - - return NULL; -} - -Tool * -tools_new_scale_tool (void) -{ - Tool *tool; - TransformCore *private; - - tool = transform_core_new (SCALE, TRUE); - - private = tool->private; - - /* set the scale specific transformation attributes */ - private->trans_func = scale_tool_transform; - private->trans_info[X0] = 0.0; - private->trans_info[Y0] = 0.0; - private->trans_info[X1] = 0.0; - private->trans_info[Y1] = 0.0; - - /* assemble the transformation matrix */ - gimp_matrix3_identity (private->transform); - - return tool; -} - -void -tools_free_scale_tool (Tool *tool) -{ - transform_core_free (tool); -} - -static void -scale_info_update (Tool *tool) -{ - TransformCore *transform_core; - gdouble ratio_x, ratio_y; - gint x1, y1, x2, y2, x3, y3, x4, y4; - GimpUnit unit; - gdouble unit_factor; - gchar format_buf[16]; - - static GimpUnit label_unit = GIMP_UNIT_PIXEL; - - transform_core = (TransformCore *) tool->private; - unit = gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (sizeentry));; - - /* Find original sizes */ - x1 = transform_core->x1; - y1 = transform_core->y1; - x2 = transform_core->x2; - y2 = transform_core->y2; - - if (unit != GIMP_UNIT_PERCENT) - label_unit = unit; - - unit_factor = gimp_unit_get_factor (label_unit); - - if (label_unit) /* unit != GIMP_UNIT_PIXEL */ - { - g_snprintf (format_buf, sizeof (format_buf), "%%.%df %s", - gimp_unit_get_digits (label_unit) + 1, - gimp_unit_get_symbol (label_unit)); - g_snprintf (orig_width_buf, MAX_INFO_BUF, format_buf, - (x2 - x1) * unit_factor / tool->gdisp->gimage->xresolution); - g_snprintf (orig_height_buf, MAX_INFO_BUF, format_buf, - (y2 - y1) * unit_factor / tool->gdisp->gimage->yresolution); - } - else /* unit == GIMP_UNIT_PIXEL */ - { - g_snprintf (orig_width_buf, MAX_INFO_BUF, "%d", x2 - x1); - g_snprintf (orig_height_buf, MAX_INFO_BUF, "%d", y2 - y1); - } - - /* Find current sizes */ - x3 = (int) transform_core->trans_info [X0]; - y3 = (int) transform_core->trans_info [Y0]; - x4 = (int) transform_core->trans_info [X1]; - y4 = (int) transform_core->trans_info [Y1]; - - size_vals[0] = x4 - x3; - size_vals[1] = y4 - y3; - - ratio_x = ratio_y = 0.0; - - if (x2 - x1) - ratio_x = (double) (x4 - x3) / (double) (x2 - x1); - if (y2 - y1) - ratio_y = (double) (y4 - y3) / (double) (y2 - y1); - - g_snprintf (x_ratio_buf, MAX_INFO_BUF, "%0.2f", ratio_x); - g_snprintf (y_ratio_buf, MAX_INFO_BUF, "%0.2f", ratio_y); - - info_dialog_update (transform_info); - info_dialog_popup (transform_info); -} - -static void -scale_size_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - TransformCore *transform_core; - gint width; - gint height; - - tool = (Tool *)data; - - if (tool) - { - transform_core = (TransformCore *) tool->private; - - width = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0)); - height = RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1)); - - if ((width != (transform_core->trans_info[X1] - - transform_core->trans_info[X0])) || - (height != (transform_core->trans_info[Y1] - - transform_core->trans_info[Y0]))) - { - draw_core_pause (transform_core->core, tool); - transform_core->trans_info[X1] = - transform_core->trans_info[X0] + width; - transform_core->trans_info[Y1] = - transform_core->trans_info[Y0] + height; - scale_tool_recalc (tool, tool->gdisp); - draw_core_resume (transform_core->core, tool); - } - } -} - -static void -scale_unit_changed (GtkWidget *widget, - gpointer data) -{ - scale_info_update ((Tool *) data); -} - -static void -scale_tool_motion (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gdouble ratio; - gdouble *x1; - gdouble *y1; - gdouble *x2; - gdouble *y2; - gint w, h; - gint dir_x, dir_y; - gint diff_x, diff_y; - - transform_core = (TransformCore *) tool->private; - - diff_x = transform_core->curx - transform_core->lastx; - diff_y = transform_core->cury - transform_core->lasty; - - switch (transform_core->function) - { - case TRANSFORM_HANDLE_1: - x1 = &transform_core->trans_info [X0]; - y1 = &transform_core->trans_info [Y0]; - x2 = &transform_core->trans_info [X1]; - y2 = &transform_core->trans_info [Y1]; - dir_x = dir_y = 1; - break; - case TRANSFORM_HANDLE_2: - x1 = &transform_core->trans_info [X1]; - y1 = &transform_core->trans_info [Y0]; - x2 = &transform_core->trans_info [X0]; - y2 = &transform_core->trans_info [Y1]; - dir_x = -1; - dir_y = 1; - break; - case TRANSFORM_HANDLE_3: - x1 = &transform_core->trans_info [X0]; - y1 = &transform_core->trans_info [Y1]; - x2 = &transform_core->trans_info [X1]; - y2 = &transform_core->trans_info [Y0]; - dir_x = 1; - dir_y = -1; - break; - case TRANSFORM_HANDLE_4: - x1 = &transform_core->trans_info [X1]; - y1 = &transform_core->trans_info [Y1]; - x2 = &transform_core->trans_info [X0]; - y2 = &transform_core->trans_info [Y0]; - dir_x = dir_y = -1; - break; - default : - return; - } - - /* if just the mod1 key is down, affect only the height */ - if (transform_core->state & GDK_MOD1_MASK && - ! (transform_core->state & GDK_CONTROL_MASK)) - diff_x = 0; - /* if just the control key is down, affect only the width */ - else if (transform_core->state & GDK_CONTROL_MASK && - ! (transform_core->state & GDK_MOD1_MASK)) - diff_y = 0; - - *x1 += diff_x; - *y1 += diff_y; - - if (dir_x > 0) - { - if (*x1 >= *x2) *x1 = *x2 - 1; - } - else - { - if (*x1 <= *x2) *x1 = *x2 + 1; - } - - if (dir_y > 0) - { - if (*y1 >= *y2) *y1 = *y2 - 1; - } - else - { - if (*y1 <= *y2) *y1 = *y2 + 1; - } - - /* if both the control key & mod1 keys are down, - * keep the aspect ratio intact - */ - if (transform_core->state & GDK_CONTROL_MASK && - transform_core->state & GDK_MOD1_MASK) - { - ratio = (double) (transform_core->x2 - transform_core->x1) / - (double) (transform_core->y2 - transform_core->y1); - - w = ABS ((*x2 - *x1)); - h = ABS ((*y2 - *y1)); - - if (w > h * ratio) - h = w / ratio; - else - w = h * ratio; - - *y1 = *y2 - dir_y * h; - *x1 = *x2 - dir_x * w; - } -} - -static void -scale_tool_recalc (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gint x1, y1, x2, y2; - gint diffx, diffy; - gint cx, cy; - gdouble scalex, scaley; - - transform_core = (TransformCore *) tool->private; - - x1 = (int) transform_core->trans_info [X0]; - y1 = (int) transform_core->trans_info [Y0]; - x2 = (int) transform_core->trans_info [X1]; - y2 = (int) transform_core->trans_info [Y1]; - - scalex = scaley = 1.0; - if (transform_core->x2 - transform_core->x1) - scalex = (double) (x2 - x1) / (double) (transform_core->x2 - transform_core->x1); - if (transform_core->y2 - transform_core->y1) - scaley = (double) (y2 - y1) / (double) (transform_core->y2 - transform_core->y1); - - switch (transform_core->function) - { - case TRANSFORM_HANDLE_1: - cx = x2; cy = y2; - diffx = x2 - transform_core->x2; - diffy = y2 - transform_core->y2; - break; - case TRANSFORM_HANDLE_2: - cx = x1; cy = y2; - diffx = x1 - transform_core->x1; - diffy = y2 - transform_core->y2; - break; - case TRANSFORM_HANDLE_3: - cx = x2; cy = y1; - diffx = x2 - transform_core->x2; - diffy = y1 - transform_core->y1; - break; - case TRANSFORM_HANDLE_4: - cx = x1; cy = y1; - diffx = x1 - transform_core->x1; - diffy = y1 - transform_core->y1; - break; - default : - cx = x1; cy = y1; - diffx = diffy = 0; - break; - } - - /* assemble the transformation matrix */ - gimp_matrix3_identity (transform_core->transform); - gimp_matrix3_translate (transform_core->transform, - (double) -cx + diffx, (double) -cy + diffy); - gimp_matrix3_scale (transform_core->transform, scalex, scaley); - gimp_matrix3_translate (transform_core->transform, (double) cx, (double) cy); - - /* transform the bounding box */ - transform_core_transform_bounding_box (tool); - - /* update the information dialog */ - scale_info_update (tool); -} - -TileManager * -scale_tool_scale (GImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - gdouble *trans_info, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix) -{ - GimpProgress *progress; - TileManager *ret; - - progress = progress_start (gdisp, _("Scaling..."), FALSE, NULL, NULL); - - ret = transform_core_do (gimage, drawable, float_tiles, - interpolation, matrix, - progress ? progress_update_and_flush : - (GimpProgressFunc) NULL, - progress); - - if (progress) - progress_end (progress); - - return ret; -} diff --git a/app/scale_tool.h b/app/scale_tool.h deleted file mode 100644 index 2de517460f..0000000000 --- a/app/scale_tool.h +++ /dev/null @@ -1,35 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SCALE_TOOL_H__ -#define __SCALE_TOOL_H__ - - -TileManager * scale_tool_scale (GimpImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - gdouble *trans_info, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix); - -Tool * tools_new_scale_tool (void); -void tools_free_scale_tool (Tool *tool); - - -#endif /* __SCALE_TOOL_H__ */ diff --git a/app/scroll.c b/app/scroll.c index 9f9526beb9..7b753ffaa0 100644 --- a/app/scroll.c +++ b/app/scroll.c @@ -30,7 +30,8 @@ #include "scale.h" #include "scroll.h" #include "nav_window.h" -#include "tools.h" + +#include "tools/tools.h" /* This is the delay before dithering begins diff --git a/app/shear_tool.c b/app/shear_tool.c deleted file mode 100644 index ba7d567bbc..0000000000 --- a/app/shear_tool.c +++ /dev/null @@ -1,373 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "gimpprogress.h" -#include "info_dialog.h" -#include "shear_tool.h" -#include "selection.h" -#include "tools.h" -#include "tool_options.h" -#include "transform_core.h" -#include "transform_tool.h" -#include "undo.h" - -#include "tile_manager_pvt.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* index into trans_info array */ -#define HORZ_OR_VERT 0 -#define XSHEAR 1 -#define YSHEAR 2 - -/* the minimum movement before direction of shear can be determined (pixels) */ -#define MIN_MOVE 5 - - -/* forward function declarations */ -static TileManager * shear_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state); - -static void shear_tool_recalc (Tool *tool, - GDisplay *gdisp); -static void shear_tool_motion (Tool *tool, - GDisplay *gdisp); -static void shear_info_update (Tool *tool); - -static void shear_x_mag_changed (GtkWidget *widget, - gpointer data); -static void shear_y_mag_changed (GtkWidget *widget, - gpointer data); - - -/* variables local to this file */ -static gdouble xshear_val; -static gdouble yshear_val; - - -static TileManager * -shear_tool_transform (Tool *tool, - GDisplay *gdisp, - TransformState state) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - switch (state) - { - case TRANSFORM_INIT: - if (!transform_info) - { - transform_info = info_dialog_new (_("Shear Information"), - gimp_standard_help_func, - "tools/transform_shear.html"); - - info_dialog_add_spinbutton (transform_info, - _("Shear Magnitude X:"), - &xshear_val, - -65536, 65536, 1, 15, 1, 1, 0, - shear_x_mag_changed, tool); - - info_dialog_add_spinbutton (transform_info, - _("Y:"), - &yshear_val, - -65536, 65536, 1, 15, 1, 1, 0, - shear_y_mag_changed, tool); - } - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), TRUE); - transform_core->trans_info[HORZ_OR_VERT] = ORIENTATION_UNKNOWN; - transform_core->trans_info[XSHEAR] = 0.0; - transform_core->trans_info[YSHEAR] = 0.0; - - return NULL; - break; - - case TRANSFORM_MOTION: - shear_tool_motion (tool, gdisp); - shear_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_RECALC: - shear_tool_recalc (tool, gdisp); - break; - - case TRANSFORM_FINISH: - gtk_widget_set_sensitive (GTK_WIDGET (transform_info->shell), FALSE); - return shear_tool_shear (gdisp->gimage, - gimp_image_active_drawable (gdisp->gimage), - gdisp, - transform_core->original, - transform_tool_smoothing (), - transform_core->transform); - break; - } - - return NULL; -} - -Tool * -tools_new_shear_tool (void) -{ - Tool *tool; - TransformCore *private; - - tool = transform_core_new (SHEAR, TRUE); - - private = tool->private; - - /* set the rotation specific transformation attributes */ - private->trans_func = shear_tool_transform; - - /* assemble the transformation matrix */ - gimp_matrix3_identity (private->transform); - - return tool; -} - -void -tools_free_shear_tool (Tool *tool) -{ - transform_core_free (tool); -} - -static void -shear_info_update (Tool *tool) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - xshear_val = transform_core->trans_info[XSHEAR]; - yshear_val = transform_core->trans_info[YSHEAR]; - - info_dialog_update (transform_info); - info_dialog_popup (transform_info); -} - -static void -shear_x_mag_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - TransformCore *transform_core; - gint value; - - tool = (Tool *) data; - - if (tool) - { - transform_core = (TransformCore *) tool->private; - - value = GTK_ADJUSTMENT (widget)->value; - - if (value != transform_core->trans_info[XSHEAR]) - { - draw_core_pause (transform_core->core, tool); - transform_core->trans_info[XSHEAR] = value; - shear_tool_recalc (tool, tool->gdisp); - draw_core_resume (transform_core->core, tool); - } - } -} - -static void -shear_y_mag_changed (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - TransformCore *transform_core; - gint value; - - tool = (Tool *) data; - - if (tool) - { - transform_core = (TransformCore *) tool->private; - - value = GTK_ADJUSTMENT (widget)->value; - - if (value != transform_core->trans_info[YSHEAR]) - { - draw_core_pause (transform_core->core, tool); - transform_core->trans_info[YSHEAR] = value; - shear_tool_recalc (tool, tool->gdisp); - draw_core_resume (transform_core->core, tool); - } - } -} - -static void -shear_tool_motion (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gint diffx, diffy; - gint dir; - - transform_core = (TransformCore *) tool->private; - - diffx = transform_core->curx - transform_core->lastx; - diffy = transform_core->cury - transform_core->lasty; - - /* If we haven't yet decided on which way to control shearing - * decide using the maximum differential - */ - - if (transform_core->trans_info[HORZ_OR_VERT] == ORIENTATION_UNKNOWN) - { - if (abs (diffx) > MIN_MOVE || abs (diffy) > MIN_MOVE) - { - if (abs (diffx) > abs (diffy)) - { - transform_core->trans_info[HORZ_OR_VERT] = ORIENTATION_HORIZONTAL; - transform_core->trans_info[ORIENTATION_VERTICAL] = 0.0; - } - else - { - transform_core->trans_info[HORZ_OR_VERT] = ORIENTATION_VERTICAL; - transform_core->trans_info[ORIENTATION_HORIZONTAL] = 0.0; - } - } - /* set the current coords to the last ones */ - else - { - transform_core->curx = transform_core->lastx; - transform_core->cury = transform_core->lasty; - } - } - - /* if the direction is known, keep track of the magnitude */ - if (transform_core->trans_info[HORZ_OR_VERT] != ORIENTATION_UNKNOWN) - { - dir = transform_core->trans_info[HORZ_OR_VERT]; - switch (transform_core->function) - { - case TRANSFORM_HANDLE_1: - if (dir == ORIENTATION_HORIZONTAL) - transform_core->trans_info[XSHEAR] -= diffx; - else - transform_core->trans_info[YSHEAR] -= diffy; - break; - case TRANSFORM_HANDLE_2: - if (dir == ORIENTATION_HORIZONTAL) - transform_core->trans_info[XSHEAR] -= diffx; - else - transform_core->trans_info[YSHEAR] += diffy; - break; - case TRANSFORM_HANDLE_3: - if (dir == ORIENTATION_HORIZONTAL) - transform_core->trans_info[XSHEAR] += diffx; - else - transform_core->trans_info[YSHEAR] -= diffy; - break; - case TRANSFORM_HANDLE_4: - if (dir == ORIENTATION_HORIZONTAL) - transform_core->trans_info[XSHEAR] += diffx; - else - transform_core->trans_info[YSHEAR] += diffy; - break; - default: - break; - } - } -} - -static void -shear_tool_recalc (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gfloat width, height; - gfloat cx, cy; - - transform_core = (TransformCore *) tool->private; - - cx = (transform_core->x1 + transform_core->x2) / 2.0; - cy = (transform_core->y1 + transform_core->y2) / 2.0; - - width = transform_core->x2 - transform_core->x1; - height = transform_core->y2 - transform_core->y1; - - if (width == 0) - width = 1; - if (height == 0) - height = 1; - - /* assemble the transformation matrix */ - gimp_matrix3_identity (transform_core->transform); - gimp_matrix3_translate (transform_core->transform, -cx, -cy); - - /* shear matrix */ - if (transform_core->trans_info[HORZ_OR_VERT] == ORIENTATION_HORIZONTAL) - gimp_matrix3_xshear (transform_core->transform, - (float) transform_core->trans_info [XSHEAR] / height); - else - gimp_matrix3_yshear (transform_core->transform, - (float) transform_core->trans_info [YSHEAR] / width); - - gimp_matrix3_translate (transform_core->transform, +cx, +cy); - - /* transform the bounding box */ - transform_core_transform_bounding_box (tool); - - /* update the information dialog */ - shear_info_update (tool); -} - -TileManager * -shear_tool_shear (GimpImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix) -{ - GimpProgress *progress; - TileManager *ret; - - progress = progress_start (gdisp, _("Shearing..."), FALSE, NULL, NULL); - - ret = transform_core_do (gimage, drawable, float_tiles, - interpolation, matrix, - progress ? progress_update_and_flush : - (GimpProgressFunc) NULL, - progress); - - if (progress) - progress_end (progress); - - return ret; -} diff --git a/app/shear_tool.h b/app/shear_tool.h deleted file mode 100644 index 3b1a0e381c..0000000000 --- a/app/shear_tool.h +++ /dev/null @@ -1,34 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SHEAR_TOOL_H__ -#define __SHEAR_TOOL_H__ - - -TileManager * shear_tool_shear (GimpImage *gimage, - GimpDrawable *drawable, - GDisplay *gdisp, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix); - -Tool * tools_new_shear_tool (void); -void tools_free_shear_tool (Tool *matrix); - - -#endif /* __SHEAR_TOOL_H__ */ diff --git a/app/smudge.c b/app/smudge.c deleted file mode 100644 index 1ae4cfa455..0000000000 --- a/app/smudge.c +++ /dev/null @@ -1,511 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "smudge.h" -#include "gdisplay.h" -#include "gimpcontext.h" -#include "gimpbrush.h" -#include "gimplut.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_core.h" -#include "pixel_region.h" -#include "paint_options.h" -#include "selection.h" -#include "temp_buf.h" -#include "tools.h" -#include "tool_options.h" -#include "gimage.h" - -#include "libgimp/gimpmath.h" - -#include "libgimp/gimpintl.h" - - -/* default defines */ - -#define SMUDGE_DEFAULT_RATE 50.0 - -/* the smudge structures */ - -typedef struct _SmudgeOptions SmudgeOptions; - -struct _SmudgeOptions -{ - PaintOptions paint_options; - - gdouble rate; - gdouble rate_d; - GtkObject *rate_w; -}; - - -/* function prototypes */ -static gpointer smudge_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state); -static void smudge_motion (PaintCore *paint_core, - PaintPressureOptions *pressure_options, - gdouble smudge_rate, - GimpDrawable *drawable); -static gboolean smudge_init (PaintCore *paint_core, - GimpDrawable *drawable); -static void smudge_finish (PaintCore *paint_core, - GimpDrawable *drawable); - -static void smudge_nonclipped_painthit_coords (PaintCore *paint_core, - gint *x, - gint *y, - gint *w, - gint *h); -static void smudge_allocate_accum_buffer (gint w, - gint h, - gint bytes, - guchar *do_fill); - - -/* local variables */ -static PixelRegion accumPR; -static guchar *accum_data; - -/* the smudge tool options */ -static SmudgeOptions * smudge_options = NULL; - -static gdouble non_gui_rate; - - -static void -smudge_options_reset (void) -{ - SmudgeOptions *options = smudge_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w), options->rate_d); -} - -static SmudgeOptions * -smudge_options_new (void) -{ - SmudgeOptions *options; - - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *scale; - - /* the new smudge tool options structure */ - options = g_new (SmudgeOptions, 1); - paint_options_init ((PaintOptions *) options, - SMUDGE, - smudge_options_reset); - - options->rate = options->rate_d = SMUDGE_DEFAULT_RATE; - - /* the main vbox */ - vbox = ((ToolOptions *) options)->main_vbox; - - /* the rate scale */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Rate:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - options->rate_w = - gtk_adjustment_new (options->rate_d, 0.0, 100.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w)); - gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->rate); - gtk_widget_show (scale); - gtk_widget_show (hbox); - - return options; -} - -static gpointer -smudge_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - /* initialization fails if the user starts outside the drawable */ - static gboolean initialized = FALSE; - - switch (state) - { - case MOTION_PAINT: - if (!initialized) - initialized = smudge_init (paint_core, drawable); - if (initialized) - smudge_motion (paint_core, - smudge_options->paint_options.pressure_options, - smudge_options->rate, drawable); - break; - - case FINISH_PAINT: - smudge_finish (paint_core, drawable); - initialized = FALSE; - break; - - default: - break; - } - - return NULL; -} - -static void -smudge_finish (PaintCore *paint_core, - GimpDrawable *drawable) -{ - if (accum_data) - { - g_free (accum_data); - accum_data = NULL; - } -} - -static void -smudge_nonclipped_painthit_coords (PaintCore *paint_core, - gint *x, - gint *y, - gint *w, - gint *h) -{ - /* Note: these are the brush mask size plus a border of 1 pixel */ - *x = (gint) paint_core->curx - paint_core->brush->mask->width/2 - 1; - *y = (gint) paint_core->cury - paint_core->brush->mask->height/2 - 1; - *w = paint_core->brush->mask->width + 2; - *h = paint_core->brush->mask->height + 2; -} - -static gboolean -smudge_init (PaintCore *paint_core, - GimpDrawable *drawable) -{ - GImage *gimage; - TempBuf *area; - PixelRegion srcPR; - gint x, y, w, h; - gint was_clipped; - guchar *do_fill = NULL; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return FALSE; - - /* If the image type is indexed, don't smudge */ - if (gimp_drawable_is_indexed (drawable)) - return FALSE; - - area = paint_core_get_paint_area (paint_core, drawable, 1.0); - - if (!area) - return FALSE; - - /* adjust the x and y coordinates to the upper left corner of the brush */ - smudge_nonclipped_painthit_coords (paint_core, &x, &y, &w, &h); - - if (x != area->x || y != area->y || w != area->width || h != area->height) - was_clipped = TRUE; - else - was_clipped = FALSE; - - /* When clipped, accum_data may contain pixels that map to - off-canvas pixels of the under-the-brush image, particulary - when the brush image contains an edge or corner of the - image. These off-canvas pixels are not a part of the current - composite, but may be composited in later generations. do_fill - contains a copy of the color of the pixel at the center of the - brush; assumed this is a reasonable choice for off- canvas pixels - that may enter into the blend */ - - if (was_clipped) - do_fill = gimp_drawable_get_color_at (drawable, - CLAMP ((gint) paint_core->curx, 0, gimp_drawable_width (drawable) - 1), - CLAMP ((gint) paint_core->cury, 0, gimp_drawable_height (drawable) - 1)); - - smudge_allocate_accum_buffer (w, h, gimp_drawable_bytes (drawable), do_fill); - - accumPR.x = area->x - x; - accumPR.y = area->y - y; - accumPR.w = area->width; - accumPR.h = area->height; - accumPR.rowstride = accumPR.bytes * w; - accumPR.data = accum_data - + accumPR.rowstride * accumPR.y - + accumPR.x * accumPR.bytes; - - pixel_region_init (&srcPR, gimp_drawable_data (drawable), - area->x, area->y, area->width, area->height, FALSE); - - /* copy the region under the original painthit. */ - copy_region (&srcPR, &accumPR); - - accumPR.x = area->x - x; - accumPR.y = area->y - y; - accumPR.w = area->width; - accumPR.h = area->height; - accumPR.rowstride = accumPR.bytes * w; - accumPR.data = accum_data - + accumPR.rowstride * accumPR.y - + accumPR.x * accumPR.bytes; - - if (do_fill) - g_free(do_fill); - - return TRUE; -} - -static void -smudge_allocate_accum_buffer (gint w, - gint h, - gint bytes, - guchar *do_fill) -{ - /* Allocate the accumulation buffer */ - accumPR.bytes = bytes; - accum_data = g_malloc (w * h * bytes); - - if (do_fill != NULL) - { - /* guchar color[3] = {0,0,0}; */ - accumPR.x = 0; - accumPR.y = 0; - accumPR.w = w; - accumPR.h = h; - accumPR.rowstride = accumPR.bytes * w; - accumPR.data = accum_data; - color_region (&accumPR, (const guchar*)do_fill); - } -} - -Tool * -tools_new_smudge (void) -{ - Tool * tool; - PaintCore * private; - - /* The tool options */ - if (! smudge_options) - { - smudge_options = smudge_options_new (); - tools_register (SMUDGE, (ToolOptions *) smudge_options); - - /* press all default buttons */ - smudge_options_reset (); - } - - tool = paint_core_new (SMUDGE); - /*tool->modifier_key_func = smudge_modifier_key_func;*/ - - private = (PaintCore *) tool->private; - private->paint_func = smudge_paint_func; - - return tool; -} - -void -tools_free_smudge (Tool *tool) -{ - paint_core_free (tool); -} - -static void -smudge_motion (PaintCore *paint_core, - PaintPressureOptions *pressure_options, - gdouble smudge_rate, - GimpDrawable *drawable) -{ - GImage *gimage; - TempBuf *area; - PixelRegion srcPR, destPR, tempPR; - gdouble rate; - gint opacity; - gint x, y, w, h; - - if (! (gimage = gimp_drawable_gimage (drawable))) - return; - - /* If the image type is indexed, don't smudge */ - if (gimp_drawable_is_indexed (drawable)) - return; - - smudge_nonclipped_painthit_coords (paint_core, &x, &y, &w, &h); - - /* Get the paint area */ - /* Smudge won't scale! */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, 1.0))) - return; - - /* srcPR will be the pixels under the current painthit from - the drawable*/ - - pixel_region_init (&srcPR, gimp_drawable_data (drawable), - area->x, area->y, area->width, area->height, FALSE); - - /* Enable pressure sensitive rate */ - if (pressure_options->rate) - rate = MIN (smudge_rate / 100.0 * paint_core->curpressure * 2.0, 1.0); - else - rate = smudge_rate / 100.0; - - /* The tempPR will be the built up buffer (for smudge) */ - tempPR.bytes = accumPR.bytes; - tempPR.rowstride = accumPR.rowstride; - tempPR.x = area->x - x; - tempPR.y = area->y - y; - tempPR.w = area->width; - tempPR.h = area->height; - tempPR.data = accum_data + - tempPR.rowstride * tempPR.y + tempPR.x * tempPR.bytes; - - /* The dest will be the paint area we got above (= canvas_buf) */ - - destPR.bytes = area->bytes; - destPR.x = 0; destPR.y = 0; - destPR.w = area->width; - destPR.h = area->height; - destPR.rowstride = area->width * area->bytes; - destPR.data = temp_buf_data (area); - - /* - Smudge uses the buffer Accum. - For each successive painthit Accum is built like this - Accum = rate*Accum + (1-rate)*I. - where I is the pixels under the current painthit. - Then the paint area (canvas_buf) is built as - (Accum,1) (if no alpha), - */ - - blend_region (&srcPR, &tempPR, &tempPR, ROUND (rate * 255.0)); - - /* re-init the tempPR */ - - tempPR.bytes = accumPR.bytes; - tempPR.rowstride = accumPR.rowstride; - tempPR.x = area->x - x; - tempPR.y = area->y - y; - tempPR.w = area->width; - tempPR.h = area->height; - tempPR.data = accum_data - + tempPR.rowstride * tempPR.y - + tempPR.x * tempPR.bytes; - - if (! gimp_drawable_has_alpha (drawable)) - add_alpha_region (&tempPR, &destPR); - else - copy_region (&tempPR, &destPR); - - opacity = 255 * gimp_context_get_opacity (NULL); - if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; - - /*Replace the newly made paint area to the gimage*/ - paint_core_replace_canvas (paint_core, drawable, - MIN (opacity, 255), - OPAQUE_OPACITY, - pressure_options->pressure ? PRESSURE : SOFT, - 1.0, INCREMENTAL); -} - -static gpointer -smudge_non_gui_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ - smudge_motion (paint_core, &non_gui_pressure_options, non_gui_rate, drawable); - - return NULL; -} - -gboolean -smudge_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array) -{ - gdouble rate = SMUDGE_DEFAULT_RATE; - SmudgeOptions *options = smudge_options; - - if (options) - rate = options->rate; - - return smudge_non_gui (drawable, rate, num_strokes, stroke_array); -} - -gboolean -smudge_non_gui (GimpDrawable *drawable, - gdouble rate, - gint num_strokes, - gdouble *stroke_array) -{ - gint i; - - if (paint_core_init (&non_gui_paint_core, drawable, - stroke_array[0], stroke_array[1])) - { - smudge_init (&non_gui_paint_core, drawable); - - /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = smudge_non_gui_paint_func; - - non_gui_rate = rate; - - non_gui_paint_core.curx = non_gui_paint_core.startx = - non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.cury = non_gui_paint_core.starty = - non_gui_paint_core.lasty = stroke_array[1]; - - smudge_non_gui_paint_func (&non_gui_paint_core, drawable, 0); - - for (i = 1; i < num_strokes; i++) - { - non_gui_paint_core.curx = stroke_array[i * 2 + 0]; - non_gui_paint_core.cury = stroke_array[i * 2 + 1]; - - paint_core_interpolate (&non_gui_paint_core, drawable); - - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; - } - - /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); - - /* Cleanup */ - paint_core_cleanup (); - smudge_finish (&non_gui_paint_core, drawable); - return TRUE; - } - - return FALSE; -} diff --git a/app/smudge.h b/app/smudge.h deleted file mode 100644 index 0ea9609198..0000000000 --- a/app/smudge.h +++ /dev/null @@ -1,49 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SMUDGE_H__ -#define __SMUDGE_H__ - - -typedef enum -{ - SMUDGE_TYPE_SMUDGE, - SMUDGE_TYPE_STREAK -} SmudgeType; - -typedef enum -{ - SMUDGE_MODE_HIGHLIGHTS, - SMUDGE_MODE_MIDTONES, - SMUDGE_MODE_SHADOWS -} SmudgeMode; - - -gboolean smudge_non_gui (GimpDrawable *drawable, - gdouble rate, - gint num_strokes, - gdouble *stroke_array); -gboolean smudge_non_gui_default (GimpDrawable *drawable, - gint num_strokes, - gdouble *stroke_array); - -Tool * tools_new_smudge (void); -void tools_free_smudge (Tool *tool); - - -#endif /* __SMUDGE_H__ */ diff --git a/app/text_tool.c b/app/text_tool.c deleted file mode 100644 index 92bf01874c..0000000000 --- a/app/text_tool.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#ifndef GDK_WINDOWING_WIN32 -#include -#endif - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "edit_selection.h" -#include "errors.h" -#include "floating_sel.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "global_edit.h" -#include "layer.h" -#include "paint_funcs.h" -#include "pixel_region.h" -#include "plug_in.h" -#include "selection.h" -#include "text_tool.h" -#include "tile.h" -#include "tools.h" -#include "tool_options.h" -#include "tile_manager.h" -#include "tile_manager_pvt.h" -#include "undo.h" - -#include "libgimp/gimplimits.h" - -#include "libgimp/gimpintl.h" - - -#define FOUNDRY 0 -#define FAMILY 1 -#define WEIGHT 2 -#define SLANT 3 -#define SET_WIDTH 4 -#define PIXEL_SIZE 6 -#define POINT_SIZE 7 -#define XRESOLUTION 8 -#define YRESOLUTION 9 -#define SPACING 10 -#define REGISTRY 12 -#define ENCODING 13 - -/* the text tool structures */ - -typedef struct _TextTool TextTool; - -struct _TextTool -{ - gint click_x; - gint click_y; - GDisplay *gdisp; -}; - -typedef struct _TextOptions TextOptions; - -struct _TextOptions -{ - ToolOptions tool_options; - - gboolean antialias; - gboolean antialias_d; - GtkWidget *antialias_w; - - gint border; - gint border_d; - GtkObject *border_w; - - gboolean use_dyntext; - gboolean use_dyntext_d; - GtkWidget *use_dyntext_w; -}; - - -static void text_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void text_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void text_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void text_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static void text_dialog_create (void); -static void text_dialog_ok_callback (GtkWidget *widget, - gpointer data); -static void text_dialog_cancel_callback (GtkWidget *widget, - gpointer data); -static gint text_dialog_delete_callback (GtkWidget *widget, - GdkEvent *event, - gpointer data); - -static void text_init_render (TextTool *text_tool); -static void text_gdk_image_to_region (GdkImage *image, - gint , - PixelRegion *); -static void text_size_multiply (gchar **fontname, - gint size); -static void text_set_resolution (gchar **fontname, - gdouble xres, - gdouble yres); - - -/* the text tool options */ -static TextOptions *text_options = NULL; - -/* local variables */ -static TextTool *the_text_tool = NULL; -static GtkWidget *text_tool_shell = NULL; - - -/* functions */ - -static void -text_options_reset (void) -{ - TextOptions *options = text_options; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->antialias_w), - options->antialias_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->border_w), - options->border_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_dyntext_w), - options->use_dyntext_d); -} - -static TextOptions * -text_options_new (void) -{ - TextOptions *options; - - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *spinbutton; - GtkWidget *sep; - - /* the new text tool options structure */ - options = g_new (TextOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Text Tool"), - text_options_reset); - options->antialias = options->antialias_d = TRUE; - options->border = options->border_d = 0; - options->use_dyntext = options->use_dyntext_d = FALSE; - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* antialias toggle */ - options->antialias_w = - gtk_check_button_new_with_label (_("Antialiasing")); - gtk_signal_connect (GTK_OBJECT (options->antialias_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->antialias); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->antialias_w), - options->antialias_d); - gtk_box_pack_start (GTK_BOX (vbox), options->antialias_w, - FALSE, FALSE, 0); - gtk_widget_show (options->antialias_w); - - /* the border spinbutton */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Border:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - options->border_w = - gtk_adjustment_new (options->border_d, 0.0, 32767.0, 1.0, 50.0, 0.0); - gtk_signal_connect (GTK_OBJECT (options->border_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_int_adjustment_update), - &options->border); - spinbutton = - gtk_spin_button_new (GTK_ADJUSTMENT (options->border_w), 1.0, 0.0); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), - GTK_SHADOW_NONE); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_widget_set_usize (spinbutton, 75, 0); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - gtk_widget_show (spinbutton); - - gtk_widget_show (hbox); - - sep = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), sep, FALSE, FALSE, 0); - gtk_widget_show (sep); - - /* the dynamic text toggle */ - options->use_dyntext_w = - gtk_check_button_new_with_label (_("Use Dynamic Text")); - gtk_signal_connect (GTK_OBJECT (options->use_dyntext_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->use_dyntext); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_dyntext_w), - options->use_dyntext_d); - gtk_box_pack_start (GTK_BOX (vbox), options->use_dyntext_w, - FALSE, FALSE, 0); - gtk_widget_show (options->use_dyntext_w); - - /* let the toggle callback set the sensitive states */ - gtk_widget_set_sensitive (options->antialias_w, ! options->use_dyntext_d); - gtk_widget_set_sensitive (spinbutton, ! options->use_dyntext_d); - gtk_widget_set_sensitive (label, ! options->use_dyntext_d); - gtk_object_set_data (GTK_OBJECT (options->use_dyntext_w), "inverse_sensitive", - spinbutton); - gtk_object_set_data (GTK_OBJECT (spinbutton), "inverse_sensitive", label); - gtk_object_set_data (GTK_OBJECT (label), "inverse_sensitive", - options->antialias_w); - - return options; -} - -Tool* -tools_new_text (void) -{ - Tool * tool; - - /* The tool options */ - if (! text_options) - { - text_options = text_options_new (); - tools_register (TEXT, (ToolOptions *) text_options); - } - - /* the new text tool structure */ - tool = tools_new_tool (TEXT); - the_text_tool = g_new (TextTool, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - - tool->private = (void *) the_text_tool; - - tool->button_press_func = text_button_press; - tool->button_release_func = text_button_release; - tool->cursor_update_func = text_cursor_update; - tool->control_func = text_control; - - return tool; -} - -void -tools_free_text (Tool *tool) -{ - g_free (tool->private); - the_text_tool = NULL; - - if (text_tool_shell) - gimp_dialog_hide (text_tool_shell); -} - -static void -text_call_gdyntext (GDisplay *gdisp) -{ - ProcRecord *proc_rec; - Argument *args; - - /* find the gDynText PDB record */ - if ((proc_rec = procedural_db_lookup ("plug_in_dynamic_text")) == NULL) - { - g_message ("text_call_gdyntext: gDynText procedure lookup failed"); - return; - } - - /* plug-in arguments as if called by /Filters/... */ - args = g_new (Argument, 3); - args[0].arg_type = PDB_INT32; - args[0].value.pdb_int = RUN_INTERACTIVE; - args[1].arg_type = PDB_IMAGE; - args[1].value.pdb_int = (gint32) pdb_image_to_id (gdisp->gimage); - args[2].arg_type = PDB_DRAWABLE; - args[2].value.pdb_int = (gint32) gimp_image_active_drawable (gdisp->gimage)->ID; - - plug_in_run (proc_rec, args, 3, FALSE, TRUE, gdisp->ID); - - g_free (args); -} - -static void -text_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - Layer *layer; - TextTool *text_tool; - - text_tool = tool->private; - text_tool->gdisp = gdisp; - - tool->state = ACTIVE; - tool->gdisp = gdisp; - - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &text_tool->click_x, &text_tool->click_y, - TRUE, 0); - - if ((layer = gimp_image_pick_correlate_layer (gdisp->gimage, - text_tool->click_x, - text_tool->click_y))) - /* If there is a floating selection, and this aint it, use the move tool */ - if (layer_is_floating_sel (layer)) - { - init_edit_selection (tool, gdisp, bevent, EDIT_LAYER_TRANSLATE); - return; - } - - if (text_options->use_dyntext) - { - text_call_gdyntext (gdisp); - return; - } - - if (! text_tool_shell) - text_dialog_create (); - - if (!GTK_WIDGET_VISIBLE (text_tool_shell)) - gtk_widget_show (text_tool_shell); -} - -static void -text_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - tool->state = INACTIVE; -} - -static void -text_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - Layer *layer; - gint x, y; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &x, &y, FALSE, FALSE); - - if ((layer = gimp_image_pick_correlate_layer (gdisp->gimage, x, y))) - /* if there is a floating selection, and this aint it... */ - if (layer_is_floating_sel (layer)) - { - gdisplay_install_tool_cursor (gdisp, GDK_FLEUR, - MOVE, - CURSOR_MODIFIER_NONE, - FALSE); - return; - } - - gdisplay_install_tool_cursor (gdisp, GDK_XTERM, - TEXT, - CURSOR_MODIFIER_NONE, - FALSE); -} - -static void -text_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - if (text_tool_shell) - gimp_dialog_hide (text_tool_shell); - break; - - default: - break; - } -} - -static void -text_dialog_create (void) -{ - /* Create the shell */ - text_tool_shell = gtk_font_selection_dialog_new (_("Text Tool")); - gtk_window_set_wmclass (GTK_WINDOW (text_tool_shell), "text_tool", "Gimp"); - gtk_window_set_policy (GTK_WINDOW (text_tool_shell), FALSE, TRUE, FALSE); - gtk_window_set_position (GTK_WINDOW (text_tool_shell), GTK_WIN_POS_MOUSE); - - /* handle the wm close signal */ - gtk_signal_connect (GTK_OBJECT (text_tool_shell), "delete_event", - GTK_SIGNAL_FUNC (text_dialog_delete_callback), - NULL); - - /* ok and cancel buttons */ - gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG - (text_tool_shell)->ok_button), "clicked", - GTK_SIGNAL_FUNC (text_dialog_ok_callback), - NULL); - - gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG - (text_tool_shell)->cancel_button), "clicked", - GTK_SIGNAL_FUNC (text_dialog_cancel_callback), - NULL); - - /* Show the shell */ - gtk_widget_show (text_tool_shell); -} - -static void -text_dialog_ok_callback (GtkWidget *widget, - gpointer data) -{ - gimp_dialog_hide (text_tool_shell); - - if (the_text_tool) - text_init_render (the_text_tool); -} - -static gint -text_dialog_delete_callback (GtkWidget *widget, - GdkEvent *event, - gpointer data) -{ - text_dialog_cancel_callback (widget, data); - - return TRUE; -} - -static void -text_dialog_cancel_callback (GtkWidget *widget, - gpointer data) -{ - gimp_dialog_hide (text_tool_shell); -} - -static void -text_init_render (TextTool *text_tool) -{ - GDisplay *gdisp; - gchar *fontname; - gchar *text; - gboolean antialias = text_options->antialias; - - fontname = gtk_font_selection_dialog_get_font_name - (GTK_FONT_SELECTION_DIALOG (text_tool_shell)); - if (!fontname) - return; - - gdisp = text_tool->gdisp; - - /* override the user's antialias setting if this is an indexed image */ - if (gimp_image_base_type (gdisp->gimage) == INDEXED) - antialias = FALSE; - - /* If we're anti-aliasing, request a larger font than user specified. - * This will probably produce a font which isn't available if fonts - * are not scalable on this particular X server. TODO: Ideally, should - * grey out anti-alias on these kinds of servers. */ - if (antialias) - text_size_multiply (&fontname, SUPERSAMPLE); - - /* If the text size is specified in points, it's size will be scaled - * correctly according to the image's resolution. - * FIXME: this currently can't be activated for the PDB, as the text has - * to be rendered in the size "text_get_extents" returns. - * TODO: add resolution parameters to "text_get_extents" - */ - text_set_resolution (&fontname, - gdisp->gimage->xresolution, - gdisp->gimage->yresolution); - - text = gtk_font_selection_dialog_get_preview_text - (GTK_FONT_SELECTION_DIALOG (text_tool_shell)); - - /* strdup it since the render function strtok()s the text */ - text = g_strdup (text); - - text_render (gdisp->gimage, gimp_image_active_drawable (gdisp->gimage), - text_tool->click_x, text_tool->click_y, - fontname, text, text_options->border, antialias); - - gdisplays_flush (); - - g_free (fontname); - g_free (text); -} - -static void -text_gdk_image_to_region (GdkImage *image, - gint scale, - PixelRegion *textPR) -{ - GdkColor black; - gint black_pixel; - gint pixel; - gint value; - gint scalex, scaley; - gint scale2; - gint x, y; - gint i, j; - guchar * data; - - scale2 = scale * scale; -/* GDK_WINDOWING is defined only with GTk+ 1.3 */ -#ifndef GDK_WINDOWING_WIN32 - black.red = black.green = black.blue = 0; - gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE); - black_pixel = black.pixel; -#else - black_pixel = 0; -#endif - data = textPR->data; - - for (y = 0, scaley = 0; y < textPR->h; y++, scaley += scale) - { - for (x = 0, scalex = 0; x < textPR->w; x++, scalex += scale) - { - value = 0; - - for (i = scaley; i < scaley + scale; i++) - for (j = scalex; j < scalex + scale; j++) - { - pixel = gdk_image_get_pixel (image, j, i); - if (pixel == black_pixel) - value ++; - } - - /* store the alpha value in the data */ - *data++= (guchar) ((value * 255) / scale2); - - } - } -} - -GimpLayer * -text_render (GimpImage *gimage, - GimpDrawable *drawable, - gint text_x, - gint text_y, - gchar *fontname, - gchar *text, - gint border, - gint antialias) -{ - GdkFont *font; - GdkPixmap *pixmap; - GdkImage *image; - GdkGC *gc; - GdkColor black, white; - Layer *layer; - TileManager *mask, *newmask; - PixelRegion textPR, maskPR; - gint layer_type; - guchar color[MAX_CHANNELS]; - gchar *str; - gint nstrs; - gboolean crop; - gint line_width, line_height; - gint pixmap_width, pixmap_height; - gint text_width, text_height; - gint width, height; - gint x, y, k; - void *pr; -#ifndef GDK_WINDOWING_WIN32 - XFontStruct *xfs; -#endif - - /* determine the layer type */ - if (drawable) - layer_type = gimp_drawable_type_with_alpha (drawable); - else - layer_type = gimp_image_base_type_with_alpha (gimage); - - /* scale the text based on the antialiasing amount */ - if (antialias) - antialias = SUPERSAMPLE; - else - antialias = 1; - - /* Dont crop the text if border is negative */ - crop = (border >= 0); - if (!crop) - border = 0; - - /* load the font in */ - gdk_error_warnings = 0; - gdk_error_code = 0; -#ifndef GDK_WINDOWING_WIN32 - font = gdk_font_load (fontname); - if (!font) - { - g_message (_("Font '%s' not found."), fontname); - return NULL; - } - xfs = GDK_FONT_XFONT (font); - if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0) - { - gchar *fname; - - gdk_font_unref (font); - fname = g_strdup_printf ("%s,*", fontname); - font = gdk_fontset_load (fname); - g_free (fname); - } -#else - /* Just use gdk_fontset_load all the time. IMHO it could be like - * this on all platforms? - */ - font = gdk_fontset_load (fontname); -#endif - gdk_error_warnings = 1; - if (!font || (gdk_error_code == -1)) - { - g_message (_("Font '%s' not found.%s"), - fontname, - antialias > 1 ? - _("\nIf you don't have scalable fonts, " - "try turning off antialiasing in the tool options.") : ""); - return NULL; - } - - /* determine the bounding box of the text */ - width = -1; - height = 0; - line_height = font->ascent + font->descent; - - nstrs = 0; - str = strtok (text, "\n"); - while (str) - { - nstrs += 1; - - /* gdk_string_measure will give the correct width of the - * string. However, we'll add a little "fudge" factor just - * to be sure. - */ - line_width = gdk_string_measure (font, str) + 5; - if (line_width > width) - width = line_width; - height += line_height; - - str = strtok (NULL, "\n"); - } - - /* We limit the largest pixmap we create to approximately 200x200. - * This is approximate since it depends on the amount of antialiasing. - * Basically, we want the width and height to be divisible by the antialiasing - * amount. (Which lies in the range 1-10). - * This avoids problems on some X-servers (Xinside) which have problems - * with large pixmaps. (Specifically pixmaps which are larger - width - * or height - than the screen). - */ - pixmap_width = TILE_WIDTH * antialias; - pixmap_height = TILE_HEIGHT * antialias; - - /* determine the actual text size based on the amount of antialiasing */ - text_width = width / antialias; - text_height = height / antialias; - - /* create the pixmap of depth 1 */ - pixmap = gdk_pixmap_new (NULL, pixmap_width, pixmap_height, 1); - - /* create the gc */ - gc = gdk_gc_new (pixmap); - gdk_gc_set_font (gc, font); - - /* get black and white pixels for this gdisplay */ - black.red = black.green = black.blue = 0; - white.red = white.green = white.blue = 65535; -#ifndef GDK_WINDOWING_WIN32 - gdk_colormap_alloc_color (gdk_colormap_get_system (), &black, FALSE, TRUE); - gdk_colormap_alloc_color (gdk_colormap_get_system (), &white, FALSE, TRUE); -#else - black.pixel = 0; - white.pixel = 1; -#endif - - /* Render the text into the pixmap. - * Since the pixmap may not fully bound the text (because we limit its size) - * we must tile it around the texts actual bounding box. - */ - mask = tile_manager_new (text_width, text_height, 1); - pixel_region_init (&maskPR, mask, 0, 0, text_width, text_height, TRUE); - - for (pr = pixel_regions_register (1, &maskPR); - pr != NULL; - pr = pixel_regions_process (pr)) - { - /* erase the pixmap */ - gdk_gc_set_foreground (gc, &white); - gdk_draw_rectangle (pixmap, gc, 1, 0, 0, pixmap_width, pixmap_height); - gdk_gc_set_foreground (gc, &black); - - /* adjust the x and y values */ - x = -maskPR.x * antialias; - y = font->ascent - maskPR.y * antialias; - str = text; - - for (k = 0; k < nstrs; k++) - { - gdk_draw_string (pixmap, font, gc, x, y, str); - str += strlen (str) + 1; - y += line_height; - } - - /* create the GdkImage */ - image = gdk_image_get (pixmap, 0, 0, pixmap_width, pixmap_height); - - if (!image) - gimp_fatal_error ("text_render(): Sanity check failed: could not get gdk image"); - - if (image->depth != 1) - gimp_fatal_error ("text_render(): Sanity check failed: image should have 1 bit per pixel"); - - /* convert the GdkImage bitmap to a region */ - text_gdk_image_to_region (image, antialias, &maskPR); - - /* free the image */ - gdk_image_destroy (image); - } - - /* Crop the mask buffer */ - newmask = crop ? crop_buffer (mask, border) : mask; - if (newmask != mask) - tile_manager_destroy (mask); - - if (newmask && - (layer = layer_new (gimage, newmask->width, - newmask->height, layer_type, - _("Text Layer"), OPAQUE_OPACITY, NORMAL_MODE))) - { - /* color the layer buffer */ - gimp_image_get_foreground (gimage, drawable, color); - color[GIMP_DRAWABLE (layer)->bytes - 1] = OPAQUE_OPACITY; - pixel_region_init (&textPR, GIMP_DRAWABLE (layer)->tiles, - 0, 0, - GIMP_DRAWABLE (layer)->width, - GIMP_DRAWABLE (layer)->height, TRUE); - color_region (&textPR, color); - - /* apply the text mask */ - pixel_region_init (&textPR, GIMP_DRAWABLE (layer)->tiles, - 0, 0, - GIMP_DRAWABLE (layer)->width, - GIMP_DRAWABLE (layer)->height, TRUE); - pixel_region_init (&maskPR, newmask, - 0, 0, - GIMP_DRAWABLE (layer)->width, - GIMP_DRAWABLE (layer)->height, FALSE); - apply_mask_to_region (&textPR, &maskPR, OPAQUE_OPACITY); - - /* Start a group undo */ - undo_push_group_start (gimage, TEXT_UNDO); - - /* Set the layer offsets */ - GIMP_DRAWABLE (layer)->offset_x = text_x; - GIMP_DRAWABLE (layer)->offset_y = text_y; - - /* If there is a selection mask clear it-- - * this might not always be desired, but in general, - * it seems like the correct behavior. - */ - if (! gimage_mask_is_empty (gimage)) - channel_clear (gimp_image_get_mask (gimage)); - - /* If the drawable id is invalid, create a new layer */ - if (drawable == NULL) - gimp_image_add_layer (gimage, layer, -1); - /* Otherwise, instantiate the text as the new floating selection */ - else - floating_sel_attach (layer, drawable); - - /* end the group undo */ - undo_push_group_end (gimage); - - tile_manager_destroy (newmask); - } - else - { - if (newmask) - { - g_message ("text_render: could not allocate image"); - tile_manager_destroy (newmask); - } - layer = NULL; - } - - /* free the pixmap */ - gdk_pixmap_unref (pixmap); - - /* free the gc */ - gdk_gc_destroy (gc); - - /* free the font */ - gdk_font_unref (font); - - return layer; -} - -gboolean -text_get_extents (gchar *fontname, - gchar *text, - gint *width, - gint *height, - gint *ascent, - gint *descent) -{ - GdkFont *font; - gchar *str; - gint nstrs; - gint line_width, line_height; -#ifndef GDK_WINDOWING_WIN32 - XFontStruct *xfs; -#endif - - /* load the font in */ - gdk_error_warnings = 0; - gdk_error_code = 0; -#ifndef GDK_WINDOWING_WIN32 - font = gdk_font_load (fontname); - if (!font) - return FALSE; - - xfs = GDK_FONT_XFONT (font); - if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0) - { - gchar *fname; - - gdk_font_unref (font); - fname = g_strdup_printf ("%s,*", fontname); - font = gdk_fontset_load (fname); - g_free (fname); - } -#else - /* Just use gdk_fontset_load all the time. IMHO it could be like - * this on all platforms? - */ - font = gdk_fontset_load (fontname); -#endif - gdk_error_warnings = 1; - if (!font || (gdk_error_code == -1)) - return FALSE; - - /* determine the bounding box of the text */ - *width = -1; - *height = 0; - *ascent = font->ascent; - *descent = font->descent; - line_height = *ascent + *descent; - - nstrs = 0; - str = strtok (text, "\n"); - while (str) - { - nstrs += 1; - - /* gdk_string_measure will give the correct width of the - * string. However, we'll add a little "fudge" factor just - * to be sure. - */ - line_width = gdk_string_measure (font, str) + 5; - if (line_width > *width) - *width = line_width; - *height += line_height; - - str = strtok (NULL, "\n"); - } - - if (*width < 0) - return FALSE; - else - return TRUE; -} - -static void -text_field_edges (gchar *fontname, - gint field_num, - /* RETURNS: */ - gchar **start, - gchar **end) -{ - gchar *t1, *t2; - - t1 = fontname; - - while (*t1 && (field_num >= 0)) - if (*t1++ == '-') - field_num--; - - t2 = t1; - while (*t2 && (*t2 != '-')) - t2++; - - *start = t1; - *end = t2; -} - -/* convert sizes back to text */ -#define TO_TXT(x) \ -{ \ - if (x >= 0) \ - g_snprintf (new_ ## x, sizeof (new_ ## x), "%d", x); \ - else \ - g_snprintf (new_ ## x, sizeof (new_ ## x), "*"); \ -} - -/* Multiply the point and pixel sizes in *fontname by "mul", which - * must be positive. If either point or pixel sizes are "*" then they - * are left untouched. The memory *fontname is g_free()d, and - * *fontname is replaced by a fresh allocation of the correct size. - */ -static void -text_size_multiply (gchar **fontname, - gint mul) -{ - gchar *pixel_str; - gchar *point_str; - gchar *newfont; - gchar *end; - gint pixel = -1; - gint point = -1; - gchar new_pixel[16]; - gchar new_point[16]; - - /* slice the font spec around the size fields */ - text_field_edges (*fontname, PIXEL_SIZE, &pixel_str, &end); - text_field_edges (*fontname, POINT_SIZE, &point_str, &end); - - *(pixel_str - 1) = 0; - *(point_str - 1) = 0; - - if (*pixel_str != '*') - pixel = atoi (pixel_str); - - if (*point_str != '*') - point = atoi (point_str); - - pixel *= mul; - point *= mul; - - /* convert the pixel and point sizes back to text */ - TO_TXT (pixel); - TO_TXT (point); - - newfont = g_strdup_printf ("%s-%s-%s%s", *fontname, new_pixel, new_point, end); - - g_free (*fontname); - - *fontname = newfont; -} - -static void -text_set_resolution (gchar **fontname, - gdouble xresolution, - gdouble yresolution) -{ - gchar *size_str; - gchar *xres_str; - gchar *yres_str; - gchar *newfont; - gchar *end; - gchar new_size[16]; - gchar new_xres[16]; - gchar new_yres[16]; - gdouble points; - - gint size; - gint xres; - gint yres; - - /* get the point size string */ - text_field_edges (*fontname, POINT_SIZE, &size_str, &end); - - /* don't set the resolution if the point size is unspecified */ - if (xresolution < GIMP_MIN_RESOLUTION || - yresolution < GIMP_MIN_RESOLUTION || - *size_str == '*') - return; - - points = atof (size_str); - - /* X allows only integer resolution values, so we do some - * ugly calculations (starting with yres because the size of - * a font is it's height) - */ - if (yresolution < 1.0) - { - points /= (1.0 / yresolution); - xresolution *= (1.0 / yresolution); - yresolution = 1.0; - } - - /* res may be != (int) res - * (important only for very small resolutions) - */ - points *= yresolution / (double) (int) yresolution; - xresolution /= yresolution / (double) (int) yresolution; - - /* finally, if xres became invalid by the above calculations */ - xresolution = CLAMP (xresolution, 1.0, GIMP_MAX_RESOLUTION); - - /* slice the font spec around the resolution fields */ - text_field_edges (*fontname, XRESOLUTION, &xres_str, &end); - text_field_edges (*fontname, YRESOLUTION, &yres_str, &end); - - *(size_str - 1) = 0; - *(xres_str - 1) = 0; - *(yres_str - 1) = 0; - - /* convert the resolutions to text */ - size = (gint) points; - xres = (gint) xresolution; - yres = (gint) yresolution; - - TO_TXT (size); - TO_TXT (xres); - TO_TXT (yres); - - newfont = g_strdup_printf ("%s-%s-%s-%s%s", - *fontname, new_size, new_xres, new_yres, end); - - g_free (*fontname); - - *fontname = newfont; -} - -#undef TO_TXT diff --git a/app/text_tool.h b/app/text_tool.h deleted file mode 100644 index 41633d6c35..0000000000 --- a/app/text_tool.h +++ /dev/null @@ -1,52 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __TEXT_TOOL_H__ -#define __TEXT_TOOL_H__ - - -#define SUPERSAMPLE 3 - -typedef enum -{ - PIXELS, - POINTS -} SizeType; - - -Tool * tools_new_text (void); -void tools_free_text (Tool *tool); - -gboolean text_get_extents (gchar *fontname, - gchar *text, - gint *width, - gint *height, - gint *ascent, - gint *descent); - -GimpLayer * text_render (GimpImage *gimage, - GimpDrawable *drawable, - gint text_x, - gint text_y, - gchar *fontname, - gchar *text, - gint border, - gint antialias); - - -#endif /* __TEXT_TOOL_H__ */ diff --git a/app/threshold.c b/app/threshold.c deleted file mode 100644 index d0dcc39222..0000000000 --- a/app/threshold.c +++ /dev/null @@ -1,579 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "drawable.h" -#include "gdisplay.h" -#include "gimphistogram.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "histogramwidget.h" -#include "image_map.h" -#include "paint_funcs.h" -#include "pixel_region.h" -#include "threshold.h" -#include "tools.h" -#include "tool_options.h" - -#include "libgimp/gimpintl.h" - - -#define HISTOGRAM_WIDTH 256 -#define HISTOGRAM_HEIGHT 150 - -#define LOW 0x1 -#define HIGH 0x2 -#define HISTORGAM 0x4 -#define ALL (LOW | HIGH | HISTOGRAM) - -/* the threshold structures */ - -typedef struct _Threshold Threshold; - -struct _Threshold -{ - gint x, y; /* coords for last mouse click */ -}; - - -/* threshold action functions */ -static void threshold_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -static ThresholdDialog * threshold_dialog_new (void); - -static void threshold_update (ThresholdDialog *td, - gint update); -static void threshold_preview (ThresholdDialog *td); -static void threshold_reset_callback (GtkWidget *widget, - gpointer data); -static void threshold_ok_callback (GtkWidget *widget, - gpointer data); -static void threshold_cancel_callback (GtkWidget *widget, - gpointer data); -static void threshold_preview_update (GtkWidget *widget, - gpointer data); -static void threshold_low_threshold_adjustment_update (GtkAdjustment *adj, - gpointer data); -static void threshold_high_threshold_adjustment_update (GtkAdjustment *adj, - gpointer data); - -static void threshold (PixelRegion *, - PixelRegion *, - gpointer ); -static void threshold_histogram_range (HistogramWidget *, - gint , - gint , - gpointer ); - - -/* the threshold tool options */ -static ToolOptions *threshold_options = NULL; - -/* the threshold tool dialog */ -static ThresholdDialog *threshold_dialog = NULL; - - -/* threshold machinery */ - -void -threshold_2 (gpointer data, - PixelRegion *srcPR, - PixelRegion *destPR) -{ - /* this function just re-orders the arguments so we can use - * pixel_regions_process_paralell - */ - threshold (srcPR, destPR, data); -} - -static void -threshold (PixelRegion *srcPR, - PixelRegion *destPR, - void *data) -{ - ThresholdDialog *td; - unsigned char *src, *s; - unsigned char *dest, *d; - int has_alpha, alpha; - int w, h, b; - int value; - - td = (ThresholdDialog *) data; - - h = srcPR->h; - src = srcPR->data; - dest = destPR->data; - has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4); - alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes; - - while (h--) - { - w = srcPR->w; - s = src; - d = dest; - while (w--) - { - if (td->color) - { - value = MAX (s[RED_PIX], s[GREEN_PIX]); - value = MAX (value, s[BLUE_PIX]); - - value = (value >= td->low_threshold && value <= td->high_threshold ) ? 255 : 0; - } - else - value = (s[GRAY_PIX] >= td->low_threshold && s[GRAY_PIX] <= td->high_threshold) ? 255 : 0; - - for (b = 0; b < alpha; b++) - d[b] = value; - - if (has_alpha) - d[alpha] = s[alpha]; - - s += srcPR->bytes; - d += destPR->bytes; - } - - src += srcPR->rowstride; - dest += destPR->rowstride; - } -} - -/* threshold action functions */ - -static void -threshold_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - switch (action) - { - case PAUSE: - break; - - case RESUME: - break; - - case HALT: - threshold_dialog_hide (); - break; - - default: - break; - } -} - -Tool * -tools_new_threshold (void) -{ - Tool * tool; - Threshold * private; - - /* The tool options */ - if (! threshold_options) - { - threshold_options = tool_options_new (_("Threshold")); - tools_register (THRESHOLD, threshold_options); - } - - tool = tools_new_tool (THRESHOLD); - private = g_new0 (Threshold, 1); - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->control_func = threshold_control; - - return tool; -} - -void -threshold_dialog_hide (void) -{ - if (threshold_dialog) - threshold_cancel_callback (NULL, (gpointer) threshold_dialog); -} - -void -tools_free_threshold (Tool *tool) -{ - Threshold * thresh; - - thresh = (Threshold *) tool->private; - - /* Close the threshold dialog */ - threshold_dialog_hide (); - - g_free (thresh); -} - -void -threshold_initialize (GDisplay *gdisp) -{ - if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage))) - { - g_message (_("Threshold does not operate on indexed drawables.")); - return; - } - - /* The threshold dialog */ - if (!threshold_dialog) - threshold_dialog = threshold_dialog_new (); - else - if (!GTK_WIDGET_VISIBLE (threshold_dialog->shell)) - gtk_widget_show (threshold_dialog->shell); - - threshold_dialog->low_threshold = 127; - threshold_dialog->high_threshold = 255; - - threshold_dialog->drawable = gimp_image_active_drawable (gdisp->gimage); - threshold_dialog->color = gimp_drawable_is_rgb (threshold_dialog->drawable); - threshold_dialog->image_map = - image_map_create (gdisp, threshold_dialog->drawable); - - gimp_histogram_calculate_drawable (threshold_dialog->hist, - threshold_dialog->drawable); - - gtk_signal_handler_block_by_data (GTK_OBJECT (threshold_dialog->histogram), - threshold_dialog); - histogram_widget_update (threshold_dialog->histogram, - threshold_dialog->hist); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (threshold_dialog->histogram), - threshold_dialog); - - threshold_update (threshold_dialog, ALL); - - if (threshold_dialog->preview) - threshold_preview (threshold_dialog); -} - -/**********************/ -/* Threshold dialog */ -/**********************/ - -static ThresholdDialog * -threshold_dialog_new (void) -{ - ThresholdDialog *td; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *spinbutton; - GtkWidget *label; - GtkWidget *frame; - GtkWidget *toggle; - GtkObject *data; - - td = g_new (ThresholdDialog, 1); - td->preview = TRUE; - td->low_threshold = 127; - td->high_threshold = 255; - td->hist = gimp_histogram_new (); - - /* The shell and main vbox */ - td->shell = - gimp_dialog_new (_("Threshold"), "threshold", - tools_help_func, NULL, - GTK_WIN_POS_NONE, - FALSE, TRUE, FALSE, - - _("OK"), threshold_ok_callback, - td, NULL, NULL, TRUE, FALSE, - _("Reset"), threshold_reset_callback, - td, NULL, NULL, TRUE, FALSE, - _("Cancel"), threshold_cancel_callback, - td, NULL, NULL, FALSE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (td->shell)->vbox), vbox); - - /* Horizontal box for threshold text widget */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = gtk_label_new (_("Threshold Range:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* low threshold spinbutton */ - data = gtk_adjustment_new (td->low_threshold, 0.0, 255.0, 1.0, 10.0, 0.0); - td->low_threshold_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (td->low_threshold_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (td->low_threshold_data), "value_changed", - GTK_SIGNAL_FUNC (threshold_low_threshold_adjustment_update), - td); - - gtk_widget_show (spinbutton); - - /* high threshold spinbutton */ - data = gtk_adjustment_new (td->high_threshold, 0.0, 255.0, 1.0, 10.0, 0.0); - td->high_threshold_data = GTK_ADJUSTMENT (data); - - spinbutton = gtk_spin_button_new (td->high_threshold_data, 1.0, 0); - gtk_widget_set_usize (spinbutton, 75, -1); - gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (td->high_threshold_data), "value_changed", - GTK_SIGNAL_FUNC (threshold_high_threshold_adjustment_update), - td); - - gtk_widget_show (spinbutton); - - gtk_widget_show (hbox); - - /* The threshold histogram */ - hbox = gtk_hbox_new (TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, FALSE, 0); - - td->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT); - - gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (td->histogram)); - - gtk_signal_connect (GTK_OBJECT (td->histogram), "range_changed", - GTK_SIGNAL_FUNC (threshold_histogram_range), - td); - - gtk_widget_show (GTK_WIDGET(td->histogram)); - - gtk_widget_show (frame); - gtk_widget_show (hbox); - - /* Horizontal box for preview */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - /* The preview toggle */ - toggle = gtk_check_button_new_with_label (_("Preview")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), td->preview); - gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); - - gtk_signal_connect (GTK_OBJECT (toggle), "toggled", - GTK_SIGNAL_FUNC (threshold_preview_update), - td); - - gtk_widget_show (toggle); - gtk_widget_show (hbox); - - gtk_widget_show (vbox); - gtk_widget_show (td->shell); - - return td; -} - -static void -threshold_update (ThresholdDialog *td, - gint update) -{ - if (update & LOW) - { - gtk_adjustment_set_value (td->low_threshold_data, td->low_threshold); - } - if (update & HIGH) - { - gtk_adjustment_set_value (td->high_threshold_data, td->high_threshold); - } - if (update & HISTOGRAM) - { - histogram_widget_range (td->histogram, - td->low_threshold, - td->high_threshold); - } -} - -static void -threshold_preview (ThresholdDialog *td) -{ - if (!td->image_map) - { - g_warning ("threshold_preview(): No image map"); - return; - } - - active_tool->preserve = TRUE; - image_map_apply (td->image_map, threshold, td); - active_tool->preserve = FALSE; -} - -static void -threshold_reset_callback (GtkWidget *widget, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - td->low_threshold = 127.0; - td->high_threshold = 255.0; - - threshold_update (td, ALL); - - if (td->preview) - threshold_preview (td); -} - -static void -threshold_ok_callback (GtkWidget *widget, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - gimp_dialog_hide (td->shell); - - active_tool->preserve = TRUE; - - if (!td->preview) - image_map_apply (td->image_map, threshold, (void *) td); - - if (td->image_map) - image_map_commit (td->image_map); - - active_tool->preserve = FALSE; - - td->image_map = NULL; - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -threshold_cancel_callback (GtkWidget *widget, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - gimp_dialog_hide (td->shell); - - if (td->image_map) - { - active_tool->preserve = TRUE; - image_map_abort (td->image_map); - active_tool->preserve = FALSE; - - td->image_map = NULL; - gdisplays_flush (); - } - - active_tool->gdisp = NULL; - active_tool->drawable = NULL; -} - -static void -threshold_preview_update (GtkWidget *widget, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - if (GTK_TOGGLE_BUTTON (widget)->active) - { - td->preview = TRUE; - threshold_preview (td); - } - else - { - td->preview = FALSE; - if (td->image_map) - { - active_tool->preserve = TRUE; - image_map_clear (td->image_map); - active_tool->preserve = FALSE; - gdisplays_flush (); - } - } -} - -static void -threshold_low_threshold_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - if (td->low_threshold != adjustment->value) - { - td->low_threshold = adjustment->value; - - threshold_update (td, HISTOGRAM); - - if (td->preview) - threshold_preview (td); - } -} - -static void -threshold_high_threshold_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - if (td->high_threshold != adjustment->value) - { - td->high_threshold = adjustment->value; - - threshold_update (td, HISTOGRAM); - - if (td->preview) - threshold_preview (td); - } -} - -static void -threshold_histogram_range (HistogramWidget *widget, - gint start, - gint end, - gpointer data) -{ - ThresholdDialog *td; - - td = (ThresholdDialog *) data; - - td->low_threshold = start; - td->high_threshold = end; - - threshold_update (td, LOW | HIGH); - - if (td->preview) - threshold_preview (td); -} diff --git a/app/threshold.h b/app/threshold.h deleted file mode 100644 index 92f8934157..0000000000 --- a/app/threshold.h +++ /dev/null @@ -1,56 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __THRESHOLD_H__ -#define __THRESHOLD_H__ - - -typedef struct _ThresholdDialog ThresholdDialog; - -struct _ThresholdDialog -{ - GtkWidget *shell; - - GtkAdjustment *low_threshold_data; - GtkAdjustment *high_threshold_data; - - HistogramWidget *histogram; - GimpHistogram *hist; - - GimpDrawable *drawable; - ImageMap image_map; - - gint color; - gint low_threshold; - gint high_threshold; - - gboolean preview; -}; - - -Tool * tools_new_threshold (void); -void tools_free_threshold (Tool *tool); - -void threshold_dialog_hide (void); -void threshold_initialize (GDisplay *gdisp); -void threshold_2 (gpointer data, - PixelRegion *srcPR, - PixelRegion *destPR); - - -#endif /* __THRESHOLD_H__ */ diff --git a/app/tool_options.c b/app/tool_options.c deleted file mode 100644 index 25eb1ec7fd..0000000000 --- a/app/tool_options.c +++ /dev/null @@ -1,971 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "brush_select.h" -#include "gimpcontext.h" -#include "gimprc.h" -#include "gimpui.h" -#include "paint_funcs.h" -#include "paint_options.h" -#include "selection_options.h" -#include "gtkhwrapbox.h" - -#include "libgimp/gimpunitmenu.h" - -#include "libgimp/gimpintl.h" - - -/* declared extern in paint_options.h */ -PaintPressureOptions non_gui_pressure_options = -{ - NULL, - FALSE, FALSE, NULL, - FALSE, FALSE, NULL, - FALSE, FALSE, NULL, - FALSE, FALSE, NULL, - FALSE, FALSE, NULL -}; - - -/* a list of all PaintOptions */ -static GSList *paint_options_list = NULL; - -static PaintPressureOptions * paint_pressure_options_new (ToolType); -static void paint_pressure_options_reset (PaintPressureOptions *); - - -/* ui helper functions ******************************************************/ - -static void -tool_options_opacity_adjustment_update (GtkAdjustment *adjustment, - gpointer data) -{ - gtk_signal_handler_block_by_data (GTK_OBJECT (data), adjustment); - gimp_context_set_opacity (GIMP_CONTEXT (data), - adjustment->value / 100); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (data), adjustment); -} - -static void -tool_options_opacity_changed (GimpContext *context, - gdouble opacity, - gpointer data) -{ - gtk_signal_handler_block_by_data (GTK_OBJECT (data), context); - gtk_adjustment_set_value (GTK_ADJUSTMENT (data), opacity * 100); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (data), context); -} - -static void -tool_options_paint_mode_update (GtkWidget *widget, - gpointer data) -{ - LayerModeEffects paint_mode; - PaintOptions *options; - - paint_mode = (LayerModeEffects) gtk_object_get_user_data (GTK_OBJECT (widget)); - options = (PaintOptions *) data; - - gtk_signal_handler_block_by_data (GTK_OBJECT (options->context), - options->paint_mode_w); - gimp_context_set_paint_mode (GIMP_CONTEXT (options->context), paint_mode); - gtk_signal_handler_unblock_by_data (GTK_OBJECT (options->context), - options->paint_mode_w); -} - -static void -tool_options_paint_mode_changed (GimpContext *context, - LayerModeEffects paint_mode, - gpointer data) -{ - gimp_option_menu_set_history (GTK_OPTION_MENU (data), (gpointer) paint_mode); -} - -/* tool options functions ***************************************************/ - -void -tool_options_init (ToolOptions *options, - gchar *title, - ToolOptionsResetFunc reset_func) -{ - options->main_vbox = gtk_vbox_new (FALSE, 2); - options->title = title; - options->reset_func = reset_func; -} - -ToolOptions * -tool_options_new (gchar *title) -{ - ToolOptions *options; - - GtkWidget *label; - - options = g_new (ToolOptions, 1); - tool_options_init (options, title, NULL); - - label = gtk_label_new (_("This tool has no options.")); - gtk_box_pack_start (GTK_BOX (options->main_vbox), label, FALSE, FALSE, 6); - gtk_widget_show (label); - - return options; -} - -/* selection tool options functions *****************************************/ - -void -selection_options_init (SelectionOptions *options, - ToolType tool_type, - ToolOptionsResetFunc reset_func) -{ - GtkWidget *vbox; - GtkWidget *abox; - GtkWidget *table; - GtkWidget *label; - GtkWidget *scale; - GtkWidget *separator; - - /* initialize the tool options structure */ - tool_options_init ((ToolOptions *) options, - ((tool_type == RECT_SELECT) ? - _("Rectangular Selection") : - ((tool_type == ELLIPSE_SELECT) ? - _("Elliptical Selection") : - ((tool_type == FREE_SELECT) ? - _("Free-Hand Selection") : - ((tool_type == FUZZY_SELECT) ? - _("Fuzzy Selection") : - ((tool_type == BEZIER_SELECT) ? - _("Bezier Selection") : - ((tool_type == ISCISSORS) ? - _("Intelligent Scissors") : - ((tool_type == BY_COLOR_SELECT) ? - _("By-Color Selection") : - "ERROR: Unknown Select Tool Type"))))))), - reset_func); - - /* the main vbox */ - vbox = options->tool_options.main_vbox; - - /* initialize the selection options structure */ - options->feather = options->feather_d = FALSE; - options->feather_radius = options->feather_radius_d = 10.0; - options->antialias = options->antialias_d = TRUE; - options->sample_merged = options->sample_merged_d = FALSE; - options->threshold = default_threshold; - options->fixed_size = options->fixed_size_d = FALSE; - options->fixed_height = options->fixed_height_d = 1; - options->fixed_width = options->fixed_width_d = 1; - options->fixed_unit = options->fixed_unit_d = GIMP_UNIT_PIXEL; - options->interactive = options->interactive_d = FALSE; - - options->feather_w = NULL; - options->feather_radius_w = NULL; - options->antialias_w = NULL; - options->sample_merged_w = NULL; - options->threshold_w = NULL; - options->fixed_size_w = NULL; - options->fixed_height_w = NULL; - options->fixed_width_w = NULL; - options->fixed_unit_w = NULL; - options->interactive_w = NULL; - - /* the feather toggle button */ - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); - - options->feather_w = gtk_check_button_new_with_label (_("Feather")); - gtk_table_attach (GTK_TABLE (table), options->feather_w, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->feather_w), - options->feather_d); - gtk_signal_connect (GTK_OBJECT (options->feather_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->feather); - gtk_widget_show (options->feather_w); - - /* the feather radius scale */ - label = gtk_label_new (_("Radius:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); - gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 0, 2, - GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (abox); - - options->feather_radius_w = - gtk_adjustment_new (options->feather_radius_d, 0.0, 100.0, 1.0, 1.0, 1.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->feather_radius_w)); - gtk_container_add (GTK_CONTAINER (abox), scale); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->feather_radius_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->feather_radius); - gtk_widget_show (scale); - - /* grey out label & scale if feather is off */ - gtk_widget_set_sensitive (scale, options->feather_d); - gtk_widget_set_sensitive (label, options->feather_d); - gtk_object_set_data (GTK_OBJECT (options->feather_w), "set_sensitive", scale); - gtk_object_set_data (GTK_OBJECT (scale), "set_sensitive", label); - - gtk_widget_show (table); - - /* the antialias toggle button */ - if (tool_type != RECT_SELECT) - { - options->antialias_w = gtk_check_button_new_with_label (_("Antialiasing")); - gtk_box_pack_start (GTK_BOX (vbox), options->antialias_w, FALSE, FALSE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->antialias_w), - options->antialias_d); - gtk_signal_connect (GTK_OBJECT (options->antialias_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->antialias); - gtk_widget_show (options->antialias_w); - } - - /* a separator between the common and tool-specific selection options */ - switch (tool_type) - { - case FREE_SELECT: - case BEZIER_SELECT: - break; - - case ISCISSORS: - case RECT_SELECT: - case ELLIPSE_SELECT: - case FUZZY_SELECT: - case BY_COLOR_SELECT: - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); - gtk_widget_show (separator); - break; - default: - break; - } - - /* selection tool with an interactive boundary that can be toggled */ - if (tool_type == ISCISSORS) - { - options->interactive_w = - gtk_check_button_new_with_label (_("Show Interactive Boundary")); - - gtk_box_pack_start (GTK_BOX (vbox), options->interactive_w, - FALSE, FALSE, 0); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->interactive_w), - options->interactive_d); - gtk_signal_connect (GTK_OBJECT (options->interactive_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->interactive); - gtk_widget_show (options->interactive_w); - } - - /* selection tools which operate on contiguous regions */ - if (tool_type == FUZZY_SELECT) - { - GtkWidget *hbox; - - /* the sample merged toggle */ - options->sample_merged_w = - gtk_check_button_new_with_label (_("Sample Merged")); - gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, - FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->sample_merged); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w), - options->sample_merged_d); - gtk_widget_show (options->sample_merged_w); - - /* the threshold scale */ - hbox = gtk_hbox_new (FALSE, 1); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - label = gtk_label_new (_("Threshold:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); - gtk_widget_show (label); - - options->threshold_w = - gtk_adjustment_new (default_threshold, 0.0, 255.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w)); - gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->threshold_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->threshold); - gtk_widget_show (scale); - } - - /* widgets for fixed size select */ - if (tool_type == RECT_SELECT || tool_type == ELLIPSE_SELECT) - { - GtkWidget *alignment; - GtkWidget *table; - GtkWidget *width_spinbutton; - GtkWidget *height_spinbutton; - - options->fixed_size_w = - gtk_check_button_new_with_label (_("Fixed Size / Aspect Ratio")); - gtk_box_pack_start (GTK_BOX (vbox), options->fixed_size_w, - FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->fixed_size_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->fixed_size); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->fixed_size_w), - options->fixed_size_d); - gtk_widget_show (options->fixed_size_w); - - alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); - gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0); - gtk_widget_show (alignment); - - table = gtk_table_new (3, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_table_set_row_spacings (GTK_TABLE (table), 1); - gtk_container_add (GTK_CONTAINER (alignment), table); - - /* grey out the table if fixed size is off */ - gtk_widget_set_sensitive (table, options->fixed_size_d); - gtk_object_set_data (GTK_OBJECT (options->fixed_size_w), "set_sensitive", - table); - - options->fixed_width_w = - gtk_adjustment_new (options->fixed_width_d, 1e-5, 32767.0, - 1.0, 50.0, 0.0); - width_spinbutton = - gtk_spin_button_new (GTK_ADJUSTMENT (options->fixed_width_w), 1.0, 0.0); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON(width_spinbutton), - GTK_SHADOW_NONE); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width_spinbutton), TRUE); - gtk_widget_set_usize (width_spinbutton, 75, 0); - gtk_signal_connect (GTK_OBJECT (options->fixed_width_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->fixed_width); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, - _("Width:"), 1.0, 0.5, - width_spinbutton, 1, FALSE); - - options->fixed_height_w = - gtk_adjustment_new (options->fixed_height_d, 1e-5, 32767.0, - 1.0, 50.0, 0.0); - height_spinbutton = - gtk_spin_button_new (GTK_ADJUSTMENT (options->fixed_height_w), 1.0, 0.0); - gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON(height_spinbutton), - GTK_SHADOW_NONE); - gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(height_spinbutton), TRUE); - gtk_widget_set_usize (height_spinbutton, 75, 0); - gtk_signal_connect (GTK_OBJECT (options->fixed_height_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->fixed_height); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Height:"), 1.0, 0.5, - height_spinbutton, 1, FALSE); - - options->fixed_unit_w = - gimp_unit_menu_new ("%a", options->fixed_unit_d, TRUE, TRUE, TRUE); - gtk_signal_connect (GTK_OBJECT (options->fixed_unit_w), "unit_changed", - GTK_SIGNAL_FUNC (gimp_unit_menu_update), - &options->fixed_unit); - gtk_object_set_data (GTK_OBJECT (options->fixed_unit_w), "set_digits", - width_spinbutton); - gtk_object_set_data (GTK_OBJECT (width_spinbutton), "set_digits", - height_spinbutton); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, - _("Unit:"), 1.0, 0.5, - options->fixed_unit_w, 1, FALSE); - - gtk_widget_show (table); - } -} - -SelectionOptions * -selection_options_new (ToolType tool_type, - ToolOptionsResetFunc reset_func) -{ - SelectionOptions *options; - - options = g_new (SelectionOptions, 1); - selection_options_init (options, tool_type, reset_func); - - return options; -} - -void -selection_options_reset (SelectionOptions *options) -{ - if (options->feather_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->feather_w), - options->feather_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->feather_radius_w), - options->feather_radius_d); - } - - if (options->antialias_w) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->antialias_w), - options->antialias_d); - - if (options->sample_merged_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w), - options->sample_merged_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->threshold_w), - default_threshold); - } - - if (options->fixed_size_w) - { - GtkWidget *spinbutton; - gint digits; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(options->fixed_size_w), - options->fixed_size_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->fixed_width_w), - options->fixed_width_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->fixed_height_w), - options->fixed_height_d); - - options->fixed_unit = options->fixed_unit_d; - gimp_unit_menu_set_unit (GIMP_UNIT_MENU (options->fixed_unit_w), - options->fixed_unit_d); - - digits = - ((options->fixed_unit_d == GIMP_UNIT_PIXEL) ? 0 : - ((options->fixed_unit_d == GIMP_UNIT_PERCENT) ? 2 : - (MIN (6, MAX (3, gimp_unit_get_digits (options->fixed_unit_d)))))); - - spinbutton = - gtk_object_get_data (GTK_OBJECT (options->fixed_unit_w), "set_digits"); - while (spinbutton) - { - gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), digits); - spinbutton = - gtk_object_get_data (GTK_OBJECT (spinbutton), "set_digits"); - } - } - - if (options->interactive_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->interactive_w), - options->interactive_d); - } -} - - -/* paint tool options functions *********************************************/ - -void -paint_options_init (PaintOptions *options, - ToolType tool_type, - ToolOptionsResetFunc reset_func) -{ - GtkWidget *vbox; - GtkWidget *table; - GtkWidget *scale; - GtkWidget *separator; - - GimpContext *tool_context = tool_info[tool_type].tool_context; - - /* initialize the tool options structure */ - tool_options_init ((ToolOptions *) options, - ((tool_type == BUCKET_FILL) ? - _("Bucket Fill") : - ((tool_type == BLEND) ? - _("Blend Tool") : - ((tool_type == PENCIL) ? - _("Pencil") : - ((tool_type == PAINTBRUSH) ? - _("Paintbrush") : - ((tool_type == ERASER) ? - _("Eraser") : - ((tool_type == AIRBRUSH) ? - _("Airbrush") : - ((tool_type == CLONE) ? - _("Clone Tool") : - ((tool_type == CONVOLVE) ? - _("Convolver") : - ((tool_type == INK) ? - _("Ink Tool") : - ((tool_type == DODGEBURN) ? - _("Dodge or Burn") : - ((tool_type == SMUDGE) ? - _("Smudge Tool") : -/* ((tool_type == XINPUT_AIRBRUSH) ? */ -/* _("Xinput Airbrush") : */ - "ERROR: Unknown Paint Tool Type"))))))))))), - reset_func); - - /* initialize the paint options structure */ - options->global = NULL; - options->opacity_w = NULL; - options->paint_mode_w = NULL; - options->context = tool_context; - options->incremental_w = NULL; - options->incremental = options->incremental_d = FALSE; - options->pressure_options = NULL; - - /* the main vbox */ - vbox = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), vbox, - FALSE, FALSE, 0); - options->paint_vbox = vbox; - - /* the main table */ - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); - gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); - - /* the opacity scale */ - options->opacity_w = - gtk_adjustment_new (gimp_context_get_opacity (tool_context) * 100, - 0.0, 100.0, 1.0, 1.0, 0.0); - scale = gtk_hscale_new (GTK_ADJUSTMENT (options->opacity_w)); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->opacity_w), "value_changed", - GTK_SIGNAL_FUNC (tool_options_opacity_adjustment_update), - tool_context); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, - _("Opacity:"), 1.0, 1.0, - scale, 1, FALSE); - - gtk_signal_connect (GTK_OBJECT (tool_context), "opacity_changed", - GTK_SIGNAL_FUNC (tool_options_opacity_changed), - options->opacity_w); - - /* the paint mode menu */ - switch (tool_type) - { - case BUCKET_FILL: - case BLEND: - case PENCIL: - case PAINTBRUSH: - case AIRBRUSH: - case CLONE: - case INK: -/* case XINPUT_AIRBRUSH: */ - gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); - - options->paint_mode_w = - paint_mode_menu_new (tool_options_paint_mode_update, options, - gimp_context_get_paint_mode (tool_context)); - gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, - _("Mode:"), 1.0, 0.5, - options->paint_mode_w, 1, TRUE); - - gtk_signal_connect (GTK_OBJECT (tool_context), "paint_mode_changed", - GTK_SIGNAL_FUNC (tool_options_paint_mode_changed), - options->paint_mode_w); - break; - case CONVOLVE: - case ERASER: - case DODGEBURN: - case SMUDGE: - break; - default: - break; - } - - /* show the main table */ - gtk_widget_show (table); - - /* a separator after the common paint options which can be global */ - switch (tool_type) - { - case BUCKET_FILL: - case BLEND: - case INK: - /* case XINPUT_AIRBRUSH: */ - separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); - gtk_widget_show (separator); - break; - case PENCIL: - case PAINTBRUSH: - case ERASER: - case AIRBRUSH: - case CLONE: - case CONVOLVE: - case DODGEBURN: - case SMUDGE: - break; - default: - break; - } - - if (! global_paint_options) - gtk_widget_show (vbox); - - /* the "incremental" toggle */ - switch (tool_type) - { - case AIRBRUSH: - case ERASER: - case PAINTBRUSH: - case PENCIL: - options->incremental_w = - gtk_check_button_new_with_label (_("Incremental")); - gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), - options->incremental_w, FALSE, FALSE, 0); - gtk_signal_connect (GTK_OBJECT (options->incremental_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->incremental); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->incremental_w), - options->incremental_d); - gtk_widget_show (options->incremental_w); - - case BUCKET_FILL: - case BLEND: - case CLONE: - case CONVOLVE: - case DODGEBURN: - case SMUDGE: - break; - default: - break; - } - - options->pressure_options = paint_pressure_options_new (tool_type); - - if (options->pressure_options->frame) - { - gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), - options->pressure_options->frame, FALSE, FALSE, 0); - gtk_widget_show (options->pressure_options->frame); - } - - /* register this Paintoptions structure */ - paint_options_list = g_slist_prepend (paint_options_list, options); -} - -PaintOptions * -paint_options_new (ToolType tool_type, - ToolOptionsResetFunc reset_func) -{ - PaintOptions *options; - - options = g_new (PaintOptions, 1); - paint_options_init (options, tool_type, reset_func); - - if (global_paint_options && options->global) - gtk_widget_show (options->global); - - return options; -} - -void -paint_options_reset (PaintOptions *options) -{ - GimpContext *default_context; - - default_context = gimp_context_get_default (); - - if (options->opacity_w) - { - gimp_context_set_opacity (GIMP_CONTEXT (options->context), - gimp_context_get_opacity (default_context)); - } - if (options->paint_mode_w) - { - gimp_context_set_paint_mode (GIMP_CONTEXT (options->context), - gimp_context_get_paint_mode (default_context)); - } - if (options->incremental_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->incremental_w), - options->incremental_d); - } - - paint_pressure_options_reset (options->pressure_options); -} - -static PaintPressureOptions * -paint_pressure_options_new (ToolType tool_type) -{ - PaintPressureOptions *pressure = NULL; - GtkWidget *frame = NULL; - GtkWidget *wbox = NULL; - - pressure = g_new (PaintPressureOptions, 1); - - pressure->opacity = pressure->opacity_d = TRUE; - pressure->pressure = pressure->pressure_d = TRUE; - pressure->rate = pressure->rate_d = FALSE; - pressure->size = pressure->size_d = FALSE; - pressure->color = pressure->color_d = FALSE; - - pressure->opacity_w = NULL; - pressure->pressure_w = NULL; - pressure->rate_w = NULL; - pressure->size_w = NULL; - pressure->color_w = NULL; - - switch (tool_type) - { - case AIRBRUSH: - case CLONE: - case CONVOLVE: - case DODGEBURN: - case ERASER: - case PAINTBRUSH: - case PENCIL: - case SMUDGE: - frame = gtk_frame_new (_("Pressure Sensitivity")); - wbox = gtk_hwrap_box_new (FALSE); - gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (wbox), 6); - gtk_container_add (GTK_CONTAINER (frame), wbox); - gtk_widget_show (wbox); - break; - default: - break; - } - - /* the opacity toggle */ - switch (tool_type) - { - case CLONE: - case DODGEBURN: - case ERASER: - case PAINTBRUSH: - case PENCIL: - pressure->opacity_w = - gtk_check_button_new_with_label (_("Opacity")); - gtk_container_add (GTK_CONTAINER (wbox), pressure->opacity_w); - gtk_signal_connect (GTK_OBJECT (pressure->opacity_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &pressure->opacity); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->opacity_w), - pressure->opacity_d); - gtk_widget_show (pressure->opacity_w); - break; - default: - break; - } - - /* the pressure toggle */ - switch (tool_type) - { - case AIRBRUSH: - case CLONE: - case CONVOLVE: - case DODGEBURN: - case ERASER: - case PAINTBRUSH: - case SMUDGE: - pressure->pressure_w = gtk_check_button_new_with_label (_("Hardness")); - gtk_container_add (GTK_CONTAINER (wbox), pressure->pressure_w); - gtk_signal_connect (GTK_OBJECT (pressure->pressure_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &pressure->pressure); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->pressure_w), - pressure->pressure_d); - gtk_widget_show (pressure->pressure_w); - break; - default: - break; - } - - /* the rate toggle */ - switch (tool_type) - { - case AIRBRUSH: - case CONVOLVE: - case SMUDGE: - pressure->rate_w = - gtk_check_button_new_with_label (_("Rate")); - gtk_container_add (GTK_CONTAINER (wbox), pressure->rate_w); - gtk_signal_connect (GTK_OBJECT (pressure->rate_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &pressure->rate); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->rate_w), - pressure->rate_d); - gtk_widget_show (pressure->rate_w); - break; - default: - break; - } - - /* the size toggle */ - switch (tool_type) - { - case AIRBRUSH: - case CLONE: - case CONVOLVE: - case DODGEBURN: - case ERASER: - case PAINTBRUSH: - case PENCIL: - pressure->size_w = - gtk_check_button_new_with_label (_("Size")); - gtk_container_add (GTK_CONTAINER (wbox), pressure->size_w); - gtk_signal_connect (GTK_OBJECT (pressure->size_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &pressure->size); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->size_w), - pressure->size_d); - gtk_widget_show (pressure->size_w); - break; - default: - break; - } - - /* the color toggle */ - switch (tool_type) - { - case AIRBRUSH: - case PAINTBRUSH: - case PENCIL: - pressure->color_w = - gtk_check_button_new_with_label (_("Color")); - gtk_container_add (GTK_CONTAINER (wbox), pressure->color_w); - gtk_signal_connect (GTK_OBJECT (pressure->color_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &pressure->color); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->color_w), - pressure->color_d); - gtk_widget_show (pressure->color_w); - break; - default: - break; - } - - pressure->frame = frame; - - return pressure; -} - -static void -paint_pressure_options_reset (PaintPressureOptions *pressure) -{ - if (pressure->opacity_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->opacity_w), - pressure->opacity_d); - } - if (pressure->pressure_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->pressure_w), - pressure->pressure_d); - } - if (pressure->rate_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->rate_w), - pressure->rate_d); - } - if (pressure->size_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->size_w), - pressure->size_d); - } - if (pressure->color_w) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pressure->color_w), - pressure->color_d); - } -} - - -/* global paint options functions *******************************************/ - -void -paint_options_set_global (gboolean global) -{ - PaintOptions *options; - GSList *list; - - global = global ? TRUE : FALSE; - - if (global_paint_options == global) - return; - - global_paint_options = global; - - for (list = paint_options_list; list; list = list->next) - { - options = (PaintOptions *) list->data; - - if (global) - { - if (options->paint_vbox && GTK_WIDGET_VISIBLE (options->paint_vbox)) - gtk_widget_hide (options->paint_vbox); - if (options->global && ! GTK_WIDGET_VISIBLE (options->global)) - gtk_widget_show (options->global); - } - else - { - if (options->paint_vbox && ! GTK_WIDGET_VISIBLE (options->paint_vbox)) - gtk_widget_show (options->paint_vbox); - if (options->global && GTK_WIDGET_VISIBLE (options->global)) - gtk_widget_hide (options->global); - } - } - - /* NULL means the main brush selection */ - brush_select_show_paint_options (NULL, global); -} - - -/* create a paint mode menu *************************************************/ - -GtkWidget * -paint_mode_menu_new (GtkSignalFunc callback, - gpointer data, - LayerModeEffects initial) -{ - GtkWidget *menu; - - menu = gimp_option_menu_new2 - (FALSE, callback, data, (gpointer) initial, - - _("Normal"), (gpointer) NORMAL_MODE, NULL, - _("Dissolve"), (gpointer) DISSOLVE_MODE, NULL, - _("Behind"), (gpointer) BEHIND_MODE, NULL, - _("Multiply"), (gpointer) MULTIPLY_MODE, NULL, - _("Divide"), (gpointer) DIVIDE_MODE, NULL, - _("Screen"), (gpointer) SCREEN_MODE, NULL, - _("Overlay"), (gpointer) OVERLAY_MODE, NULL, - _("Dodge"), (gpointer) DODGE_MODE, NULL, - _("Burn"), (gpointer) BURN_MODE, NULL, - _("Hard Light"), (gpointer) HARDLIGHT_MODE, NULL, - _("Difference"), (gpointer) DIFFERENCE_MODE, NULL, - _("Addition"), (gpointer) ADDITION_MODE, NULL, - _("Subtract"), (gpointer) SUBTRACT_MODE, NULL, - _("Darken Only"), (gpointer) DARKEN_ONLY_MODE, NULL, - _("Lighten Only"), (gpointer) LIGHTEN_ONLY_MODE, NULL, - _("Hue"), (gpointer) HUE_MODE, NULL, - _("Saturation"), (gpointer) SATURATION_MODE, NULL, - _("Color"), (gpointer) COLOR_MODE, NULL, - _("Value"), (gpointer) VALUE_MODE, NULL, - - NULL); - - return menu; -} diff --git a/app/tool_options.h b/app/tool_options.h deleted file mode 100644 index fe00fa2fe9..0000000000 --- a/app/tool_options.h +++ /dev/null @@ -1,47 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __TOOL_OPTIONS_H__ -#define __TOOL_OPTIONS_H__ - - -/* the tool options structures */ - -struct _ToolOptions -{ - GtkWidget *main_vbox; - gchar *title; - - ToolOptionsResetFunc reset_func; -}; - - -/* create a dummy tool options structure - * (to be used by tools without options) - */ -ToolOptions * tool_options_new (gchar *title); - -/* initialize an already allocated ToolOptions structure - * (to be used by derived tool options only) - */ -void tool_options_init (ToolOptions *options, - gchar *title, - ToolOptionsResetFunc reset_func); - - -#endif /* __TOOL_OPTIONS_H__ */ diff --git a/app/tools.c b/app/tools.c deleted file mode 100644 index 6ea915e3f3..0000000000 --- a/app/tools.c +++ /dev/null @@ -1,1762 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "airbrush.h" -#include "bezier_select.h" -#include "blend.h" -#include "brightness_contrast.h" -#include "bucket_fill.h" -#include "by_color_select.h" -#include "clone.h" -#include "color_balance.h" -#include "color_picker.h" -#include "context_manager.h" -#include "convolve.h" -#include "crop.h" -#include "curves.h" -#include "dodgeburn.h" -#include "eraser.h" -#include "gdisplay.h" -#include "gimpcontext.h" -#include "gimpdnd.h" -#include "gimpimage.h" -#include "gimpui.h" -#include "hue_saturation.h" -#include "ellipse_select.h" -#include "flip_tool.h" -#include "free_select.h" -#include "fuzzy_select.h" -#include "histogram_tool.h" -#include "ink.h" -#include "iscissors.h" -#include "levels.h" -#include "magnify.h" -#include "measure.h" -#include "move.h" -#include "paintbrush.h" -/* #include "path_tool.h" */ -#include "pencil.h" -#include "posterize.h" -#include "rect_select.h" -#include "session.h" -#include "smudge.h" -/* #include "xinput_airbrush.h" */ -#include "text_tool.h" -#include "threshold.h" -#include "tools.h" -#include "tool_options.h" -#include "transform_tool.h" -#include "dialog_handler.h" - -#include "libgimp/gimpintl.h" - -#include "pixmaps2.h" - -#include "cursors/rect_select_small.xbm" -#include "cursors/rect_select_small_mask.xbm" -#include "cursors/ellipse_select_small.xbm" -#include "cursors/ellipse_select_small_mask.xbm" -#include "cursors/free_select_small.xbm" -#include "cursors/free_select_small_mask.xbm" -#include "cursors/fuzzy_select_small.xbm" -#include "cursors/fuzzy_select_small_mask.xbm" -#include "cursors/bezier_select_small.xbm" -#include "cursors/bezier_select_small_mask.xbm" -#include "cursors/scissors_small.xbm" -#include "cursors/scissors_small_mask.xbm" -#include "cursors/move_small.xbm" -#include "cursors/move_small_mask.xbm" -#include "cursors/zoom_small.xbm" -#include "cursors/zoom_small_mask.xbm" -#include "cursors/crop_small.xbm" -#include "cursors/crop_small_mask.xbm" -#include "cursors/resize_small.xbm" -#include "cursors/resize_small_mask.xbm" -#include "cursors/rotate_small.xbm" -#include "cursors/rotate_small_mask.xbm" -#include "cursors/shear_small.xbm" -#include "cursors/shear_small_mask.xbm" -#include "cursors/perspective_small.xbm" -#include "cursors/perspective_small_mask.xbm" -#include "cursors/flip_horizontal_small.xbm" -#include "cursors/flip_horizontal_small_mask.xbm" -#include "cursors/flip_vertical_small.xbm" -#include "cursors/flip_vertical_small_mask.xbm" -#include "cursors/text_small.xbm" -#include "cursors/text_small_mask.xbm" -#include "cursors/dropper_small.xbm" -#include "cursors/dropper_small_mask.xbm" -#include "cursors/bucket_fill_small.xbm" -#include "cursors/bucket_fill_small_mask.xbm" -#include "cursors/blend_small.xbm" -#include "cursors/blend_small_mask.xbm" -#include "cursors/pencil_small.xbm" -#include "cursors/pencil_small_mask.xbm" -#include "cursors/paintbrush_small.xbm" -#include "cursors/paintbrush_small_mask.xbm" -#include "cursors/eraser_small.xbm" -#include "cursors/eraser_small_mask.xbm" -#include "cursors/airbrush_small.xbm" -#include "cursors/airbrush_small_mask.xbm" -#include "cursors/clone_small.xbm" -#include "cursors/clone_small_mask.xbm" -#include "cursors/blur_small.xbm" -#include "cursors/blur_small_mask.xbm" -#include "cursors/ink_small.xbm" -#include "cursors/ink_small_mask.xbm" -#include "cursors/dodge_small.xbm" -#include "cursors/dodge_small_mask.xbm" -#include "cursors/burn_small.xbm" -#include "cursors/burn_small_mask.xbm" -#include "cursors/smudge_small.xbm" -#include "cursors/smudge_small_mask.xbm" -#include "cursors/measure_small.xbm" -#include "cursors/measure_small_mask.xbm" - - -/* Global Data */ -Tool * active_tool = NULL; - -/* Local Data */ -static GtkWidget * options_shell = NULL; -static GtkWidget * options_vbox = NULL; -static GtkWidget * options_label = NULL; -static GtkWidget * options_pixmap = NULL; -static GtkWidget * options_eventbox = NULL; -static GtkWidget * options_reset_button = NULL; - -static gint global_tool_ID = 0; - -ToolInfo tool_info[] = -{ - { - NULL, - N_("Rect Select"), - N_("/Tools/Select Tools/Rect Select"), - "R", - (char **) rect_bits, - NULL, - NULL, - N_("Select rectangular regions"), - "tools/rect_select.html", - RECT_SELECT, - tools_new_rect_select, - tools_free_rect_select, - NULL, - NULL, - NULL, - { - rect_select_small_bits, rect_select_small_mask_bits, - rect_select_small_width, rect_select_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Ellipse Select"), - N_("/Tools/Select Tools/Ellipse Select"), - "E", - (char **) circ_bits, - NULL, - NULL, - N_("Select elliptical regions"), - "tools/ellipse_select.html", - ELLIPSE_SELECT, - tools_new_ellipse_select, - tools_free_ellipse_select, - NULL, - NULL, - NULL, - { - ellipse_select_small_bits, ellipse_select_small_mask_bits, - ellipse_select_small_width, ellipse_select_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Free Select"), - N_("/Tools/Select Tools/Free Select"), - "F", - (char **) free_bits, - NULL, - NULL, - N_("Select hand-drawn regions"), - "tools/free_select.html", - FREE_SELECT, - tools_new_free_select, - tools_free_free_select, - NULL, - NULL, - NULL, - { - free_select_small_bits, free_select_small_mask_bits, - free_select_small_width, free_select_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Fuzzy Select"), - N_("/Tools/Select Tools/Fuzzy Select"), - "Z", - (char **) fuzzy_bits, - NULL, - NULL, - N_("Select contiguous regions"), - "tools/fuzzy_select.html", - FUZZY_SELECT, - tools_new_fuzzy_select, - tools_free_fuzzy_select, - NULL, - NULL, - NULL, - { - fuzzy_select_small_bits, fuzzy_select_small_mask_bits, - fuzzy_select_small_width, fuzzy_select_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Bezier Select"), - N_("/Tools/Select Tools/Bezier Select"), - "B", - (char **) bezier_bits, - NULL, - NULL, - N_("Select regions using Bezier curves"), - "tools/bezier_select.html", - BEZIER_SELECT, - tools_new_bezier_select, - tools_free_bezier_select, - NULL, - NULL, - NULL, - { - bezier_select_small_bits, bezier_select_small_mask_bits, - bezier_select_small_width, bezier_select_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Intelligent Scissors"), - N_("/Tools/Select Tools/Intelligent Scissors"), - "I", - (char **) iscissors_bits, - NULL, - NULL, - N_("Select shapes from image"), - "tools/intelligent_scissors.html", - ISCISSORS, - tools_new_iscissors, - tools_free_iscissors, - NULL, - NULL, - NULL, - { - scissors_small_bits, scissors_small_mask_bits, - scissors_small_width, scissors_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Move"), - N_("/Tools/Transform Tools/Move"), - "M", - (char **) move_bits, - NULL, - NULL, - N_("Move layers & selections"), - "tools/move.html", - MOVE, - tools_new_move_tool, - tools_free_move_tool, - NULL, - NULL, - NULL, - { - move_small_bits, move_small_mask_bits, - move_small_width, move_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Magnify"), - N_("/Tools/Transform Tools/Magnify"), - "M", - (char **) magnify_bits, - NULL, - NULL, - N_("Zoom in & out"), - "tools/magnify.html", - MAGNIFY, - tools_new_magnify, - tools_free_magnify, - NULL, - NULL, - NULL, - { - zoom_small_bits, zoom_small_mask_bits, - zoom_small_width, zoom_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Crop & Resize"), - N_("/Tools/Transform Tools/Crop & Resize"), - "C", - (char **) crop_bits, - NULL, - NULL, - N_("Crop or resize the image"), - "tools/crop.html", - CROP, - tools_new_crop, - tools_free_crop, - NULL, - NULL, - NULL, - { - crop_small_bits, crop_small_mask_bits, - crop_small_width, crop_small_height, - 0, 0, NULL, NULL, NULL - }, - { - resize_small_bits, resize_small_mask_bits, - resize_small_width, resize_small_height, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Transform"), - N_("/Tools/Transform Tools/Transform"), - "T", - (char **) scale_bits, - NULL, - NULL, - N_("Rotation, scaling, shearing, perspective."), - "tools/transform.html", - ROTATE, - tools_new_transform_tool, - tools_free_transform_tool, - NULL, - NULL, - NULL, - { - rotate_small_bits, rotate_small_mask_bits, - rotate_small_width, rotate_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, /* rotate */ - - { - NULL, - N_("Transform"), - NULL, - NULL, - (char **) scale_bits, - NULL, - NULL, - N_("Rotation, scaling, shearing, perspective."), - "tools/transform.html", - SCALE, - tools_new_transform_tool, - tools_free_transform_tool, - NULL, - NULL, - NULL, - { - resize_small_bits, resize_small_mask_bits, - resize_small_width, resize_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, /* scale */ - - { - NULL, - N_("Transform"), - NULL, - NULL, - (char **) scale_bits, - NULL, - NULL, - N_("Rotation, scaling, shearing, perspective."), - "tools/transform.html", - SHEAR, - tools_new_transform_tool, - tools_free_transform_tool, - NULL, - NULL, - NULL, - { - shear_small_bits, shear_small_mask_bits, - shear_small_width, shear_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, /* shear */ - - { - NULL, - N_("Transform"), - NULL, - NULL, - (char **) scale_bits, - NULL, - NULL, - N_("Rotation, scaling, shearing, perspective."), - "tools/transform.html", - PERSPECTIVE, - tools_new_transform_tool, - tools_free_transform_tool, - NULL, - NULL, - NULL, - { - perspective_small_bits, perspective_small_mask_bits, - perspective_small_width, perspective_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, /* perspective */ - - { - NULL, - N_("Flip"), - N_("/Tools/Transform Tools/Flip"), - "F", - (char **) flip_bits, - NULL, - NULL, - N_("Flip the layer or selection"), - "tools/flip.html", - FLIP, - tools_new_flip, - tools_free_flip_tool, - NULL, - NULL, - NULL, - { - flip_horizontal_small_bits, flip_horizontal_small_mask_bits, - flip_horizontal_small_width, flip_horizontal_small_height, - 0, 0, NULL, NULL, NULL - }, - { - flip_vertical_small_bits, flip_vertical_small_mask_bits, - flip_vertical_small_width, flip_vertical_small_height, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Text"), - N_("/Tools/Text"), - "T", - (char **) text_bits, - NULL, - NULL, - N_("Add text to the image"), - "tools/text.html", - TEXT, - tools_new_text, - tools_free_text, - NULL, - NULL, - NULL, - { - text_small_bits, text_small_mask_bits, - text_small_width, text_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Color Picker"), - N_("/Tools/Color Picker"), - "O", - (char **) colorpicker_bits, - NULL, - NULL, - N_("Pick colors from the image"), - "tools/color_picker.html", - COLOR_PICKER, - tools_new_color_picker, - tools_free_color_picker, - NULL, - NULL, - NULL, - { - dropper_small_bits, dropper_small_mask_bits, - dropper_small_width, dropper_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Bucket Fill"), - N_("/Tools/Paint Tools/Bucket Fill"), - "B", - (char **) fill_bits, - NULL, - NULL, - N_("Fill with a color or pattern"), - "tools/bucket_fill.html", - BUCKET_FILL, - tools_new_bucket_fill, - tools_free_bucket_fill, - NULL, - NULL, - NULL, - { - bucket_fill_small_bits, bucket_fill_small_mask_bits, - bucket_fill_small_width, bucket_fill_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Blend"), - N_("/Tools/Paint Tools/Blend"), - "L", - (char **) gradient_bits, - NULL, - NULL, - N_("Fill with a color gradient"), - "tools/blend.html", - BLEND, - tools_new_blend, - tools_free_blend, - NULL, - NULL, - NULL, - { - blend_small_bits, blend_small_mask_bits, - blend_small_width, blend_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Pencil"), - N_("/Tools/Paint Tools/Pencil"), - "P", - (char **) pencil_bits, - NULL, - NULL, - N_("Draw sharp pencil strokes"), - "tools/pencil.html", - PENCIL, - tools_new_pencil, - tools_free_pencil, - NULL, - NULL, - NULL, - { - pencil_small_bits, pencil_small_mask_bits, - pencil_small_width, pencil_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Paintbrush"), - N_("/Tools/Paint Tools/Paintbrush"), - "P", - (char **) paint_bits, - NULL, - NULL, - N_("Paint fuzzy brush strokes"), - "tools/paintbrush.html", - PAINTBRUSH, - tools_new_paintbrush, - tools_free_paintbrush, - NULL, - NULL, - NULL, - { - paintbrush_small_bits, paintbrush_small_mask_bits, - paintbrush_small_width, paintbrush_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Airbrush"), - N_("/Tools/Paint Tools/Airbrush"), - "A", - (char **) airbrush_bits, - NULL, - NULL, - N_("Airbrush with variable pressure"), - "tools/airbrush.html", - AIRBRUSH, - tools_new_airbrush, - tools_free_airbrush, - NULL, - NULL, - NULL, - { - airbrush_small_bits, airbrush_small_mask_bits, - airbrush_small_width, airbrush_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Ink"), - N_("/Tools/Paint Tools/Ink"), - "K", - (char **) ink_bits, - NULL, - NULL, - N_("Draw in ink"), - "tools/ink.html", - INK, - tools_new_ink, - tools_free_ink, - NULL, - NULL, - NULL, - { - ink_small_bits, ink_small_mask_bits, - ink_small_width, ink_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Clone"), - N_("/Tools/Paint Tools/Clone"), - "C", - (char **) clone_bits, - NULL, - NULL, - N_("Paint using patterns or image regions"), - "tools/clone.html", - CLONE, - tools_new_clone, - tools_free_clone, - NULL, - NULL, - NULL, - { - clone_small_bits, clone_small_mask_bits, - clone_small_width, clone_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Eraser"), - N_("/Tools/Paint Tools/Eraser"), - "E", - (char **) erase_bits, - NULL, - NULL, - N_("Erase to background or transparency"), - "tools/eraser.html", - ERASER, - tools_new_eraser, - tools_free_eraser, - NULL, - NULL, - NULL, - { - eraser_small_bits, eraser_small_mask_bits, - eraser_small_width, eraser_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Smudge"), - N_("/Tools/Paint Tools/Smudge"), - "S", - (char **) smudge_bits, - NULL, - NULL, - N_("Smudge"), - "tools/smudge.html", - SMUDGE, - tools_new_smudge, - tools_free_smudge, - NULL, - NULL, - NULL, - { - smudge_small_bits, smudge_small_mask_bits, - smudge_small_width, smudge_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Convolve"), - N_("/Tools/Paint Tools/Convolve"), - "V", - (char **) blur_bits, - NULL, - NULL, - N_("Blur or sharpen"), - "tools/convolve.html", - CONVOLVE, - tools_new_convolve, - tools_free_convolve, - NULL, - NULL, - NULL, - { - blur_small_bits, blur_small_mask_bits, - blur_small_width, blur_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Dodge or Burn"), - N_("/Tools/Paint Tools/DodgeBurn"), - "D", - (char **) dodge_bits, - NULL, - NULL, - N_("Dodge or Burn"), - "tools/dodgeburn.html", - DODGEBURN, - tools_new_dodgeburn, - tools_free_dodgeburn, - NULL, - NULL, - NULL, - { - dodge_small_bits, dodge_small_mask_bits, - dodge_small_width, dodge_small_height, - 0, 0, NULL, NULL, NULL - }, - { - burn_small_bits, burn_small_mask_bits, - burn_small_width, burn_small_height, - 0, 0, NULL, NULL, NULL - } - }, - -/* - { - NULL, - N_("Xinput Airbrush"), - N_("/Tools/Paint Tools/XinputAirbrush"), - "A", - (char **) xinput_airbrush_bits, - NULL, - NULL, - N_("Natural Airbrush"), - "tools/xinput_airbrush.html", - XINPUT_AIRBRUSH, - tools_new_xinput_airbrush, - tools_free_xinput_airbrush, - NULL, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, -*/ - - { - NULL, - N_("Measure"), - N_("/Tools/Measure"), - "", - (char **) measure_bits, - NULL, - NULL, - N_("Measure distances and angles"), - "tools/measure.html", - MEASURE, - tools_new_measure_tool, - tools_free_measure_tool, - NULL, - NULL, - NULL, - { - measure_small_bits, measure_small_mask_bits, - measure_small_width, measure_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - -/* - { - NULL, - N_("Path"), - N_("/Tools/Path"), - "", - (char **) path_tool_bits, - NULL, - NULL, - N_("Manipulate paths"), - "tools/path.html", - PATH_TOOL, - tools_new_path_tool, - tools_free_path_tool, - NULL, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, -*/ - - /* Non-toolbox tools */ - { - NULL, - N_("By Color Select"), - N_("/Select/By Color..."), - NULL, - (char **) by_color_select_bits, - NULL, - NULL, - N_("Select regions by color"), - "tools/by_color_select.html", - BY_COLOR_SELECT, - tools_new_by_color_select, - tools_free_by_color_select, - by_color_select_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Color Balance"), - N_("/Image/Colors/Color Balance..."), - NULL, - (char **) adjustment_bits, - NULL, - NULL, - N_("Adjust color balance"), - "tools/color_balance.html", - COLOR_BALANCE, - tools_new_color_balance, - tools_free_color_balance, - color_balance_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Brightness-Contrast"), - N_("/Image/Colors/Brightness-Contrast..."), - NULL, - (char **) adjustment_bits, - NULL, - NULL, - N_("Adjust brightness and contrast"), - "tools/brightness_contrast.html", - BRIGHTNESS_CONTRAST, - tools_new_brightness_contrast, - tools_free_brightness_contrast, - brightness_contrast_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Hue-Saturation"), - N_("/Image/Colors/Hue-Saturation..."), - NULL, - (char **) adjustment_bits, - NULL, - NULL, - N_("Adjust hue and saturation"), - "tools/hue_saturation.html", - HUE_SATURATION, - tools_new_hue_saturation, - tools_free_hue_saturation, - hue_saturation_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Posterize"), - N_("/Image/Colors/Posterize..."), - NULL, - (char **) adjustment_bits, - NULL, - NULL, - N_("Reduce image to a fixed numer of colors"), - "tools/posterize.html", - POSTERIZE, - tools_new_posterize, - tools_free_posterize, - posterize_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Threshold"), - N_("/Image/Colors/Threshold..."), - NULL, - (char **) levels_bits, - NULL, - NULL, - N_("Reduce image to two colors using a threshold"), - "tools/threshold.html", - THRESHOLD, - tools_new_threshold, - tools_free_threshold, - threshold_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Curves"), - N_("/Image/Colors/Curves..."), - NULL, - (char **) curves_bits, - NULL, - NULL, - N_("Adjust color curves"), - "tools/curves.html", - CURVES, - tools_new_curves, - tools_free_curves, - curves_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Levels"), - N_("/Image/Colors/Levels..."), - NULL, - (char **) levels_bits, - NULL, - NULL, - N_("Adjust color levels"), - "tools/levels.html", - LEVELS, - tools_new_levels, - tools_free_levels, - levels_initialize, - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { - NULL, - N_("Histogram"), - N_("/Image/Histogram..."), - NULL, - (char **) histogram_bits, - NULL, - NULL, - N_("View image histogram"), - "tools/histogram.html", - HISTOGRAM, - tools_new_histogram_tool, - tools_free_histogram_tool, - histogram_tool_initialize , - NULL, - NULL, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - } -}; - -gint num_tools = sizeof (tool_info) / sizeof (tool_info[0]); - -/* dnd stuff */ -static GtkTargetEntry tool_target_table[] = -{ - GIMP_TARGET_TOOL -}; -static guint n_tool_targets = (sizeof (tool_target_table) / - sizeof (tool_target_table[0])); - - -/* Local function declarations */ -static void tool_options_show (ToolType); -static void tool_options_hide (ToolType); -static ToolType tool_options_drag_tool (GtkWidget *, gpointer); -static void tool_options_drop_tool (GtkWidget *, ToolType, gpointer); -static void tool_options_reset_callback (GtkWidget *, gpointer); -static void tool_options_close_callback (GtkWidget *, gpointer); - - -/* Function definitions */ - -static void -active_tool_free (void) -{ - if (!active_tool) - return; - - tool_options_hide (active_tool->type); - - (* tool_info[(gint) active_tool->type].free_func) (active_tool); - - g_free (active_tool); - active_tool = NULL; -} - -void -tools_select (ToolType tool_type) -{ - if (active_tool) - active_tool_free (); - - active_tool = (* tool_info[(gint) tool_type].new_func) (); - - tool_options_show (active_tool->type); -} - -void -tools_initialize (ToolType tool_type, - GDisplay *gdisp) -{ - /* Tools which have an init function have dialogs and - * cannot be initialized without a display - */ - if (tool_info[(gint) tool_type].init_func && !gdisp) - tool_type = RECT_SELECT; - - /* Force the emission of the "tool_changed" signal - */ - if (active_tool->type == tool_type) - { - gimp_context_tool_changed (gimp_context_get_user ()); - } - else - { - gimp_context_set_tool (gimp_context_get_user (), tool_type); - } - - if (tool_info[(gint) tool_type].init_func) - { - (* tool_info[(gint) tool_type].init_func) (gdisp); - - active_tool->drawable = gimp_image_active_drawable (gdisp->gimage); - } - - /* don't set tool->gdisp here! (see commands.c) */ -} - - -void -active_tool_control (ToolAction action, - GDisplay *gdisp) -{ - if (active_tool) - { - if (active_tool->gdisp == gdisp) - { - switch (action) - { - case PAUSE : - if (active_tool->state == ACTIVE) - { - if (! active_tool->paused_count) - { - active_tool->state = PAUSED; - (* active_tool->control_func) (active_tool, action, gdisp); - } - } - active_tool->paused_count++; - break; - - case RESUME : - active_tool->paused_count--; - if (active_tool->state == PAUSED) - { - if (! active_tool->paused_count) - { - active_tool->state = ACTIVE; - (* active_tool->control_func) (active_tool, action, gdisp); - } - } - break; - - case HALT : - active_tool->state = INACTIVE; - (* active_tool->control_func) (active_tool, action, gdisp); - break; - - case DESTROY : - active_tool_free (); - gtk_widget_hide (options_shell); - break; - - default: - break; - } - } - else if (action == HALT) - { - active_tool->state = INACTIVE; - } - } -} - -/* standard member functions */ - -static void -standard_button_press_func (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - tool->gdisp = gdisp; - tool->drawable = gimp_image_active_drawable (gdisp->gimage); -} - -static void -standard_button_release_func (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ -} - -static void -standard_motion_func (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ -} - -static void -standard_arrow_keys_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ -} - -static void -standard_modifier_key_func (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp) -{ -} - -static void -standard_cursor_update_func (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - gdisplay_install_tool_cursor (gdisp, GDK_TOP_LEFT_ARROW, - TOOL_TYPE_NONE, - CURSOR_MODIFIER_NONE, - FALSE); -} - -static void -standard_operator_update_func (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ -} - -static void -standard_control_func (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ -} - -/* Create a default tool structure - * - * TODO: objectifying the tools will remove lots of code duplication - */ - -Tool * -tools_new_tool (ToolType tool_type) -{ - Tool *tool; - - tool = g_new (Tool, 1); - - tool->type = tool_type; - tool->ID = global_tool_ID++; - - tool->state = INACTIVE; - tool->paused_count = 0; - tool->scroll_lock = FALSE; /* Allow scrolling */ - tool->auto_snap_to = TRUE; /* Snap to guides */ - - tool->preserve = TRUE; /* Preserve tool across drawable changes */ - tool->gdisp = NULL; - tool->drawable = NULL; - - tool->toggled = FALSE; - - tool->private = NULL; - - tool->button_press_func = standard_button_press_func; - tool->button_release_func = standard_button_release_func; - tool->motion_func = standard_motion_func; - tool->arrow_keys_func = standard_arrow_keys_func; - tool->modifier_key_func = standard_modifier_key_func; - tool->cursor_update_func = standard_cursor_update_func; - tool->oper_update_func = standard_operator_update_func; - tool->control_func = standard_control_func; - - return tool; -} - -void -tools_help_func (const gchar *help_data) -{ - gimp_standard_help_func (tool_info[(gint) active_tool->type].private_tip); -} - -void -tools_register (ToolType tool_type, - ToolOptions *tool_options) -{ - g_return_if_fail (tool_options != NULL); - - tool_info [(gint) tool_type].tool_options = tool_options; - - /* need to check whether the widget is visible...this can happen - * because some tools share options such as the transformation tools - */ - if (! GTK_WIDGET_VISIBLE (tool_options->main_vbox)) - { - gtk_box_pack_start (GTK_BOX (options_vbox), tool_options->main_vbox, - TRUE, TRUE, 0); - gtk_widget_show (tool_options->main_vbox); - } - - gtk_label_set_text (GTK_LABEL (options_label), tool_options->title); - - gtk_pixmap_set (GTK_PIXMAP (options_pixmap), - tool_get_pixmap (tool_type), tool_get_mask (tool_type)); - - gtk_widget_queue_draw (options_pixmap); - - gimp_help_set_help_data (options_eventbox, - gettext (tool_info[(gint) tool_type].tool_desc), - tool_info[(gint) tool_type].private_tip); -} - -/* Tool options function */ - -void -tool_options_dialog_new (void) -{ - GtkWidget *frame; - GtkWidget *hbox; - GtkWidget *vbox; - - /* The shell and main vbox */ - options_shell = - gimp_dialog_new (_("Tool Options"), "tool_options", - tools_help_func, - "dialogs/tool_options.html", - GTK_WIN_POS_NONE, - FALSE, TRUE, TRUE, - - _("Reset"), tool_options_reset_callback, - NULL, NULL, &options_reset_button, FALSE, FALSE, - _("Close"), tool_options_close_callback, - NULL, NULL, NULL, TRUE, TRUE, - - NULL); - - /* Register dialog */ - dialog_register (options_shell); - session_set_window_geometry (options_shell, &tool_options_session_info, - FALSE ); - - /* The outer frame */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options_shell)->vbox), frame); - gtk_widget_show (frame); - - /* The vbox containing the title frame and the options vbox */ - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - - /* The title frame */ - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - options_eventbox = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (frame), options_eventbox); - gtk_widget_show (options_eventbox); - - hbox = gtk_hbox_new (FALSE, 4); - gtk_container_add (GTK_CONTAINER (options_eventbox), hbox); - gtk_widget_show (hbox); - - options_pixmap = gtk_pixmap_new (tool_get_pixmap (RECT_SELECT), tool_get_mask (RECT_SELECT)); - gtk_box_pack_start (GTK_BOX (hbox), options_pixmap, FALSE, FALSE, 0); - gtk_widget_show (options_pixmap); - - options_label = gtk_label_new (""); - gtk_box_pack_start (GTK_BOX (hbox), options_label, FALSE, FALSE, 1); - gtk_widget_show (options_label); - - options_vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (options_vbox), 2); - gtk_box_pack_start (GTK_BOX (vbox), options_vbox, FALSE, FALSE, 0); - - gtk_widget_show (options_vbox); - - /* hide the separator between the dialog's vbox and the action area */ - gtk_widget_hide (GTK_WIDGET (g_list_nth_data (gtk_container_children (GTK_CONTAINER (GTK_BIN (options_shell)->child)), 1))); - - /* dnd stuff */ - gtk_drag_dest_set (options_shell, - GTK_DEST_DEFAULT_HIGHLIGHT | - GTK_DEST_DEFAULT_MOTION | - GTK_DEST_DEFAULT_DROP, - tool_target_table, n_tool_targets, - GDK_ACTION_COPY); - gimp_dnd_tool_dest_set (options_shell, tool_options_drop_tool, NULL); - - gtk_drag_source_set (options_eventbox, - GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, - tool_target_table, n_tool_targets, - GDK_ACTION_COPY); - gimp_dnd_tool_source_set (options_eventbox, tool_options_drag_tool, NULL); -} - -void -tool_options_dialog_free (void) -{ - session_get_window_info (options_shell, &tool_options_session_info); - gtk_widget_destroy (options_shell); -} - -void -tool_options_dialog_show (void) -{ - if (!GTK_WIDGET_VISIBLE (options_shell)) - { - gtk_widget_show (options_shell); - } - else - { - gdk_window_raise (options_shell->window); - } -} - -static void -tool_options_show (ToolType tool_type) -{ - if (tool_info[tool_type].tool_options->main_vbox) - gtk_widget_show (tool_info[tool_type].tool_options->main_vbox); - - if (tool_info[tool_type].tool_options->title) - gtk_label_set_text (GTK_LABEL (options_label), - tool_info[tool_type].tool_options->title); - - gtk_pixmap_set (GTK_PIXMAP (options_pixmap), - tool_get_pixmap (tool_type), tool_get_mask (tool_type)); - - gtk_widget_queue_draw (options_pixmap); - - gimp_help_set_help_data (options_label->parent->parent, - gettext (tool_info[(gint) tool_type].tool_desc), - tool_info[(gint) tool_type].private_tip); - - if (tool_info[tool_type].tool_options->reset_func) - gtk_widget_set_sensitive (options_reset_button, TRUE); - else - gtk_widget_set_sensitive (options_reset_button, FALSE); -} - -static void -tool_options_hide (ToolType tool_type) -{ - if (tool_info[tool_type].tool_options) - gtk_widget_hide (tool_info[tool_type].tool_options->main_vbox); -} - -/* Tool options callbacks */ - -static void -tool_options_drop_tool (GtkWidget *widget, - ToolType tool, - gpointer data) -{ - gimp_context_set_tool (gimp_context_get_user (), tool); -} - -ToolType -tool_options_drag_tool (GtkWidget *widget, - gpointer data) -{ - return gimp_context_get_tool (gimp_context_get_user ()); -} - -static void -tool_options_close_callback (GtkWidget *widget, - gpointer data) -{ - GtkWidget *shell; - - shell = (GtkWidget *) data; - gimp_dialog_hide (shell); -} - -static void -tool_options_reset_callback (GtkWidget *widget, - gpointer data) -{ - GtkWidget *shell; - - shell = (GtkWidget *) data; - - if (!active_tool) - return; - - if (tool_info[(gint) active_tool->type].tool_options->reset_func) - (* tool_info[(gint) active_tool->type].tool_options->reset_func) (); -} - -gchar * -tool_active_PDB_string (void) -{ - gchar *toolStr = "gimp_paintbrush_default"; - - /* Return the correct PDB function for the active tool - * The default is paintbrush if the tool is not recognised - */ - - if (!active_tool) - return toolStr; - - switch (gimp_context_get_tool (gimp_context_get_user ())) - { - case PENCIL: - toolStr = "gimp_pencil"; - break; - case PAINTBRUSH: - toolStr = "gimp_paintbrush_default"; - break; - case ERASER: - toolStr = "gimp_eraser_default"; - break; - case AIRBRUSH: - toolStr = "gimp_airbrush_default"; - break; - case CLONE: - toolStr = "gimp_clone_default"; - break; - case CONVOLVE: - toolStr = "gimp_convolve_default"; - break; - case SMUDGE: - toolStr = "gimp_smudge_default"; - break; - case DODGEBURN: - toolStr = "gimp_dodgeburn_default"; - break; - default: - break; - } - - return toolStr; -} - -GdkPixmap * -tool_get_pixmap (ToolType type) -{ - return (tool_info[type].icon_pixmap); -} - -GdkPixmap * -tool_get_mask (ToolType type) -{ - return (tool_info[type].icon_mask); -} diff --git a/app/tools.h b/app/tools.h deleted file mode 100644 index 6058153c52..0000000000 --- a/app/tools.h +++ /dev/null @@ -1,159 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __TOOLS_H__ -#define __TOOLS_H__ - - -#include "cursorutil.h" - - -/* The possibilities for where the cursor lies */ -#define ACTIVE_LAYER (1 << 0) -#define SELECTION (1 << 1) -#define NON_ACTIVE_LAYER (1 << 2) - -/* Tool action function declarations */ -typedef void (* ButtonPressFunc) (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -typedef void (* ButtonReleaseFunc) (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -typedef void (* MotionFunc) (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -typedef void (* ArrowKeysFunc) (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -typedef void (* ModifierKeyFunc) (Tool *tool, - GdkEventKey *kevent, - GDisplay *gdisp); -typedef void (* CursorUpdateFunc) (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -typedef void (* OperUpdateFunc) (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -typedef void (* ToolCtlFunc) (Tool *tool, - ToolAction action, - GDisplay *gdisp); - -/* ToolInfo function declarations */ -typedef Tool * (* ToolInfoNewFunc) (void); -typedef void (* ToolInfoFreeFunc) (Tool *tool); -typedef void (* ToolInfoInitFunc) (GDisplay *gdisp); - -/* The types of tools... */ -struct _Tool -{ - /* Data */ - ToolType type; /* Tool type */ - gint ID; /* unique tool ID */ - - ToolState state; /* state of tool activity */ - gint paused_count; /* paused control count */ - gboolean scroll_lock; /* allow scrolling or not */ - gboolean auto_snap_to; /* snap to guides automatically */ - - gboolean preserve; /* Preserve this tool across drawable changes */ - GDisplay *gdisp; /* pointer to currently active gdisp */ - GimpDrawable *drawable; /* pointer to the tool's current drawable */ - - gboolean toggled; /* Bad hack to let the paint_core show the - * right toggle cursors - */ - - - gpointer private; /* Tool-specific information */ - - /* Action functions */ - ButtonPressFunc button_press_func; - ButtonReleaseFunc button_release_func; - MotionFunc motion_func; - ArrowKeysFunc arrow_keys_func; - ModifierKeyFunc modifier_key_func; - CursorUpdateFunc cursor_update_func; - OperUpdateFunc oper_update_func; - ToolCtlFunc control_func; -}; - -struct _ToolInfo -{ - ToolOptions *tool_options; - - gchar *tool_name; - - gchar *menu_path; - gchar *menu_accel; - - gchar **icon_data; - GdkPixmap *icon_pixmap; - GdkBitmap *icon_mask; - - gchar *tool_desc; - const gchar *private_tip; - - ToolType tool_id; - - ToolInfoNewFunc new_func; - ToolInfoFreeFunc free_func; - ToolInfoInitFunc init_func; - - GtkWidget *tool_widget; - - GimpContext *tool_context; - - BitmapCursor tool_cursor; - BitmapCursor toggle_cursor; -}; - - -/* Function declarations */ -Tool * tools_new_tool (ToolType tool_type); - -void tools_select (ToolType tool_type); -void tools_initialize (ToolType tool_type, - GDisplay *gdisplay); - -void active_tool_control (ToolAction action, - GDisplay *gdisp); - -void tools_help_func (const gchar *help_data); - -void tools_register (ToolType tool_type, - ToolOptions *tool_options); - -void tool_options_dialog_new (void); -void tool_options_dialog_show (void); -void tool_options_dialog_free (void); - -gchar * tool_active_PDB_string (void); - -/* don't unref these pixmaps, they are static! */ -GdkPixmap * tool_get_pixmap (ToolType tool_type); -GdkBitmap * tool_get_mask (ToolType tool_type); - - -/* Global Data Structures */ -extern Tool *active_tool; -extern ToolInfo tool_info[]; -extern gint num_tools; - - -#endif /* __TOOLS_H__ */ diff --git a/app/tools/.cvsignore b/app/tools/.cvsignore new file mode 100644 index 0000000000..3bacef6e78 --- /dev/null +++ b/app/tools/.cvsignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +.deps +.libs +*.lo +libapptools.la diff --git a/app/tools/Makefile.am b/app/tools/Makefile.am new file mode 100644 index 0000000000..71b79e36f3 --- /dev/null +++ b/app/tools/Makefile.am @@ -0,0 +1,113 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libapptools.la + +libapptools_la_SOURCES = \ + airbrush.c \ + airbrush.h \ + airbrush_blob.c \ + airbrush_blob.h \ + bezier_select.c \ + bezier_select.h \ + bezier_selectP.h \ + blend.c \ + blend.h \ + blob.c \ + blob.h \ + brightness_contrast.c \ + brightness_contrast.h \ + bucket_fill.c \ + bucket_fill.h \ + by_color_select.c \ + by_color_select.h \ + clone.c \ + clone.h \ + color_balance.c \ + color_balance.h \ + color_picker.c \ + color_picker.h \ + convolve.c \ + convolve.h \ + crop.c \ + crop.h \ + curves.c \ + curves.h \ + dodgeburn.c \ + dodgeburn.h \ + ellipse_select.c \ + ellipse_select.h \ + eraser.c \ + eraser.h \ + flip_tool.c \ + flip_tool.h \ + free_select.c \ + free_select.h \ + fuzzy_select.c \ + fuzzy_select.h \ + histogram_tool.c \ + histogram_tool.h \ + hue_saturation.c \ + hue_saturation.h \ + ink.c \ + ink.h \ + iscissors.c \ + iscissors.h \ + levels.c \ + levels.h \ + magnify.c \ + magnify.h \ + measure.c \ + measure.h \ + move.c \ + move.h \ + paintbrush.c \ + paintbrush.h \ + paint_core.c \ + paint_core.h \ + paint_core_kernels.h \ + paint_options.h \ + pencil.c \ + pencil.h \ + perspective_tool.c \ + perspective_tool.h \ + posterize.c \ + posterize.h \ + rect_select.c \ + rect_select.h \ + rect_selectP.h \ + rotate_tool.c \ + rotate_tool.h \ + scale_tool.c \ + scale_tool.h \ + shear_tool.c \ + shear_tool.h \ + smudge.c \ + smudge.h \ + text_tool.c \ + text_tool.h \ + threshold.c \ + threshold.h \ + tool_options.c \ + tool_options.h \ + tools.c \ + tools.h \ + transform_core.c \ + transform_core.h \ + transform_tool.c \ + transform_tool.h + +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"Gimp-Tools\" + +INCLUDES = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/app \ + $(GTK_CFLAGS) \ + -I$(includedir) + +.PHONY: files + +files: + @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ + echo $$p; \ + done diff --git a/app/tools/edit_selection.c b/app/tools/edit_selection.c index e7c25486cb..ee6be297fc 100644 --- a/app/tools/edit_selection.c +++ b/app/tools/edit_selection.c @@ -31,7 +31,6 @@ #include "cursorutil.h" #include "draw_core.h" #include "drawable.h" -#include "tools.h" #include "edit_selection.h" #include "floating_sel.h" #include "gimpimage.h" @@ -43,6 +42,8 @@ #include "selection.h" #include "undo.h" +#include "tools/tools.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpintl.h" diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c index e7c25486cb..ee6be297fc 100644 --- a/app/tools/gimpeditselectiontool.c +++ b/app/tools/gimpeditselectiontool.c @@ -31,7 +31,6 @@ #include "cursorutil.h" #include "draw_core.h" #include "drawable.h" -#include "tools.h" #include "edit_selection.h" #include "floating_sel.h" #include "gimpimage.h" @@ -43,6 +42,8 @@ #include "selection.h" #include "undo.h" +#include "tools/tools.h" + #include "libgimp/gimpmath.h" #include "libgimp/gimpintl.h" diff --git a/app/transform_core.c b/app/transform_core.c deleted file mode 100644 index ede5f7f04b..0000000000 --- a/app/transform_core.c +++ /dev/null @@ -1,1723 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "cursorutil.h" -#include "draw_core.h" -#include "drawable.h" -#include "floating_sel.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimpimage.h" -#include "gimprc.h" -#include "gimpui.h" -#include "info_dialog.h" -#include "layer.h" -#include "path_transform.h" -#include "paint_funcs.h" -#include "pixel_region.h" -#include "transform_core.h" -#include "transform_tool.h" -#include "tools.h" -#include "undo.h" -#include "tile_manager.h" -#include "tile_manager_pvt.h" -#include "tile.h" - -#include "libgimp/gimpintl.h" -#include "libgimp/gimpmath.h" - - -/* This should be migrated to pixel_region or similar... */ -/* PixelSurround describes a (read-only) - * region around a pixel in a tile manager - */ - -typedef struct _PixelSurround -{ - Tile *tile; - TileManager *mgr; - guchar *buff; - gint buff_size; - gint bpp; - gint w; - gint h; - guchar bg[MAX_CHANNELS]; - gint row_stride; -} PixelSurround; - -#define BILINEAR(jk,j1k,jk1,j1k1,dx,dy) \ - ((1-dy) * (jk + dx * (j1k - jk)) + \ - dy * (jk1 + dx * (j1k1 - jk1))) - -/* access interleaved pixels */ -#define CUBIC_ROW(dx, row, step) \ - cubic(dx, (row)[0], (row)[step], (row)[step+step], (row)[step+step+step]) -#define CUBIC_SCALED_ROW(dx, row, step, i) \ - cubic(dx, (row)[0] * (row)[i], \ - (row)[step] * (row)[step + i], \ - (row)[step+step]* (row)[step+step + i], \ - (row)[step+step+step] * (row)[step+step+step + i]) - -#define REF_TILE(i,x,y) \ - tile[i] = tile_manager_get_tile (float_tiles, x, y, TRUE, FALSE); \ - src[i] = tile_data_pointer (tile[i], (x) % TILE_WIDTH, (y) % TILE_HEIGHT); - -/* forward function declarations */ -static void transform_core_bounds (Tool *tool, - GDisplay *gdisp); -static void transform_core_recalc (Tool *tool, - GDisplay *gdisp); -static void transform_core_doit (Tool *tool, - GDisplay *gdisp); -static gdouble cubic (gdouble dx, - gint jm1, - gint j, - gint jp1, - gint jp2); -static void transform_core_setup_grid (Tool *tool); -static void transform_core_grid_recalc (TransformCore *transform_core); - - -/* variables */ -static TranInfo old_trans_info; -InfoDialog *transform_info = NULL; -static gboolean transform_info_inited = FALSE; - - -static void -pixel_surround_init (PixelSurround *ps, - TileManager *tm, - gint w, - gint h, - guchar bg[MAX_CHANNELS]) -{ - gint i; - - for (i = 0; i < MAX_CHANNELS; ++i) - { - ps->bg[i] = bg[i]; - } - - ps->tile = NULL; - ps->mgr = tm; - ps->bpp = tile_manager_level_bpp (tm); - ps->w = w; - ps->h = h; - /* make sure buffer is big enough */ - ps->buff_size = w * h * ps->bpp; - ps->buff = g_malloc (ps->buff_size); - ps->row_stride = 0; -} - -/* return a pointer to a buffer which contains all the surrounding pixels */ -/* strategy: if we are in the middle of a tile, use the tile storage */ -/* otherwise just copy into our own malloced buffer and return that */ - -static guchar * -pixel_surround_lock (PixelSurround *ps, - gint x, - gint y) -{ - gint i, j; - guchar *k; - guchar *ptr; - - ps->tile = tile_manager_get_tile (ps->mgr, x, y, TRUE, FALSE); - - i = x % TILE_WIDTH; - j = y % TILE_HEIGHT; - - /* do we have the whole region? */ - if (ps->tile && - (i < (tile_ewidth(ps->tile) - ps->w)) && - (j < (tile_eheight(ps->tile) - ps->h))) - { - ps->row_stride = tile_ewidth (ps->tile) * ps->bpp; - /* is this really the correct way? */ - return tile_data_pointer (ps->tile, i, j); - } - - /* nope, do this the hard way (for now) */ - if (ps->tile) - { - tile_release (ps->tile, FALSE); - ps->tile = 0; - } - - /* copy pixels, one by one */ - /* no, this is not the best way, but it's much better than before */ - ptr = ps->buff; - for (j = y; j < y+ps->h; ++j) - { - for (i = x; i < x+ps->w; ++i) - { - Tile *tile = tile_manager_get_tile (ps->mgr, i, j, TRUE, FALSE); - - if (tile) - { - guchar *buff = tile_data_pointer (tile, - i % TILE_WIDTH, - j % TILE_HEIGHT); - - for (k = buff; k < buff+ps->bpp; ++k, ++ptr) - { - *ptr = *k; - } - tile_release (tile, FALSE); - } - else - { - for (k = ps->bg; k < ps->bg+ps->bpp; ++k, ++ptr) - { - *ptr = *k; - } - } - } - } - ps->row_stride = ps->w * ps->bpp; - - return ps->buff; -} - -static gint -pixel_surround_rowstride (PixelSurround *ps) -{ - return ps->row_stride; -} - -static void -pixel_surround_release (PixelSurround *ps) -{ - /* always get new tile (for now), so release the old one */ - if (ps->tile) - { - tile_release (ps->tile, FALSE); - ps->tile = 0; - } -} - -static void -pixel_surround_clear (PixelSurround *ps) -{ - if (ps->buff) - { - g_free (ps->buff); - ps->buff = 0; - ps->buff_size = 0; - } -} - -static void -transform_ok_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - - tool = (Tool *) data; - transform_core_doit (tool, tool->gdisp); -} - -static void -transform_reset_callback (GtkWidget *widget, - gpointer data) -{ - Tool *tool; - TransformCore *transform_core; - gint i; - - tool = (Tool *) data; - transform_core = (TransformCore *) tool->private; - - /* stop the current tool drawing process */ - draw_core_pause (transform_core->core, tool); - - /* Restore the previous transformation info */ - for (i = 0; i < TRAN_INFO_SIZE; i++) - transform_core->trans_info [i] = old_trans_info [i]; - - /* recalculate the tool's transformation matrix */ - transform_core_recalc (tool, tool->gdisp); - - /* resume drawing the current tool */ - draw_core_resume (transform_core->core, tool); -} - -static const gchar *action_labels[] = -{ - N_("Rotate"), - N_("Scale"), - N_("Shear"), - N_("Transform") -}; - -void -transform_core_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - TransformCore *transform_core; - GimpDrawable *drawable; - gint dist; - gint closest_dist; - gint x, y; - gint i; - gint off_x, off_y; - - transform_core = (TransformCore *) tool->private; - - transform_core->bpressed = TRUE; /* ALT */ - - drawable = gimp_image_active_drawable (gdisp->gimage); - - if (transform_core->function == TRANSFORM_CREATING && tool->state == ACTIVE) - { - /* Save the current transformation info */ - for (i = 0; i < TRAN_INFO_SIZE; i++) - old_trans_info [i] = transform_core->trans_info [i]; - } - - /* if we have already displayed the bounding box and handles, - * check to make sure that the display which currently owns the - * tool is the one which just received the button pressed event - */ - if ((gdisp == tool->gdisp) && transform_core->interactive) - { - /* start drawing the bounding box and handles... */ - draw_core_start (transform_core->core, gdisp->canvas->window, tool); - - x = bevent->x; - y = bevent->y; - - closest_dist = SQR (x - transform_core->sx1) + SQR (y - transform_core->sy1); - transform_core->function = TRANSFORM_HANDLE_1; - - dist = SQR (x - transform_core->sx2) + SQR (y - transform_core->sy2); - if (dist < closest_dist) - { - closest_dist = dist; - transform_core->function = TRANSFORM_HANDLE_2; - } - - dist = SQR (x - transform_core->sx3) + SQR (y - transform_core->sy3); - if (dist < closest_dist) - { - closest_dist = dist; - transform_core->function = TRANSFORM_HANDLE_3; - } - - dist = SQR (x - transform_core->sx4) + SQR (y - transform_core->sy4); - if (dist < closest_dist) - { - closest_dist = dist; - transform_core->function = TRANSFORM_HANDLE_4; - } - - if (tool->type == ROTATE - && (SQR (x - transform_core->scx) + - SQR (y - transform_core->scy)) <= 100) - { - transform_core->function = TRANSFORM_HANDLE_CENTER; - } - - /* Save the current pointer position */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, - &transform_core->startx, - &transform_core->starty, TRUE, 0); - transform_core->lastx = transform_core->startx; - transform_core->lasty = transform_core->starty; - - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->state = ACTIVE; - return; - } - - - /* Initialisation stuff: if the cursor is clicked inside the current - * selection, show the bounding box and handles... - */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, - FALSE, FALSE); - - gimp_drawable_offsets (drawable, &off_x, &off_y); - if (x >= off_x && y >= off_y && - x < (off_x + gimp_drawable_width (drawable)) && - y < (off_y + gimp_drawable_height (drawable))) - if (gimage_mask_is_empty (gdisp->gimage) || - gimage_mask_value (gdisp->gimage, x, y)) - { - if (GIMP_IS_LAYER (drawable) && - layer_get_mask (GIMP_LAYER (drawable))) - { - g_message (_("Transformations do not work on\n" - "layers that contain layer masks.")); - tool->state = INACTIVE; - return; - } - - /* If the tool is already active, clear the current state - * and reset - */ - if (tool->state == ACTIVE) - transform_core_reset (tool, gdisp); - - /* Set the pointer to the active display */ - tool->gdisp = gdisp; - tool->drawable = drawable; - tool->state = ACTIVE; - - /* Grab the pointer if we're in non-interactive mode */ - if (!transform_core->interactive) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - (GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK), - NULL, NULL, bevent->time); - - /* Find the transform bounds for some tools (like scale, - * perspective) that actually need the bounds for - * initializing - */ - transform_core_bounds (tool, gdisp); - - /* Calculate the grid line endpoints */ - if (transform_tool_show_grid ()) - transform_core_setup_grid (tool); - - /* Initialize the transform tool */ - (* transform_core->trans_func) (tool, gdisp, TRANSFORM_INIT); - - if (transform_info && !transform_info_inited) - { - gimp_dialog_create_action_area - (GTK_DIALOG (transform_info->shell), - - gettext (action_labels[tool->type - ROTATE]), - transform_ok_callback, - tool, NULL, NULL, TRUE, FALSE, - _("Reset"), transform_reset_callback, - tool, NULL, NULL, FALSE, FALSE, - - NULL); - - transform_info_inited = TRUE; - } - - /* Recalculate the transform tool */ - transform_core_recalc (tool, gdisp); - - /* recall this function to find which handle we're dragging */ - if (transform_core->interactive) - transform_core_button_press (tool, bevent, gdisp); - } -} - -void -transform_core_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) -{ - TransformCore *transform_core; - gint i; - - transform_core = (TransformCore *) tool->private; - - transform_core->bpressed = FALSE; /* ALT */ - - /* if we are creating, there is nothing to be done...exit */ - if (transform_core->function == TRANSFORM_CREATING && - transform_core->interactive) - return; - - /* release of the pointer grab */ - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - /* if the 3rd button isn't pressed, transform the selected mask */ - if (! (bevent->state & GDK_BUTTON3_MASK)) - { - /* Shift-clicking is another way to approve the transform */ - if ((bevent->state & GDK_SHIFT_MASK) || (tool->type == FLIP)) - { - transform_core_doit (tool, gdisp); - } - else - { - /* Only update the paths preview */ - path_transform_current_path (gdisp->gimage, - transform_core->transform, TRUE); - } - } - else - { - /* stop the current tool drawing process */ - draw_core_pause (transform_core->core, tool); - - /* Restore the previous transformation info */ - for (i = 0; i < TRAN_INFO_SIZE; i++) - transform_core->trans_info [i] = old_trans_info [i]; - - /* recalculate the tool's transformation matrix */ - transform_core_recalc (tool, gdisp); - - /* resume drawing the current tool */ - draw_core_resume (transform_core->core, tool); - - /* Update the paths preview */ - path_transform_current_path (gdisp->gimage, - transform_core->transform, TRUE); - } - - /* if this tool is non-interactive, make it inactive after use */ - if (!transform_core->interactive) - tool->state = INACTIVE; -} - -void -transform_core_doit (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - TileManager *new_tiles; - TransformUndo *tu; - PathUndo *pundo; - gboolean new_layer; - gint i, x, y; - - gimp_add_busy_cursors (); - - transform_core = (TransformCore *) tool->private; - - /* undraw the tool before we muck around with the transform matrix */ - draw_core_pause (transform_core->core, tool); - - /* We're going to dirty this image, but we want to keep the tool - * around - */ - tool->preserve = TRUE; - - /* Start a transform undo group */ - undo_push_group_start (gdisp->gimage, TRANSFORM_CORE_UNDO); - - /* With the old UI, if original is NULL, then this is the - first transformation. In the new UI, it is always so, yes? */ - g_assert (transform_core->original == NULL); - - /* If we're in interactive mode, we need to copy the current - * selection to the transform tool's private selection pointer, so - * that the original source can be repeatedly modified. - */ - tool->drawable = gimp_image_active_drawable (gdisp->gimage); - - transform_core->original = transform_core_cut (gdisp->gimage, - tool->drawable, - &new_layer); - - pundo = path_transform_start_undo (gdisp->gimage); - - /* Send the request for the transformation to the tool... - */ - new_tiles = (* transform_core->trans_func) (tool, gdisp, - TRANSFORM_FINISH); - - (* transform_core->trans_func) (tool, gdisp, TRANSFORM_INIT); - - transform_core_recalc (tool, gdisp); - - if (new_tiles) - { - /* paste the new transformed image to the gimage...also implement - * undo... - */ - /* FIXME: we should check if the drawable is still valid */ - transform_core_paste (gdisp->gimage, tool->drawable, - new_tiles, new_layer); - - /* create and initialize the transform_undo structure */ - tu = g_new (TransformUndo, 1); - tu->tool_ID = tool->ID; - tu->tool_type = tool->type; - for (i = 0; i < TRAN_INFO_SIZE; i++) - tu->trans_info[i] = old_trans_info[i]; - tu->original = NULL; - tu->path_undo = pundo; - - /* Make a note of the new current drawable (since we may have - * a floating selection, etc now. - */ - tool->drawable = gimp_image_active_drawable (gdisp->gimage); - - undo_push_transform (gdisp->gimage, (void *) tu); - } - - /* push the undo group end */ - undo_push_group_end (gdisp->gimage); - - /* We're done dirtying the image, and would like to be restarted - * if the image gets dirty while the tool exists - */ - tool->preserve = FALSE; - - /* Flush the gdisplays */ - if (gdisp->disp_xoffset || gdisp->disp_yoffset) - { - gdk_window_get_size (gdisp->canvas->window, &x, &y); - if (gdisp->disp_yoffset) - { - gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_width, - gdisp->disp_yoffset); - gdisplay_expose_area (gdisp, 0, gdisp->disp_yoffset + y, - gdisp->disp_width, gdisp->disp_height); - } - if (gdisp->disp_xoffset) - { - gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_xoffset, - gdisp->disp_height); - gdisplay_expose_area (gdisp, gdisp->disp_xoffset + x, 0, - gdisp->disp_width, gdisp->disp_height); - } - } - - gimp_remove_busy_cursors (NULL); - - gdisplays_flush (); - - transform_core_reset (tool, gdisp); - - /* if this tool is non-interactive, make it inactive after use */ - if (!transform_core->interactive) - tool->state = INACTIVE; -} - -void -transform_core_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - if (transform_core->bpressed == FALSE) - { - /* hey we have not got the button press yet - * so go away. - */ - return; - } - - /* if we are creating or this tool is non-interactive, there is - * nothing to be done so exit. - */ - if (transform_core->function == TRANSFORM_CREATING || - !transform_core->interactive) - return; - - /* stop the current tool drawing process */ - draw_core_pause (transform_core->core, tool); - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, - &transform_core->curx, - &transform_core->cury, TRUE, 0); - transform_core->state = mevent->state; - - /* recalculate the tool's transformation matrix */ - (* transform_core->trans_func) (tool, gdisp, TRANSFORM_MOTION); - - transform_core->lastx = transform_core->curx; - transform_core->lasty = transform_core->cury; - - /* resume drawing the current tool */ - draw_core_resume (transform_core->core, tool); -} - -void -transform_core_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) -{ - TransformCore *transform_core; - GimpDrawable *drawable; - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; - gint x, y; - - transform_core = (TransformCore *) tool->private; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, - FALSE, FALSE); - - if ((drawable = gimp_image_active_drawable (gdisp->gimage))) - { - if (GIMP_IS_LAYER (drawable) && - layer_get_mask (GIMP_LAYER (drawable))) - { - ctype = GIMP_BAD_CURSOR; - } - else if (x >= drawable->offset_x && - y >= drawable->offset_y && - x < (drawable->offset_x + drawable->width) && - y < (drawable->offset_y + drawable->height)) - { - if (gimage_mask_is_empty (gdisp->gimage) || - gimage_mask_value (gdisp->gimage, x, y)) - { - ctype = GIMP_MOUSE_CURSOR; - } - } - } - - gdisplay_install_tool_cursor (gdisp, ctype, - tool->type, - CURSOR_MODIFIER_NONE, - FALSE); -} - -void -transform_core_control (Tool *tool, - ToolAction action, - GDisplay *gdisp) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (transform_core->core, tool); - break; - - case RESUME: - transform_core_recalc (tool, gdisp); - draw_core_resume (transform_core->core, tool); - break; - - case HALT: - transform_core_reset (tool, gdisp); - break; - - default: - break; - } -} - -void -transform_core_no_draw (Tool *tool) -{ - return; -} - -void -transform_core_draw (Tool *tool) -{ - GDisplay *gdisp; - TransformCore *transform_core; - gint x1, y1, x2, y2, x3, y3, x4, y4; - gint srw, srh; - gint i, k, gci; - gint xa, ya, xb, yb; - - gdisp = tool->gdisp; - transform_core = (TransformCore *) tool->private; - - gdisplay_transform_coords (gdisp, transform_core->tx1, transform_core->ty1, - &transform_core->sx1, &transform_core->sy1, FALSE); - gdisplay_transform_coords (gdisp, transform_core->tx2, transform_core->ty2, - &transform_core->sx2, &transform_core->sy2, FALSE); - gdisplay_transform_coords (gdisp, transform_core->tx3, transform_core->ty3, - &transform_core->sx3, &transform_core->sy3, FALSE); - gdisplay_transform_coords (gdisp, transform_core->tx4, transform_core->ty4, - &transform_core->sx4, &transform_core->sy4, FALSE); - - x1 = transform_core->sx1; y1 = transform_core->sy1; - x2 = transform_core->sx2; y2 = transform_core->sy2; - x3 = transform_core->sx3; y3 = transform_core->sy3; - x4 = transform_core->sx4; y4 = transform_core->sy4; - - /* find the handles' width and height */ - srw = 10; - srh = 10; - - /* draw the bounding box */ - gdk_draw_line (transform_core->core->win, transform_core->core->gc, - x1, y1, x2, y2); - gdk_draw_line (transform_core->core->win, transform_core->core->gc, - x2, y2, x4, y4); - gdk_draw_line (transform_core->core->win, transform_core->core->gc, - x3, y3, x4, y4); - gdk_draw_line (transform_core->core->win, transform_core->core->gc, - x3, y3, x1, y1); - - /* Draw the grid */ - - if ((transform_core->grid_coords != NULL) && - (transform_core->tgrid_coords != NULL) && - ((tool->type != PERSPECTIVE) || - ((transform_core->transform[0][0] >=0.0) && - (transform_core->transform[1][1] >=0.0)))) - { - - gci = 0; - k = transform_core->ngx + transform_core->ngy; - for (i = 0; i < k; i++) - { - gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci], - transform_core->tgrid_coords[gci+1], - &xa, &ya, FALSE); - gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci+2], - transform_core->tgrid_coords[gci+3], - &xb, &yb, FALSE); - - gdk_draw_line (transform_core->core->win, transform_core->core->gc, - xa, ya, xb, yb); - gci += 4; - } - } - - /* draw the tool handles */ - gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0, - x1 - (srw >> 1), y1 - (srh >> 1), srw, srh); - gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0, - x2 - (srw >> 1), y2 - (srh >> 1), srw, srh); - gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0, - x3 - (srw >> 1), y3 - (srh >> 1), srw, srh); - gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0, - x4 - (srw >> 1), y4 - (srh >> 1), srw, srh); - - /* draw the center */ - if (tool->type == ROTATE) - { - gdisplay_transform_coords (gdisp, transform_core->tcx, transform_core->tcy, - &transform_core->scx, &transform_core->scy, FALSE); - - gdk_draw_arc (transform_core->core->win, transform_core->core->gc, 1, - transform_core->scx - (srw >> 1), - transform_core->scy - (srh >> 1), - srw, srh, 0, 23040); - } - - if (transform_tool_showpath ()) - { - GimpMatrix3 tmp_matrix; - - if (transform_tool_direction () == TRANSFORM_CORRECTIVE) - { - gimp_matrix3_invert (transform_core->transform, tmp_matrix); - } - else - { - gimp_matrix3_duplicate (transform_core->transform, tmp_matrix); - } - - path_transform_draw_current (gdisp, transform_core->core, tmp_matrix); - } -} - -Tool * -transform_core_new (ToolType type, - gint interactive) -{ - Tool *tool; - TransformCore *private; - gint i; - - tool = tools_new_tool (type); - private = g_new0 (TransformCore, 1); - - private->interactive = interactive; - - if (interactive) - private->core = draw_core_new (transform_core_draw); - else - private->core = draw_core_new (transform_core_no_draw); - - private->function = TRANSFORM_CREATING; - private->original = NULL; - - private->bpressed = FALSE; - - for (i = 0; i < TRAN_INFO_SIZE; i++) - private->trans_info[i] = 0; - - private->grid_coords = private->tgrid_coords = NULL; - - tool->scroll_lock = TRUE; /* Disallow scrolling */ - tool->preserve = FALSE; /* Don't preserve on drawable change */ - - tool->private = (void *) private; - - tool->button_press_func = transform_core_button_press; - tool->button_release_func = transform_core_button_release; - tool->motion_func = transform_core_motion; - tool->cursor_update_func = transform_core_cursor_update; - tool->control_func = transform_core_control; - - return tool; -} - -void -transform_core_free (Tool *tool) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - /* Make sure the selection core is not visible */ - if (tool->state == ACTIVE) - draw_core_stop (transform_core->core, tool); - - /* Free the selection core */ - draw_core_free (transform_core->core); - - /* Free up the original selection if it exists */ - if (transform_core->original) - tile_manager_destroy (transform_core->original); - - /* If there is an information dialog, free it up */ - if (transform_info) - info_dialog_free (transform_info); - - transform_info = NULL; - transform_info_inited = FALSE; - - /* Free the grid line endpoint arrays if they exist */ - if (transform_core->grid_coords != NULL) - g_free (transform_core->grid_coords); - - if (transform_core->tgrid_coords != NULL) - g_free (transform_core->tgrid_coords); - - /* Finally, free the transform tool itself */ - g_free (transform_core); -} - -void -transform_core_transform_bounding_box (Tool *tool) -{ - TransformCore *transform_core; - gint i, k; - gint gci; - - transform_core = (TransformCore *) tool->private; - - gimp_matrix3_transform_point (transform_core->transform, - transform_core->x1, transform_core->y1, - &transform_core->tx1, &transform_core->ty1); - gimp_matrix3_transform_point (transform_core->transform, - transform_core->x2, transform_core->y1, - &transform_core->tx2, &transform_core->ty2); - gimp_matrix3_transform_point (transform_core->transform, - transform_core->x1, transform_core->y2, - &transform_core->tx3, &transform_core->ty3); - gimp_matrix3_transform_point (transform_core->transform, - transform_core->x2, transform_core->y2, - &transform_core->tx4, &transform_core->ty4); - - if (tool->type == ROTATE) - gimp_matrix3_transform_point (transform_core->transform, - transform_core->cx, transform_core->cy, - &transform_core->tcx, &transform_core->tcy); - - if (transform_core->grid_coords != NULL && - transform_core->tgrid_coords != NULL) - { - gci = 0; - k = (transform_core->ngx + transform_core->ngy) * 2; - for (i = 0; i < k; i++) - { - gimp_matrix3_transform_point (transform_core->transform, - transform_core->grid_coords[gci], - transform_core->grid_coords[gci+1], - &(transform_core->tgrid_coords[gci]), - &(transform_core->tgrid_coords[gci+1])); - gci += 2; - } - } -} - -void -transform_core_reset (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - if (transform_core->original) - tile_manager_destroy (transform_core->original); - transform_core->original = NULL; - - /* inactivate the tool */ - transform_core->function = TRANSFORM_CREATING; - draw_core_stop (transform_core->core, tool); - info_dialog_popdown (transform_info); - - tool->state = INACTIVE; - tool->gdisp = NULL; - tool->drawable = NULL; -} - -static void -transform_core_bounds (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - TileManager *tiles; - GimpDrawable *drawable; - gint offset_x, offset_y; - - transform_core = (TransformCore *) tool->private; - tiles = transform_core->original; - drawable = gimp_image_active_drawable (gdisp->gimage); - - /* find the boundaries */ - if (tiles) - { - transform_core->x1 = tiles->x; - transform_core->y1 = tiles->y; - transform_core->x2 = tiles->x + tiles->width; - transform_core->y2 = tiles->y + tiles->height; - } - else - { - gimp_drawable_offsets (drawable, &offset_x, &offset_y); - gimp_drawable_mask_bounds (drawable, - &transform_core->x1, &transform_core->y1, - &transform_core->x2, &transform_core->y2); - transform_core->x1 += offset_x; - transform_core->y1 += offset_y; - transform_core->x2 += offset_x; - transform_core->y2 += offset_y; - } - transform_core->cx = (transform_core->x1 + transform_core->x2) / 2; - transform_core->cy = (transform_core->y1 + transform_core->y2) / 2; - - /* changing the bounds invalidates any grid we may have */ - transform_core_grid_recalc (transform_core); -} - -void -transform_core_grid_density_changed (void) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) active_tool->private; - - if (transform_core->function == TRANSFORM_CREATING) - return; - - draw_core_pause (transform_core->core, active_tool); - transform_core_grid_recalc (transform_core); - transform_core_transform_bounding_box (active_tool); - draw_core_resume (transform_core->core, active_tool); -} - -void -transform_core_showpath_changed (gint type) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) active_tool->private; - - if (transform_core->function == TRANSFORM_CREATING) - return; - - if (type) - draw_core_pause (transform_core->core, active_tool); - else - draw_core_resume (transform_core->core, active_tool); -} - -static void -transform_core_grid_recalc (TransformCore *transform_core) -{ - if (transform_core->grid_coords != NULL) - { - g_free (transform_core->grid_coords); - transform_core->grid_coords = NULL; - } - if (transform_core->tgrid_coords != NULL) - { - g_free (transform_core->tgrid_coords); - transform_core->tgrid_coords = NULL; - } - if (transform_tool_show_grid ()) - transform_core_setup_grid (active_tool); -} - -static void -transform_core_setup_grid (Tool *tool) -{ - TransformCore *transform_core; - gint i, gci; - gdouble *coords; - - transform_core = (TransformCore *) tool->private; - - /* We use the transform_tool_grid_size function only here, even - * if the user changes the grid size in the middle of an - * operation, nothing happens. - */ - transform_core->ngx = - (transform_core->x2 - transform_core->x1) / transform_tool_grid_size (); - if (transform_core->ngx > 0) - transform_core->ngx--; - - transform_core->ngy = - (transform_core->y2 - transform_core->y1) / transform_tool_grid_size (); - if (transform_core->ngy > 0) - transform_core->ngy--; - - transform_core->grid_coords = coords = - g_new (double, (transform_core->ngx + transform_core->ngy) * 4); - - transform_core->tgrid_coords = - g_new (double, (transform_core->ngx + transform_core->ngy) * 4); - - gci = 0; - for (i = 1; i <= transform_core->ngx; i++) - { - coords[gci] = transform_core->x1 + - ((double) i)/(transform_core->ngx + 1) * - (transform_core->x2 - transform_core->x1); - coords[gci+1] = transform_core->y1; - coords[gci+2] = coords[gci]; - coords[gci+3] = transform_core->y2; - gci += 4; - } - for (i = 1; i <= transform_core->ngy; i++) - { - coords[gci] = transform_core->x1; - coords[gci+1] = transform_core->y1 + - ((double) i)/(transform_core->ngy + 1) * - (transform_core->y2 - transform_core->y1); - coords[gci+2] = transform_core->x2; - coords[gci+3] = coords[gci+1]; - gci += 4; - } -} - -static void -transform_core_recalc (Tool *tool, - GDisplay *gdisp) -{ - TransformCore *transform_core; - - transform_core = (TransformCore *) tool->private; - - transform_core_bounds (tool, gdisp); - - (* transform_core->trans_func) (tool, gdisp, TRANSFORM_RECALC); -} - -/* Actually carry out a transformation */ -TileManager * -transform_core_do (GImage *gimage, - GimpDrawable *drawable, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix, - GimpProgressFunc progress_callback, - gpointer progress_data) -{ - PixelRegion destPR; - TileManager *tiles; - GimpMatrix3 m; - GimpMatrix3 im; - gint itx, ity; - gint tx1, ty1, tx2, ty2; - gint width, height; - gint alpha; - gint bytes, b; - gint x, y; - gint sx, sy; - gint x1, y1, x2, y2; - gdouble xinc, yinc, winc; - gdouble tx, ty, tw; - gdouble ttx = 0.0, tty = 0.0; - guchar *dest; - guchar *d; - guchar *src[16]; - Tile *tile[16]; - guchar bg_col[MAX_CHANNELS]; - gint i; - gdouble a_val, a_recip; - gint newval; - - PixelSurround surround; - - alpha = 0; - - /* turn interpolation off for simple transformations (e.g. rot90) */ - if (gimp_matrix3_is_simple (matrix) || - interpolation_type == NEAREST_NEIGHBOR_INTERPOLATION) - interpolation = FALSE; - - /* Get the background color */ - gimp_image_get_background (gimage, drawable, bg_col); - - switch (gimp_drawable_type (drawable)) - { - case RGB_GIMAGE: case RGBA_GIMAGE: - bg_col[ALPHA_PIX] = TRANSPARENT_OPACITY; - alpha = ALPHA_PIX; - break; - case GRAY_GIMAGE: case GRAYA_GIMAGE: - bg_col[ALPHA_G_PIX] = TRANSPARENT_OPACITY; - alpha = ALPHA_G_PIX; - break; - case INDEXED_GIMAGE: case INDEXEDA_GIMAGE: - bg_col[ALPHA_I_PIX] = TRANSPARENT_OPACITY; - alpha = ALPHA_I_PIX; - /* If the gimage is indexed color, ignore smoothing value */ - interpolation = FALSE; - break; - default: - g_assert_not_reached (); - break; - } - - /* enable rotating un-floated non-layers */ - if (float_tiles->bpp == 1) - { - bg_col[0] = OPAQUE_OPACITY; - - /* setting alpha = 0 will cause the channel's value to be treated - * as alpha and the color channel loops never to be entered - */ - alpha = 0; - } - - if (transform_tool_direction () == TRANSFORM_CORRECTIVE) - { - /* keep the original matrix here, so we dont need to recalculate - the inverse later */ - gimp_matrix3_duplicate (matrix, m); - gimp_matrix3_invert (matrix, im); - matrix = im; - } - else - { - /* Find the inverse of the transformation matrix */ - gimp_matrix3_invert (matrix, m); - } - - path_transform_current_path (gimage, matrix, FALSE); - - x1 = float_tiles->x; - y1 = float_tiles->y; - x2 = x1 + float_tiles->width; - y2 = y1 + float_tiles->height; - - /* Find the bounding coordinates */ - if (alpha == 0 || (active_tool && transform_tool_clip ())) - { - tx1 = x1; - ty1 = y1; - tx2 = x2; - ty2 = y2; - } - else - { - gdouble dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4; - - gimp_matrix3_transform_point (matrix, x1, y1, &dx1, &dy1); - gimp_matrix3_transform_point (matrix, x2, y1, &dx2, &dy2); - gimp_matrix3_transform_point (matrix, x1, y2, &dx3, &dy3); - gimp_matrix3_transform_point (matrix, x2, y2, &dx4, &dy4); - - tx1 = MIN (dx1, dx2); - tx1 = MIN (tx1, dx3); - tx1 = MIN (tx1, dx4); - ty1 = MIN (dy1, dy2); - ty1 = MIN (ty1, dy3); - ty1 = MIN (ty1, dy4); - tx2 = MAX (dx1, dx2); - tx2 = MAX (tx2, dx3); - tx2 = MAX (tx2, dx4); - ty2 = MAX (dy1, dy2); - ty2 = MAX (ty2, dy3); - ty2 = MAX (ty2, dy4); - } - - /* Get the new temporary buffer for the transformed result */ - tiles = tile_manager_new ((tx2 - tx1), (ty2 - ty1), float_tiles->bpp); - pixel_region_init (&destPR, tiles, 0, 0, (tx2 - tx1), (ty2 - ty1), TRUE); - tiles->x = tx1; - tiles->y = ty1; - - /* initialise the pixel_surround accessor */ - if (interpolation) - { - if (interpolation_type == CUBIC_INTERPOLATION) - { - pixel_surround_init (&surround, float_tiles, 4, 4, bg_col); - } - else - { - pixel_surround_init (&surround, float_tiles, 2, 2, bg_col); - } - } - else - { - /* not actually useful, keeps the code cleaner */ - pixel_surround_init (&surround, float_tiles, 1, 1, bg_col); - } - - width = tiles->width; - height = tiles->height; - bytes = tiles->bpp; - - dest = g_new (guchar, width * bytes); - - xinc = m[0][0]; - yinc = m[1][0]; - winc = m[2][0]; - - /* these loops could be rearranged, depending on which bit of code - * you'd most like to write more than once. - */ - - for (y = ty1; y < ty2; y++) - { - if (progress_callback && !(y & 0xf)) - (* progress_callback) (ty1, ty2, y, progress_data); - - /* set up inverse transform steps */ - tx = xinc * tx1 + m[0][1] * y + m[0][2]; - ty = yinc * tx1 + m[1][1] * y + m[1][2]; - tw = winc * tx1 + m[2][1] * y + m[2][2]; - - d = dest; - for (x = tx1; x < tx2; x++) - { - /* normalize homogeneous coords */ - if (tw == 0.0) - { - g_warning ("homogeneous coordinate = 0...\n"); - } - else if (tw != 1.0) - { - ttx = tx / tw; - tty = ty / tw; - } - else - { - ttx = tx; - tty = ty; - } - - /* Set the destination pixels */ - - if (interpolation) - { - if (interpolation_type == CUBIC_INTERPOLATION) - { - /* ttx & tty are the subpixel coordinates of the point in - * the original selection's floating buffer. - * We need the four integer pixel coords around them: - * itx to itx + 3, ity to ity + 3 - */ - itx = floor (ttx); - ity = floor (tty); - - /* check if any part of our region overlaps the buffer */ - - if ((itx + 2) >= x1 && (itx - 1) < x2 && - (ity + 2) >= y1 && (ity - 1) < y2 ) - { - guchar *data; - gint row; - gdouble dx, dy; - guchar *start; - - /* lock the pixel surround */ - data = pixel_surround_lock (&surround, - itx - 1 - x1, ity - 1 - y1); - - row = pixel_surround_rowstride (&surround); - - /* the fractional error */ - dx = ttx - itx; - dy = tty - ity; - - /* calculate alpha of result */ - start = &data[alpha]; - a_val = cubic (dy, - CUBIC_ROW (dx, start, bytes), - CUBIC_ROW (dx, start + row, bytes), - CUBIC_ROW (dx, start + row + row, bytes), - CUBIC_ROW (dx, start + row + row + row, bytes)); - - if (a_val <= 0.0) - { - a_recip = 0.0; - d[alpha] = 0; - } - else if (a_val > 255.0) - { - a_recip = 1.0 / a_val; - d[alpha] = 255; - } - else - { - a_recip = 1.0 / a_val; - d[alpha] = RINT(a_val); - } - - /* for colour channels c, - * result = bicubic (c * alpha) / bicubic (alpha) - * - * never entered for alpha == 0 - */ - for (i = -alpha; i < 0; ++i) - { - start = &data[alpha]; - newval = - RINT (a_recip * - cubic (dy, - CUBIC_SCALED_ROW (dx, start, bytes, i), - CUBIC_SCALED_ROW (dx, start + row, bytes, i), - CUBIC_SCALED_ROW (dx, start + row + row, bytes, i), - CUBIC_SCALED_ROW (dx, start + row + row + row, bytes, i))); - if (newval <= 0) - { - *d++ = 0; - } - else if (newval > 255) - { - *d++ = 255; - } - else - { - *d++ = newval; - } - } - - /* alpha already done */ - d++; - - pixel_surround_release (&surround); - } - else /* not in source range */ - { - /* increment the destination pointers */ - for (b = 0; b < bytes; b++) - *d++ = bg_col[b]; - } - } - - else /* linear */ - { - itx = floor (ttx); - ity = floor (tty); - - /* expand source area to cover interpolation region - * (which runs from itx to itx + 1, same in y) - */ - if ((itx + 1) >= x1 && itx < x2 && - (ity + 1) >= y1 && ity < y2 ) - { - guchar *data; - gint row; - double dx, dy; - guchar *chan; - - /* lock the pixel surround */ - data = pixel_surround_lock (&surround, itx - x1, ity - y1); - - row = pixel_surround_rowstride (&surround); - - /* the fractional error */ - dx = ttx - itx; - dy = tty - ity; - - /* calculate alpha value of result pixel */ - chan = &data[alpha]; - a_val = BILINEAR (chan[0], chan[bytes], chan[row], - chan[row+bytes], dx, dy); - if (a_val <= 0.0) - { - a_recip = 0.0; - d[alpha] = 0.0; - } - else if (a_val >= 255.0) - { - a_recip = 1.0 / a_val; - d[alpha] = 255; - } - else - { - a_recip = 1.0 / a_val; - d[alpha] = RINT (a_val); - } - - /* for colour channels c, - * result = bilinear (c * alpha) / bilinear (alpha) - * - * never entered for alpha == 0 - */ - for (i = -alpha; i < 0; ++i) - { - chan = &data[alpha]; - newval = - RINT (a_recip * - BILINEAR (chan[0] * chan[i], - chan[bytes] * chan[bytes+i], - chan[row] * chan[row+i], - chan[row+bytes] * chan[row+bytes+i], - dx, dy)); - if (newval <= 0) - { - *d++ = 0; - } - else if (newval > 255) - { - *d++ = 255; - } - else - { - *d++ = newval; - } - } - - /* alpha already done */ - d++; - - pixel_surround_release (&surround); - } - - else /* not in source range */ - { - /* increment the destination pointers */ - for (b = 0; b < bytes; b++) - *d++ = bg_col[b]; - } - } - } - else /* no interpolation */ - { - itx = floor (ttx); - ity = floor (tty); - - if (itx >= x1 && itx < x2 && - ity >= y1 && ity < y2 ) - { - /* x, y coordinates into source tiles */ - sx = itx - x1; - sy = ity - y1; - - REF_TILE (0, sx, sy); - - for (b = 0; b < bytes; b++) - *d++ = src[0][b]; - - tile_release (tile[0], FALSE); - } - else /* not in source range */ - { - /* increment the destination pointers */ - for (b = 0; b < bytes; b++) - *d++ = bg_col[b]; - } - } - /* increment the transformed coordinates */ - tx += xinc; - ty += yinc; - tw += winc; - } - - /* set the pixel region row */ - pixel_region_set_row (&destPR, 0, (y - ty1), width, dest); - } - - pixel_surround_clear (&surround); - - g_free (dest); - return tiles; -} - -TileManager * -transform_core_cut (GImage *gimage, - GimpDrawable *drawable, - gboolean *new_layer) -{ - TileManager *tiles; - - /* extract the selected mask if there is a selection */ - if (! gimage_mask_is_empty (gimage)) - { - /* set the keep_indexed flag to FALSE here, since we use - layer_new_from_tiles() later which assumes that the tiles - are either RGB or GRAY. Eeek!!! (Sven) - */ - tiles = gimage_mask_extract (gimage, drawable, TRUE, FALSE, TRUE); - *new_layer = TRUE; - } - /* otherwise, just copy the layer */ - else - { - if (GIMP_IS_LAYER (drawable)) - tiles = gimage_mask_extract (gimage, drawable, FALSE, TRUE, TRUE); - else - tiles = gimage_mask_extract (gimage, drawable, FALSE, TRUE, FALSE); - *new_layer = FALSE; - } - - return tiles; -} - - -/* Paste a transform to the gdisplay */ -gboolean -transform_core_paste (GImage *gimage, - GimpDrawable *drawable, - TileManager *tiles, - gboolean new_layer) -{ - Layer *layer = NULL; - Channel *channel = NULL; - Layer *floating_layer; - - if (new_layer) - { - layer = layer_new_from_tiles (gimage, - gimp_drawable_type_with_alpha (drawable), - tiles, - _("Transformation"), - OPAQUE_OPACITY, NORMAL_MODE); - if (!layer) - { - g_warning ("transform_core_paste: layer_new_frome_tiles() failed"); - return FALSE; - } - GIMP_DRAWABLE (layer)->offset_x = tiles->x; - GIMP_DRAWABLE (layer)->offset_y = tiles->y; - - /* Start a group undo */ - undo_push_group_start (gimage, EDIT_PASTE_UNDO); - - floating_sel_attach (layer, drawable); - - /* End the group undo */ - undo_push_group_end (gimage); - - /* Free the tiles */ - tile_manager_destroy (tiles); - - return TRUE; - } - else - { - if (GIMP_IS_LAYER (drawable)) - layer = GIMP_LAYER (drawable); - else if (GIMP_IS_CHANNEL (drawable)) - channel = GIMP_CHANNEL (drawable); - else - return FALSE; - - if (layer) - layer_add_alpha (layer); - floating_layer = gimp_image_floating_sel (gimage); - - if (floating_layer) - floating_sel_relax (floating_layer, TRUE); - - gdisplays_update_area (gimage, - drawable->offset_x, - drawable->offset_y, - drawable->width, - drawable->height); - - /* Push an undo */ - if (layer) - undo_push_layer_mod (gimage, layer); - else if (channel) - undo_push_channel_mod (gimage, channel); - - /* set the current layer's data */ - drawable->tiles = tiles; - - /* Fill in the new layer's attributes */ - drawable->width = tiles->width; - drawable->height = tiles->height; - drawable->bytes = tiles->bpp; - drawable->offset_x = tiles->x; - drawable->offset_y = tiles->y; - - if (floating_layer) - floating_sel_rigor (floating_layer, TRUE); - - drawable_update (drawable, - 0, 0, - gimp_drawable_width (drawable), - gimp_drawable_height (drawable)); - - /* if we were operating on the floating selection, then it's boundary - * and previews need invalidating - */ - if (drawable == (GimpDrawable *) floating_layer) - floating_sel_invalidate (floating_layer); - - return TRUE; - } -} - -/* Note: cubic function no longer clips result */ -static gdouble -cubic (gdouble dx, - gint jm1, - gint j, - gint jp1, - gint jp2) -{ - gdouble result; - -#if 0 - /* Equivalent to Gimp 1.1.1 and earlier - some ringing */ - result = ((( ( - jm1 + j - jp1 + jp2 ) * dx + - ( jm1 + jm1 - j - j + jp1 - jp2 ) ) * dx + - ( - jm1 + jp1 ) ) * dx + j ); - /* Recommended by Mitchell and Netravali - too blurred? */ - result = ((( ( - 7 * jm1 + 21 * j - 21 * jp1 + 7 * jp2 ) * dx + - ( 15 * jm1 - 36 * j + 27 * jp1 - 6 * jp2 ) ) * dx + - ( - 9 * jm1 + 9 * jp1 ) ) * dx + (jm1 + 16 * j + jp1) ) / 18.0; -#else - - /* Catmull-Rom - not bad */ - result = ((( ( - jm1 + 3 * j - 3 * jp1 + jp2 ) * dx + - ( 2 * jm1 - 5 * j + 4 * jp1 - jp2 ) ) * dx + - ( - jm1 + jp1 ) ) * dx + (j + j) ) / 2.0; - -#endif - - return result; -} diff --git a/app/transform_core.h b/app/transform_core.h deleted file mode 100644 index 0c4a35d5e4..0000000000 --- a/app/transform_core.h +++ /dev/null @@ -1,157 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __TRANSFORM_CORE_H__ -#define __TRANSFORM_CORE_H__ - - -/* buffer sizes for scaling information strings (for the info dialog) */ -#define MAX_INFO_BUF 40 -#define TRAN_INFO_SIZE 8 - -enum BoundingBox -{ - X0, Y0, X1, Y1, X2, Y2, X3, Y3 -}; - -typedef gdouble TranInfo[TRAN_INFO_SIZE]; - -typedef TileManager * (* TransformFunc) (Tool *tool, - GDisplay *gdisp, - TransformState state); - - -struct _TransformCore -{ - DrawCore *core; /* Core select object */ - - gint startx; /* starting x coord */ - gint starty; /* starting y coord */ - - gint curx; /* current x coord */ - gint cury; /* current y coord */ - - gint lastx; /* last x coord */ - gint lasty; /* last y coord */ - - gint state; /* state of buttons and keys */ - - gint x1, y1; /* upper left hand coordinate */ - gint x2, y2; /* lower right hand coords */ - gint cx, cy; /* center point (for rotation) */ - - gdouble tx1, ty1; /* transformed coords */ - gdouble tx2, ty2; /* */ - gdouble tx3, ty3; /* */ - gdouble tx4, ty4; /* */ - gdouble tcx, tcy; /* */ - - gint sx1, sy1; /* transformed screen coords */ - gint sx2, sy2; /* position of four handles */ - gint sx3, sy3; /* */ - gint sx4, sy4; /* */ - gint scx, scy; /* and center for rotation */ - - GimpMatrix3 transform; /* transformation matrix */ - TranInfo trans_info; /* transformation info */ - - TileManager *original; /* pointer to original tiles */ - - TransformFunc trans_func; /* transformation function */ - - TransformAction function; /* current tool activity */ - - gboolean interactive; /* tool is interactive */ - gboolean bpressed; /* Bug work around make sure we have - * a button pressed before we deal with - * motion events. ALT. - */ - gint ngx, ngy; /* number of grid lines in original - * x and y directions - */ - gdouble *grid_coords; /* x and y coordinates of the grid - * endpoints (a total of (ngx+ngy)*2 - * coordinate pairs) - */ - gdouble *tgrid_coords; /* transformed grid_coords */ -}; - - -/* Special undo type */ -typedef struct _TransformUndo TransformUndo; - -struct _TransformUndo -{ - gint tool_ID; - gint tool_type; - TranInfo trans_info; - TileManager *original; - gpointer path_undo; -}; - - -/* make this variable available to all */ -extern InfoDialog * transform_info; - -/* transform tool action functions */ -void transform_core_button_press (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -void transform_core_button_release (Tool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -void transform_core_motion (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -void transform_core_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -void transform_core_control (Tool *tool, - ToolAction tool_action, - GDisplay *gdisp); - -/* transform tool functions */ -Tool * transform_core_new (ToolType tool_type, - gboolean interactive); -void transform_core_free (Tool *tool); -void transform_core_draw (Tool *tool); -void transform_core_no_draw (Tool *tool); -void transform_core_transform_bounding_box (Tool *tool); -void transform_core_reset (Tool *tool, - GDisplay *gdisp); -void transform_core_grid_density_changed (void); -void transform_core_showpath_changed (gint type); - -/* transform functions */ -TileManager * transform_core_do (GImage *gimage, - GimpDrawable *drawable, - TileManager *float_tiles, - gboolean interpolation, - GimpMatrix3 matrix, - GimpProgressFunc progress_callback, - gpointer progress_data); -TileManager * transform_core_cut (GImage *gimage, - GimpDrawable *drawable, - gboolean *new_layer); -gboolean transform_core_paste (GImage *gimage, - GimpDrawable *drawable, - TileManager *tiles, - gboolean new_layer); - - -#endif /* __TRANSFORM_CORE_H__ */ diff --git a/app/transform_tool.c b/app/transform_tool.c deleted file mode 100644 index b2b1193dfd..0000000000 --- a/app/transform_tool.c +++ /dev/null @@ -1,458 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "gdisplay.h" -#include "gimpcontext.h" -#include "gimpui.h" -#include "perspective_tool.h" -#include "rotate_tool.h" -#include "scale_tool.h" -#include "shear_tool.h" -#include "tools.h" -#include "tool_options.h" -#include "transform_core.h" -#include "transform_tool.h" - -#include "libgimp/gimpmath.h" -#include "libgimp/gimpintl.h" - -/* the transform structures */ - -typedef struct _TransformOptions TransformOptions; - -struct _TransformOptions -{ - ToolOptions tool_options; - - ToolType type; - ToolType type_d; - GtkWidget *type_w[4]; /* 4 radio buttons */ - - gboolean smoothing; - gboolean smoothing_d; - GtkWidget *smoothing_w; - - gint direction; - gint direction_d; - GtkWidget *direction_w[2]; /* 2 radio buttons */ - - gboolean show_grid; - gboolean show_grid_d; - GtkWidget *show_grid_w; - - gint grid_size; - gint grid_size_d; - GtkObject *grid_size_w; - - gboolean clip; - gboolean clip_d; - GtkWidget *clip_w; - - gboolean showpath; - gboolean showpath_d; - GtkWidget *showpath_w; -}; - - -/* the transform tool options */ -static TransformOptions *transform_options = NULL; - - -/* local functions */ -static void transform_change_type (ToolType new_type); - - -/* functions */ - -static void -transform_show_grid_update (GtkWidget *widget, - gpointer data) -{ - static gboolean first_call = TRUE; /* eek, this hack avoids a segfault */ - - if (first_call) - { - first_call = FALSE; - return; - } - - gimp_toggle_button_update (widget, data); - - transform_core_grid_density_changed (); -} - -static void -transform_show_path_update (GtkWidget *widget, - gpointer data) -{ - static gboolean first_call = TRUE; /* eek, this hack avoids a segfault */ - - if (first_call) - { - first_call = FALSE; - return; - } - - transform_core_showpath_changed (1); /* pause */ - gimp_toggle_button_update (widget, data); - transform_core_showpath_changed (0); /* resume */ -} - -static void -transform_type_callback (GtkWidget *widget, - gpointer data) -{ - transform_change_type ((long) data); -} - -static void -transform_direction_callback (GtkWidget *widget, - gpointer data) -{ - long dir = (long) data; - - if (dir == TRANSFORM_TRADITIONAL) - transform_options->direction = TRANSFORM_TRADITIONAL; - else - transform_options->direction = TRANSFORM_CORRECTIVE; -} - -static void -transform_grid_density_callback (GtkWidget *widget, - gpointer data) -{ - transform_options->grid_size = - (int) (pow (2.0, 7.0 - GTK_ADJUSTMENT (widget)->value) + 0.5); - - transform_core_grid_density_changed (); -} - -static void -transform_options_reset (void) -{ - TransformOptions *options = transform_options; - - gtk_toggle_button_set_active (((options->type_d == ROTATE) ? - GTK_TOGGLE_BUTTON (options->type_w[0]) : - ((options->type_d == SCALE) ? - GTK_TOGGLE_BUTTON (options->type_w[1]) : - ((options->type_d == SHEAR) ? - GTK_TOGGLE_BUTTON (options->type_w[2]) : - GTK_TOGGLE_BUTTON (options->type_w[3])))), - TRUE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->smoothing_w), - options->smoothing_d); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->showpath_w), - options->showpath_d); - gtk_toggle_button_set_active (((options->direction_d == TRANSFORM_TRADITIONAL) ? - GTK_TOGGLE_BUTTON (options->direction_w[0]) : - GTK_TOGGLE_BUTTON (options->direction_w[1])), - TRUE); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->show_grid_w), - options->show_grid_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->grid_size_w), - 7.0 - log (options->grid_size_d) / log (2.0)); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->clip_w), - options->clip_d); -} - -static TransformOptions * -transform_options_new (void) -{ - TransformOptions *options; - - GtkWidget *table; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *frame; - GtkWidget *fbox; - GtkWidget *grid_density; - - /* the new transform tool options structure */ - options = g_new (TransformOptions, 1); - tool_options_init ((ToolOptions *) options, - _("Transform Tool"), - transform_options_reset); - options->type = options->type_d = ROTATE; - options->smoothing = options->smoothing_d = TRUE; - options->showpath = options->showpath_d = TRUE; - options->clip = options->clip_d = FALSE; - options->direction = options->direction_d = TRANSFORM_TRADITIONAL; - options->grid_size = options->grid_size_d = 32; - options->show_grid = options->show_grid_d = TRUE; - - /* the main table */ - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2); - gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), table, - FALSE, FALSE, 0); - - /* the left vbox */ - vbox = gtk_vbox_new (FALSE, 2); - gtk_table_attach_defaults (GTK_TABLE (table), vbox, 0, 1, 0, 1); - - /* the transform type radio buttons */ - frame = gimp_radio_group_new (TRUE, _("Transform"), - - _("Rotation"), transform_type_callback, - ROTATE, NULL, &options->type_w[0], TRUE, - _("Scaling"), transform_type_callback, - SCALE, NULL, &options->type_w[1], FALSE, - _("Shearing"), transform_type_callback, - SHEAR, NULL, &options->type_w[2], FALSE, - _("Perspective"), transform_type_callback, - PERSPECTIVE, NULL, &options->type_w[3], FALSE, - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); - gtk_widget_show (frame); - - gtk_widget_show (vbox); - - /* the right vbox */ - vbox = gtk_vbox_new (FALSE, 2); - gtk_table_attach_defaults (GTK_TABLE (table), vbox, 1, 2, 0, 1); - - /* the second radio frame and box, for transform direction */ - frame = gimp_radio_group_new (TRUE, _("Tool Paradigm"), - - _("Traditional"), transform_direction_callback, - TRANSFORM_TRADITIONAL, NULL, - &options->direction_w[0], TRUE, - _("Corrective"), transform_direction_callback, - TRANSFORM_CORRECTIVE, NULL, - &options->direction_w[1], FALSE, - - NULL); - - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - /* the grid frame */ - frame = gtk_frame_new (NULL); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - fbox = gtk_vbox_new (FALSE, 1); - gtk_container_set_border_width (GTK_CONTAINER (fbox), 2); - gtk_container_add (GTK_CONTAINER (frame), fbox); - - /* the show grid toggle button */ - options->show_grid_w = gtk_check_button_new_with_label (_("Show Grid")); - gtk_signal_connect (GTK_OBJECT (options->show_grid_w), "toggled", - GTK_SIGNAL_FUNC (transform_show_grid_update), - &options->show_grid); - gtk_box_pack_start (GTK_BOX (fbox), options->show_grid_w, FALSE, FALSE, 0); - gtk_widget_show (options->show_grid_w); - - /* the grid density entry */ - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - gtk_box_pack_start (GTK_BOX (fbox), hbox, FALSE, FALSE, 0); - label = gtk_label_new (_("Density:")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - options->grid_size_w = - gtk_adjustment_new (7.0 - log (options->grid_size_d) / log (2.0), 0.0, 5.0, - 1.0, 1.0, 0.0); - grid_density = - gtk_spin_button_new (GTK_ADJUSTMENT (options->grid_size_w), 0, 0); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (grid_density), TRUE); - gtk_signal_connect (GTK_OBJECT (options->grid_size_w), "value_changed", - GTK_SIGNAL_FUNC (transform_grid_density_callback), - &options->grid_size); - gtk_box_pack_start (GTK_BOX (hbox), grid_density, FALSE, FALSE, 0); - gtk_widget_show (grid_density); - gtk_widget_set_sensitive (label, options->show_grid_d); - gtk_widget_set_sensitive (grid_density, options->show_grid_d); - gtk_object_set_data (GTK_OBJECT (options->show_grid_w), "set_sensitive", - grid_density); - gtk_object_set_data (GTK_OBJECT (grid_density), "set_sensitive", label); - - gtk_widget_show (fbox); - gtk_widget_show (frame); - - gtk_widget_show (vbox); - - /* the smoothing toggle button */ - options->smoothing_w = gtk_check_button_new_with_label (_("Smoothing")); - gtk_signal_connect (GTK_OBJECT (options->smoothing_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->smoothing); - gtk_table_attach_defaults (GTK_TABLE (table), - options->smoothing_w, 0, 1, 1, 2); - gtk_widget_show (options->smoothing_w); - - /* the showpath toggle button */ - options->showpath_w = gtk_check_button_new_with_label (_("Show Path")); - gtk_signal_connect (GTK_OBJECT (options->showpath_w), "toggled", - GTK_SIGNAL_FUNC (transform_show_path_update), - &options->showpath); - gtk_table_attach_defaults (GTK_TABLE (table), - options->showpath_w, 1, 2, 1, 2); - gtk_widget_show (options->showpath_w); - - gtk_widget_show (table); - - /* the clip resulting image toggle button */ - options->clip_w = gtk_check_button_new_with_label (_("Clip Result")); - gtk_signal_connect (GTK_OBJECT (options->clip_w), "toggled", - GTK_SIGNAL_FUNC (gimp_toggle_button_update), - &options->clip); - gtk_box_pack_start (GTK_BOX (options->tool_options.main_vbox), - options->clip_w, FALSE, FALSE, 0); - gtk_widget_show (options->clip_w); - - return options; -} - -Tool * -tools_new_transform_tool (void) -{ - /* The tool options */ - if (! transform_options) - { - transform_options = transform_options_new (); - tools_register (ROTATE, (ToolOptions *) transform_options); - tools_register (SCALE, (ToolOptions *) transform_options); - tools_register (SHEAR, (ToolOptions *) transform_options); - tools_register (PERSPECTIVE, (ToolOptions *) transform_options); - - /* press all default buttons */ - transform_options_reset (); - } - - switch (transform_options->type) - { - case ROTATE: - return tools_new_rotate_tool (); - break; - case SCALE: - return tools_new_scale_tool (); - break; - case SHEAR: - return tools_new_shear_tool (); - break; - case PERSPECTIVE: - return tools_new_perspective_tool (); - break; - default : - return NULL; - break; - } -} - -void -tools_free_transform_tool (Tool *tool) -{ - switch (transform_options->type) - { - case ROTATE: - tools_free_rotate_tool (tool); - break; - case SCALE: - tools_free_scale_tool (tool); - break; - case SHEAR: - tools_free_shear_tool (tool); - break; - case PERSPECTIVE: - tools_free_perspective_tool (tool); - break; - default: - break; - } -} - -static void -transform_change_type (ToolType new_type) -{ - if (transform_options->type != new_type) - { - /* change the type, free the old tool, create the new tool */ - transform_options->type = new_type; - - if (gimp_context_get_tool (gimp_context_get_user ()) != new_type) - gimp_context_set_tool (gimp_context_get_user (), new_type); - else - gimp_context_tool_changed (gimp_context_get_user ()); - } -} - -gboolean -transform_tool_smoothing (void) -{ - if (!transform_options) - return TRUE; - else - return transform_options->smoothing; -} - -gboolean -transform_tool_showpath (void) -{ - if (!transform_options) - return TRUE; - else - return transform_options->showpath; -} - -gboolean -transform_tool_clip (void) -{ - if (!transform_options) - return FALSE; - else - return transform_options->clip; -} - -gint -transform_tool_direction (void) -{ - if (!transform_options) - return TRANSFORM_TRADITIONAL; - else - return transform_options->direction; -} - -gint -transform_tool_grid_size (void) -{ - if (!transform_options) - return 32; - else - return transform_options->grid_size; -} - -gboolean -transform_tool_show_grid (void) -{ - if (!transform_options) - return TRUE; - else - return transform_options->show_grid; -} diff --git a/app/transform_tool.h b/app/transform_tool.h deleted file mode 100644 index f2f6d467c0..0000000000 --- a/app/transform_tool.h +++ /dev/null @@ -1,39 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __TRANSFORM_TOOL_H__ -#define __TRANSFORM_TOOL_H__ - - -/* transform directions */ -#define TRANSFORM_TRADITIONAL 0 -#define TRANSFORM_CORRECTIVE 1 - -/* tool functions */ -Tool * tools_new_transform_tool (void); -void tools_free_transform_tool (Tool *tool); - -gboolean transform_tool_smoothing (void); -gboolean transform_tool_showpath (void); -gboolean transform_tool_clip (void); -gint transform_tool_direction (void); -gint transform_tool_grid_size (void); -gboolean transform_tool_show_grid (void); - - -#endif /* __TRANSFORM_TOOL_H__ */ diff --git a/app/undo.c b/app/undo.c index 2a356a4f87..6a8d757166 100644 --- a/app/undo.c +++ b/app/undo.c @@ -26,7 +26,6 @@ #include "apptypes.h" #include "appenv.h" -#include "by_color_select.h" #include "channel.h" #include "draw_core.h" #include "drawable.h" @@ -38,7 +37,6 @@ #include "gimpparasite.h" #include "gimprc.h" #include "layer.h" -#include "paint_core.h" #include "paint_funcs.h" #include "parasitelist.h" #include "path_transform.h" @@ -46,10 +44,13 @@ #include "tile_manager.h" #include "tile_manager_pvt.h" #include "tile.h" -#include "tools.h" -#include "transform_core.h" #include "undo.h" +#include "tools/by_color_select.h" +#include "tools/paint_core.h" +#include "tools/tools.h" +#include "tools/transform_core.h" + #include "libgimp/gimpparasite.h" #include "libgimp/gimpintl.h" diff --git a/app/widgets/gimpcursor.c b/app/widgets/gimpcursor.c index 881ac32cc2..8bcdb218a4 100644 --- a/app/widgets/gimpcursor.c +++ b/app/widgets/gimpcursor.c @@ -26,7 +26,8 @@ #include "cursorutil.h" #include "dialog_handler.h" #include "gdisplay.h" /* for gdisplay_*_override_cursor() */ -#include "tools.h" + +#include "tools/tools.h" #include "cursors/mouse.xbm" #include "cursors/mouse_mask.xbm" diff --git a/app/widgets/gimpdeviceinfo.c b/app/widgets/gimpdeviceinfo.c index 86d07ec8d9..3f7f2e91f6 100644 --- a/app/widgets/gimpdeviceinfo.c +++ b/app/widgets/gimpdeviceinfo.c @@ -39,7 +39,8 @@ #include "gradient_header.h" #include "patterns.h" #include "session.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/widgets/gimpdevices.c b/app/widgets/gimpdevices.c index 86d07ec8d9..3f7f2e91f6 100644 --- a/app/widgets/gimpdevices.c +++ b/app/widgets/gimpdevices.c @@ -39,7 +39,8 @@ #include "gradient_header.h" #include "patterns.h" #include "session.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/widgets/gimpdnd.c b/app/widgets/gimpdnd.c index 17967cfd87..0a409d59e6 100644 --- a/app/widgets/gimpdnd.c +++ b/app/widgets/gimpdnd.c @@ -38,7 +38,8 @@ #include "layer.h" #include "patterns.h" #include "temp_buf.h" -#include "tools.h" + +#include "tools/tools.h" #include "libgimp/gimplimits.h" #include "libgimp/gimpcolorarea.h" diff --git a/app/widgets/gimpitemfactory.c b/app/widgets/gimpitemfactory.c index 20b13ec2af..55c0636ff1 100644 --- a/app/widgets/gimpitemfactory.c +++ b/app/widgets/gimpitemfactory.c @@ -31,6 +31,7 @@ #include "commands.h" #include "dialog_handler.h" #include "fileops.h" +#include "gdisplay.h" #include "gimphelp.h" #include "gimprc.h" #include "gimpui.h" @@ -41,8 +42,8 @@ #include "paint_funcs.h" #include "preferences_dialog.h" #include "scale.h" -#include "tools.h" -#include "gdisplay.h" + +#include "tools/tools.h" #include "libgimp/gimpenv.h" diff --git a/app/xinput_airbrush.c b/app/xinput_airbrush.c deleted file mode 100644 index 8413451a10..0000000000 --- a/app/xinput_airbrush.c +++ /dev/null @@ -1,3271 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "config.h" - -#include -#include -#include - -#include "appenv.h" - -#include "airbrush_blob.h" -#include "drawable.h" -#include "draw_core.h" -#include "gdisplay.h" -#include "gimage_mask.h" -#include "gimprc.h" -#include "gimpui.h" -#include "paint_options.h" -#include "tools.h" -#include "undo.h" -#include "xinput_airbrush.h" - -#include "libgimp/gimpintl.h" -#include "libgimp/gimpmath.h" - -#include "tile.h" /* ick. */ - - -#define SUBSAMPLE 8 - -#define DIST_SMOOTHER_BUFFER 10 -#define TIME_SMOOTHER_BUFFER 10 - -/* the XinputAirbrush structures */ - -typedef struct _XinputAirbrushTool XinputAirbrushTool; -struct _XinputAirbrushTool - { - DrawCore * core; /* Core select object */ - - AirBrush * last_airbrush; - AirBrushBlob * last_airbrush_blob; /* airbrush_blob for last cursor position */ - AirBlob * last_airblob; - - - int x1, y1; /* image space coordinate */ - int x2, y2; /* image space coords */ - - /* circular distance history buffer */ - gdouble dt_buffer[DIST_SMOOTHER_BUFFER]; - gint dt_index; - - /* circular timing history buffer */ - guint32 ts_buffer[TIME_SMOOTHER_BUFFER]; - gint ts_index; - - /* Direction and center point */ - double xcenter, ycenter; - double direction_abs; - double direction; - double c_direction; - double c_direction_abs; - - - gdouble last_time; /* previous time of a motion event */ - gdouble lastx, lasty; /* previous position of a motion event */ - gdouble last_lastx, last_lasty; /* The previous previous position of a motion event i.e pos of the blob */ - - gboolean init_velocity; - gboolean init_prepre; - - double last_value; - - }; - - -typedef struct _XinputAirbrushOptions XinputAirbrushOptions; -struct _XinputAirbrushOptions - { - PaintOptions paint_options; - - double flow; - double flow_d; - GtkObject *flow_w; - - double sensitivity; - double sensitivity_d; - GtkObject *sensitivity_w; - - double starttilt; - double starttilt_d; - GtkObject *starttilt_w; - - double vel_sensitivity; - double vel_sensitivity_d; - GtkObject *vel_sensitivity_w; - - double tilt_sensitivity; - double tilt_sensitivity_d; - GtkObject *tilt_sensitivity_w; - -#ifdef GTK_HAVE_SIX_VALUATORS - double minheight; - double minheight_d; - GtkObject *minheight_w; - - - double maxheight; - double maxheight_d; - GtkObject *maxheight_w; -#else /* !GTK_HAVE_SIX_VALUATORS */ - double height; - double height_d; - GtkObject *height_w; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - }; - - -/* the xinput_airbrush tool options */ -static XinputAirbrushOptions *xinput_airbrush_options = NULL; - -/* local variables */ - -/* undo blocks variables */ -static TileManager * undo_tiles = NULL; - -/* Tiles used to render the stroke at 1 byte/pp */ -static TileManager * canvas_tiles = NULL; - -/* Flat buffer that is used to used to render the dirty region - * for composition onto the destination drawable - */ -static TempBuf * canvas_buf = NULL; - - -/* local function prototypes */ - -static void xinput_airbrush_button_press (Tool *, GdkEventButton *, gpointer); -static void xinput_airbrush_button_release (Tool *, GdkEventButton *, gpointer); -static void xinput_airbrush_motion (Tool *, GdkEventMotion *, gpointer); -static void xinput_airbrush_cursor_update (Tool *, GdkEventMotion *, gpointer); -static void xinput_airbrush_control (Tool *, ToolAction, gpointer); - -static void time_smoother_add (XinputAirbrushTool* xinput_airbrush_tool, guint32 value); -static gdouble time_smoother_result (XinputAirbrushTool* xinput_airbrush_tool); -static void time_smoother_init (XinputAirbrushTool* xinput_airbrush_tool, guint32 initval); -static void dist_smoother_add (XinputAirbrushTool* xinput_airbrush_tool, gdouble value); -static gdouble dist_smoother_result (XinputAirbrushTool* xinput_airbrush_tool); -static void dist_smoother_init (XinputAirbrushTool* xinput_airbrush_tool, gdouble initval); - -static void xinput_airbrush_init (XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - double x, - double y); - -static void xinput_airbrush_finish (XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - int tool_id); - -static void xinput_airbrush_cleanup (void); - - -/*Mask functions*/ - -static void calc_angle (AirBrushBlob *airbrush_blob, - double xcenter, - double ycenter); - -static void calc_width (AirBrushBlob *airbrush_blob); - - -static void render_airbrush_line (AirBrushBlob *airbrush_blob, - guchar *dest, - int y, - int width, - XinputAirbrushTool *xinput_airbrush_tool); - - - -static void make_single_mask (AirBrushBlob *airbrush_blob, - XinputAirbrushTool *xinput_airbrush_tool, - MaskBuf *dest); - -static void make_stroke(AirBlob *airblob, - XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - guint last_value, - guint present_value); - - - -static void make_mask(AirLine *airline, - MaskBuf *brush_mask, - guint value); - - - - -static void print_mask(MaskBuf *dest); - - - - -/* Rendering functions */ - -static void xinput_airbrush_set_paint_area (XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - int x, - int y, - int width, - int height); - -static void xinput_airbrush_paste (XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - MaskBuf *brush_mask, - int x, - int y, - int width, - int height); - -static void xinput_airbrush_to_canvas_tiles (XinputAirbrushTool *xinput_airbrush_tool, - MaskBuf *brush_mask, - int brush_opacity); - -static void xinput_airbrush_canvas_tiles_to_canvas_buf(XinputAirbrushTool *xinput_airbrush_tool); - -static void xinput_airbrush_set_undo_tiles (GimpDrawable *drawable, - int x, - int y, - int w, - int h); - -static void xinput_airbrush_set_canvas_tiles(int x, - int y, - int w, - int h); - - - -/* Start of functions */ - - -static void - xinput_airbrush_options_reset (void) - { - XinputAirbrushOptions *options = xinput_airbrush_options; - - paint_options_reset ((PaintOptions *) options); - - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->flow_w), - options->flow_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->sensitivity_w), - options->sensitivity_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->starttilt_w), - options->starttilt_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->tilt_sensitivity_w), - options->tilt_sensitivity_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->vel_sensitivity_w), - options->vel_sensitivity_d); -#ifdef GTK_HAVE_SIX_VALUATORS - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->minheight_w), - options->minheight_d); - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->maxheight_w), - options->maxheight_d); -#else /* !GTK_HAVE_SIX_VALUATORS */ - gtk_adjustment_set_value (GTK_ADJUSTMENT (options->height_w), - options->height_d); -#endif /* GTK_HAVE_SIX_VALUATORS */ - - } - -static XinputAirbrushOptions * - xinput_airbrush_options_new (void) - { - XinputAirbrushOptions *options; - - GtkWidget *table; - GtkWidget *abox; - GtkWidget *label; - GtkWidget *slider; - - /* the new xinput_airbrush tool options structure */ - options = (XinputAirbrushOptions *) g_malloc (sizeof (XinputAirbrushOptions)); - paint_options_init ((PaintOptions *) options, - XINPUT_AIRBRUSH, - xinput_airbrush_options_reset); - options->flow = options->flow_d = 100; - options->sensitivity = options->sensitivity_d = 1.0; - options->starttilt = options->starttilt_d = 90; - options->vel_sensitivity = options->vel_sensitivity_d = 0.8; - options->tilt_sensitivity = options->tilt_sensitivity_d = 0.4; -#ifdef GTK_HAVE_SIX_VALUATORS - options->minheight = options->minheight_d = 25.0; - options->maxheight = options->maxheight_d = 50.0; -#else /* !GTK_HAVE_SIX_VALUATORS */ - options->height = options->height_d = 45.0; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - /*the main table*/ - - table = gtk_table_new (6, 2, FALSE); - gtk_box_pack_start (GTK_BOX (((ToolOptions *) options)->main_vbox), table, - FALSE, FALSE, 0); - - /*flow slider*/ - label = gtk_label_new (_("Flow Relation:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - options->flow_w = - gtk_adjustment_new (options->flow_d, 50.0, 201.0, 1.0, 10.0, 1.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->flow_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->flow_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->flow); - gtk_widget_show (slider); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - - /*flow sens slider*/ - label = gtk_label_new (_("Flow Sensitivity:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - options->sensitivity_w = - gtk_adjustment_new (options->sensitivity_d, 0.0, 1.0, 0.01, 0.1, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->sensitivity_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->sensitivity_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->sensitivity); - gtk_widget_show (slider); - - - /*base tilt slider*/ - - label = gtk_label_new (_("Base Tilt:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - options->starttilt_w = - gtk_adjustment_new (options->starttilt_d, 30.0 , 91.0, 1.0, 1.0, 1.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->starttilt_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 2, 3); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->starttilt_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->starttilt); - gtk_widget_show (slider); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - - - - /*tilt sens slider*/ - - - label = gtk_label_new (_("Tilt Sensitivity:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); - gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 3, 4, - GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (abox); - - options->tilt_sensitivity_w = - gtk_adjustment_new (options->tilt_sensitivity_d, 0.0, 1.0, 0.01, 0.1, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->tilt_sensitivity_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_container_add (GTK_CONTAINER (abox), slider); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->tilt_sensitivity_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->tilt_sensitivity); - gtk_widget_show (slider); - - - /*velocity sens slider*/ - - - label = gtk_label_new (_("Speed Sensitivity:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 5, 6, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); - gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 5, 6, - GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (abox); - - options->vel_sensitivity_w = - gtk_adjustment_new (options->vel_sensitivity_d, 0.0, 1.0, 0.01, 0.1, 0.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->vel_sensitivity_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_container_add (GTK_CONTAINER (abox), slider); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->vel_sensitivity_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->vel_sensitivity); - gtk_widget_show (slider); - -#ifdef GTK_HAVE_SIX_VALUATORS - - - /*min height slider*/ - - label = gtk_label_new (_("Min Height:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 7, 8, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - options->minheight_w = - gtk_adjustment_new (options->minheight_d, 25.0 , 41.0, 1.0, 1.0, 1.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->minheight_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 7, 8); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->minheight_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->minheight); - gtk_widget_show (slider); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - - - /*max height slider*/ - - label = gtk_label_new (_("Max Height:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 9, 10, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - options->maxheight_w = - gtk_adjustment_new (options->maxheight_d, 41.0 , 81.0, 1.0, 1.0, 1.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->maxheight_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 9, 10); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->maxheight_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->maxheight); - gtk_widget_show (slider); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - - -#else /* !GTK_HAVE_SIX_VALUATORS */ - - label = gtk_label_new (_("Height:")); - gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 7, 8, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show (label); - - options->height_w = - gtk_adjustment_new (options->height_d, 25.0 , 81.0, 1.0, 1.0, 1.0); - slider = gtk_hscale_new (GTK_ADJUSTMENT (options->height_w)); - gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP); - gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 7, 8); - gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED); - gtk_signal_connect (GTK_OBJECT (options->height_w), "value_changed", - GTK_SIGNAL_FUNC (gimp_double_adjustment_update), - &options->height); - gtk_widget_show (slider); - gtk_scale_set_digits (GTK_SCALE (slider), 0); - -#endif /* GTK_HAVE_SIX_VALUATORS */ - - gtk_widget_show_all (table); - - return options; - } - - -static AirBlob * -#ifdef GTK_HAVE_SIX_VALUATORS -xinput_airbrush_pen_ellipse (XinputAirbrushTool *xinput_airbrush_tool, - gdouble x_center, gdouble y_center, - gdouble pressure, gdouble xtiltv, - gdouble ytiltv, gdouble wheel) -#else /* !GTK_HAVE_SIX_VALUATORS */ -xinput_airbrush_pen_ellipse (XinputAirbrushTool *xinput_airbrush_tool, - gdouble x_center, gdouble y_center, - gdouble pressure, gdouble xtiltv, - gdouble ytiltv) -#endif /* GTK_HAVE_SIX_VALUATORS */ -{ - - gdouble xtilt, ytilt; - double height; -#ifdef GTK_HAVE_SIX_VALUATORS - double inter_height; - double min_height; - double max_height; -#endif /* GTK_HAVE_SIX_VALUATORS */ - double tanx, tany; - double tanytop, tanxright, tanybot, tanxleft; - double sprayangle; - double distx, disty; - double ytop, xright, ybot, xleft; - - - - - - /* Virtual height over the drawing */ - -#ifdef GTK_HAVE_SIX_VALUATORS - min_height=xinput_airbrush_options->minheight; - max_height=xinput_airbrush_options->maxheight; - - inter_height = CLAMP(wheel, 0.0, 1.0) * (max_height - min_height); - height = min_height + inter_height; - - /* - printf("Height: %f\n", height); - */ - -#else /* !GTK_HAVE_SIX_VALUATORS */ - height = xinput_airbrush_options->height; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - - /* - - Fix av tilt negative when it should be positive - Also a clamp of to big tilts compared to the height - i.e you will not get big brushes - - */ - - xtilt = xtiltv * -1.0 * (1 - ((0.5 * (height - 15))/100)); - ytilt = ytiltv * -1.0 * (1 - ((0.5 * (height - 15))/100)); - - - - /* The airflow controls the spray angel - High airflow renders in a big spray angel - but if the inkflow is low the blob will be - very thin. - */ - - sprayangle = G_PI/6 * (xinput_airbrush_options->flow/100.0) * MAX(pressure, 0.1); - - sprayangle = MAX(sprayangle, 0.0); - - /*printf("Angle: %f\n", sprayangle);*/ - - /*Tan of x and y tilt plus spray angles x r/l and y t/b tan*/ - - tanx = tan(xtilt * G_PI / 2.0); - tany = tan(ytilt * G_PI / 2.0); - - - tanytop = tan((ytilt * G_PI / 2.0) + (sprayangle/2)); - tanxright = tan((xtilt * G_PI / 2.0) + (sprayangle/2)); - tanybot = tan((ytilt * G_PI / 2.0) - (sprayangle/2)); - tanxleft = tan((xtilt * G_PI / 2.0) - (sprayangle/2)); - - /* Offset from cursor due to tilt in x and y depening on the hight*/ - - distx = tanx * height; - disty = tany * height; - - /* Offset from center of blob in all for axies */ - - ytop = fabs(fabs(tanytop * height) - fabs(disty)); - xright = fabs(fabs(tanxright * height) - fabs(distx)); - ybot = fabs(fabs(tanybot * height) - fabs(disty)); - xleft = fabs(fabs(tanxleft * height) - fabs(distx)); - - x_center = x_center + distx; - y_center = y_center + disty; - - - xinput_airbrush_tool->xcenter=x_center; - xinput_airbrush_tool->ycenter=y_center; - xinput_airbrush_tool->direction_abs=atan2(ytiltv, xtiltv) + G_PI; - xinput_airbrush_tool->direction=atan(ytiltv/xtiltv); - xinput_airbrush_tool->c_direction=atan(ytiltv/xtilt); - xinput_airbrush_tool->c_direction_abs=atan2(ytiltv, xtilt) + G_PI; - - return create_air_blob(x_center * SUBSAMPLE, y_center * SUBSAMPLE, - 0., ytop * SUBSAMPLE, xright * SUBSAMPLE, 0., - 0., ybot * SUBSAMPLE, xleft * SUBSAMPLE, 0., - (xinput_airbrush_tool->c_direction_abs - G_PI), - xinput_airbrush_tool->c_direction); -} - -static void -xinput_airbrush_button_press (Tool *tool, - GdkEventButton *bevent, - gpointer gdisp_ptr) -{ - gdouble x, y; - GDisplay *gdisp; - XinputAirbrushTool *xinput_airbrush_tool; - GimpDrawable *drawable; - AirBlob *airblob; - AirLine *airline; - MaskBuf *brush_mask; - int width, height; - int x_min, y_min; - guint value; - - - - gdisp = (GDisplay *) gdisp_ptr; - xinput_airbrush_tool = (XinputAirbrushTool *) tool->private; - - /* Keep the coordinates of the target */ - gdisplay_untransform_coords_f (gdisp, bevent->x, bevent->y, - &x, &y, TRUE); - drawable = gimage_active_drawable (gdisp->gimage); - - xinput_airbrush_init (xinput_airbrush_tool, drawable, x, y); - - tool->state = ACTIVE; - tool->gdisp_ptr = gdisp_ptr; - tool->paused_count = 0; - - /* pause the current selection and grab the pointer */ - gdisplays_selection_visibility (gdisp->gimage, SelectionPause); - - /* add motion memory if you press mod1 first ^ perfectmouse */ - if (((bevent->state & GDK_MOD1_MASK) != 0) != (perfectmouse != 0)) - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - else - gdk_pointer_grab (gdisp->canvas->window, FALSE, - GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, bevent->time); - - tool->gdisp_ptr = gdisp_ptr; - tool->state = ACTIVE; - - - /* Get the AirBlob from xinput_airbrush_pen_ellipse */ - -#ifdef GTK_HAVE_SIX_VALUATORS - - airblob = xinput_airbrush_pen_ellipse (xinput_airbrush_tool, x, y, - bevent->pressure, bevent->xtilt, - bevent->ytilt, bevent->wheel); -#else /* !GTK_HAVE_SIX_VALUATORS */ - - airblob = xinput_airbrush_pen_ellipse (xinput_airbrush_tool, x, y, - bevent->pressure, bevent->xtilt, - bevent->ytilt); -#endif /* GTK_HAVE_SIX_VALUATORS */ - - - /* Make the AirBlob mask */ - - value = 256 * bevent->pressure; - - airline = create_air_line(airblob); - x_min = airline->min_x; - y_min = airline->min_y; - width = airline->width; - height = airline->height; - - brush_mask = mask_buf_new(width, height); - - make_mask(airline, brush_mask, value); - - /*print_mask(brush_mask);*/ - - /*Paint the mask on the drawable*/ - - xinput_airbrush_paste (xinput_airbrush_tool, drawable, brush_mask, x_min, y_min, width, height); - - /*Prepare for next stroke*/ - - xinput_airbrush_tool->last_airblob = airblob; - - time_smoother_init (xinput_airbrush_tool, bevent->time); - xinput_airbrush_tool->last_time = bevent->time; - dist_smoother_init (xinput_airbrush_tool, 0.0); - xinput_airbrush_tool->init_velocity = TRUE; - xinput_airbrush_tool->init_prepre = FALSE; - xinput_airbrush_tool->lastx = xinput_airbrush_tool->xcenter; - xinput_airbrush_tool->lasty = xinput_airbrush_tool->ycenter; - xinput_airbrush_tool->last_value = value; - - /*Free the maks_buf and airline*/ - - mask_buf_free(brush_mask); - g_free(airline); - - gdisplay_flush_now (gdisp); - -} - -static void - xinput_airbrush_button_release (Tool *tool, - GdkEventButton *bevent, - gpointer gdisp_ptr) - { - GDisplay * gdisp; - GImage * gimage; - XinputAirbrushTool * xinput_airbrush_tool; - - gdisp = (GDisplay *) gdisp_ptr; - gimage = gdisp->gimage; - xinput_airbrush_tool = (XinputAirbrushTool *) tool->private; - - /* resume the current selection and ungrab the pointer */ - gdisplays_selection_visibility (gdisp->gimage, SelectionResume); - - gdk_pointer_ungrab (bevent->time); - gdk_flush (); - - /* Set tool state to inactive -- no longer painting */ - tool->state = INACTIVE; - - xinput_airbrush_finish (xinput_airbrush_tool, gimage_active_drawable (gdisp->gimage), tool->ID); - gdisplays_flush (); - } - - -static void - dist_smoother_init (XinputAirbrushTool* xinput_airbrush_tool, gdouble initval) - { - gint i; - - xinput_airbrush_tool->dt_index = 0; - - for (i=0; idt_buffer[i] = initval; - } - } - -static gdouble - dist_smoother_result (XinputAirbrushTool* xinput_airbrush_tool) - { - gint i; - gdouble result = 0.0; - - for (i=0; idt_buffer[i]; - } - - return (result / (gdouble)DIST_SMOOTHER_BUFFER); - } - -static void - dist_smoother_add (XinputAirbrushTool* xinput_airbrush_tool, gdouble value) - { - xinput_airbrush_tool->dt_buffer[xinput_airbrush_tool->dt_index] = value; - - if ((++xinput_airbrush_tool->dt_index) == DIST_SMOOTHER_BUFFER) - xinput_airbrush_tool->dt_index = 0; - } - - -static void - time_smoother_init (XinputAirbrushTool* xinput_airbrush_tool, guint32 initval) - { - gint i; - - xinput_airbrush_tool->ts_index = 0; - - for (i=0; its_buffer[i] = initval; - } - } - -static gdouble - time_smoother_result (XinputAirbrushTool* xinput_airbrush_tool) - { - gint i; - guint64 result = 0; - - for (i=0; its_buffer[i]; - } - -#ifdef _MSC_VER - return (gdouble) (gint64) (result / TIME_SMOOTHER_BUFFER); -#else - return (result / TIME_SMOOTHER_BUFFER); -#endif - } - -static void - time_smoother_add (XinputAirbrushTool* xinput_airbrush_tool, guint32 value) - { - xinput_airbrush_tool->ts_buffer[xinput_airbrush_tool->ts_index] = value; - - if ((++xinput_airbrush_tool->ts_index) == TIME_SMOOTHER_BUFFER) - xinput_airbrush_tool->ts_index = 0; - } - - -static void - xinput_airbrush_motion (Tool *tool, - GdkEventMotion *mevent, - gpointer gdisp_ptr) - { - GDisplay *gdisp; - XinputAirbrushTool *xinput_airbrush_tool; - GimpDrawable *drawable; - AirBlob *airblob; - - double x, y; - double pressure; - double velocity; - double dist; - gdouble lasttime, thistime; - guint last_value, present_value; - double a, b, c, A; - - gboolean turn_around; - -#ifdef GTK_HAVE_SIX_VALUATORS - double min_height; - double max_height; - double inter_height; -#endif /* GTK_HAVE_SIX_VALUATORS */ - double height; - - gdisp = (GDisplay *) gdisp_ptr; - xinput_airbrush_tool = (XinputAirbrushTool *) tool->private; - - gdisplay_untransform_coords_f (gdisp, mevent->x, mevent->y, &x, &y, TRUE); - drawable = gimage_active_drawable (gdisp->gimage); - - pressure = mevent->pressure; - -#ifdef GTK_HAVE_SIX_VALUATORS - airblob = xinput_airbrush_pen_ellipse (xinput_airbrush_tool, x, y, pressure, mevent->xtilt, mevent->ytilt, mevent->wheel); -#else /* !GTK_HAVE_SIX_VALUATORS */ - airblob = xinput_airbrush_pen_ellipse (xinput_airbrush_tool, x, y, pressure, mevent->xtilt, mevent->ytilt); -#endif /* GTK_HAVE_SIX_VALUATORS */ - - x = xinput_airbrush_tool->xcenter; - y = xinput_airbrush_tool->ycenter; - - lasttime = xinput_airbrush_tool->last_time; - - time_smoother_add (xinput_airbrush_tool, mevent->time); - thistime = xinput_airbrush_tool->last_time = - time_smoother_result(xinput_airbrush_tool); - - /* The time resolution on X-based GDK motion events is - bloody awful, hence the use of the smoothing function. - Sadly this also means that there is always the chance of - having an indeterminite velocity since this event and - the previous several may still appear to issue at the same - instant. -ADM */ - - if (thistime == lasttime) - thistime = lasttime + 1; - - if (xinput_airbrush_tool->init_velocity) - { - dist_smoother_init (xinput_airbrush_tool, dist = sqrt((xinput_airbrush_tool->lastx-x)*(xinput_airbrush_tool->lastx-x) + - (xinput_airbrush_tool->lasty-y)*(xinput_airbrush_tool->lasty-y))); - xinput_airbrush_tool->init_velocity = FALSE; - } - else - { - dist_smoother_add (xinput_airbrush_tool, sqrt((xinput_airbrush_tool->lastx-x)*(xinput_airbrush_tool->lastx-x) + - (xinput_airbrush_tool->lasty-y)*(xinput_airbrush_tool->lasty-y))); - dist = dist_smoother_result(xinput_airbrush_tool); - } - - turn_around = FALSE; - - if (xinput_airbrush_tool->init_prepre) - { - a = hypot(xinput_airbrush_tool->last_lastx - x, xinput_airbrush_tool->last_lasty - y); - b = hypot(xinput_airbrush_tool->lastx - x, xinput_airbrush_tool->lasty - y); - c = hypot(xinput_airbrush_tool->last_lastx - xinput_airbrush_tool->lastx, xinput_airbrush_tool->last_lasty - xinput_airbrush_tool->lasty); - - /* Maybe fix the fact that a, b or c can be zero i.e that we had a perfectly strait turn around or continue*/ - A = acos((b*b + c*c - a*a)/2*b*c); - /* 1.65806 RAD == 95deg*/ - if ( (A >= 0.0) && (A < 1.65806) ) - { - turn_around = TRUE; - /* printf("TURN_AROUND\n");*/ - } - - } - - velocity = 10.0 * sqrt((dist) / (double)(thistime - lasttime)); - - - /* Normal Speed is 2.0, Break point for zero ink is 18. - Slow speed is between 2.0 and 0.5 */ - - - /*printf("Speed: %f\n", velocity);*/ - -#ifdef GTK_HAVE_SIX_VALUATORS - min_height=xinput_airbrush_options->minheight; - max_height=xinput_airbrush_options->maxheight; - - inter_height = CLAMP(mevent->wheel, 0.0, 1.0) * (max_height - min_height); - height = min_height + inter_height; - - /* - printf("Height: %f\n", height); - */ - -#else /* !GTK_HAVE_SIX_VALUATORS */ - height = xinput_airbrush_options->height; -#endif /* GTK_HAVE_SIX_VALUATORS */ - - last_value = xinput_airbrush_tool->last_value; - - present_value = 256 * pressure * (1 - ((height - 25)/100)); - - make_stroke(airblob, xinput_airbrush_tool, drawable, last_value, present_value); - - xinput_airbrush_tool->last_lastx = xinput_airbrush_tool->lastx; - xinput_airbrush_tool->last_lasty = xinput_airbrush_tool->lasty; - xinput_airbrush_tool->lastx = x; - xinput_airbrush_tool->lasty = y; - xinput_airbrush_tool->last_value = present_value; - - g_free(xinput_airbrush_tool->last_airblob); - xinput_airbrush_tool->last_airblob = airblob; - - xinput_airbrush_tool->init_velocity = TRUE; - xinput_airbrush_tool->init_prepre = TRUE; - - gdisplay_flush_now (gdisp); - } - -static void - xinput_airbrush_cursor_update (Tool *tool, - GdkEventMotion *mevent, - gpointer gdisp_ptr) - { - GDisplay *gdisp; - Layer *layer; - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; - int x, y; - - gdisp = (GDisplay *) gdisp_ptr; - - gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, FALSE, FALSE); - if ((layer = gimage_get_active_layer (gdisp->gimage))) - { - int off_x, off_y; - drawable_offsets (GIMP_DRAWABLE(layer), &off_x, &off_y); - if (x >= off_x && y >= off_y && - x < (off_x + drawable_width (GIMP_DRAWABLE(layer))) && - y < (off_y + drawable_height (GIMP_DRAWABLE(layer)))) - { - /* One more test--is there a selected region? - * if so, is cursor inside? - */ - if (gimage_mask_is_empty (gdisp->gimage)) - ctype = GDK_PENCIL; - else if (gimage_mask_value (gdisp->gimage, x, y)) - ctype = GDK_PENCIL; - } - } - gdisplay_install_tool_cursor (gdisp, ctype); - } - -static void - xinput_airbrush_control (Tool *tool, - ToolAction action, - gpointer gdisp_ptr) - { - XinputAirbrushTool *xinput_airbrush_tool; - - xinput_airbrush_tool = (XinputAirbrushTool *) tool->private; - - switch (action) - { - case PAUSE: - draw_core_pause (xinput_airbrush_tool->core, tool); - break; - - case RESUME: - draw_core_resume (xinput_airbrush_tool->core, tool); - break; - - case HALT: - xinput_airbrush_cleanup (); - break; - - default: - break; - } - } - -static void - xinput_airbrush_init (XinputAirbrushTool *xinput_airbrush_tool, GimpDrawable *drawable, - double x, double y) - { - /* free the block structures */ - if (undo_tiles) - tile_manager_destroy (undo_tiles); - if (canvas_tiles) - tile_manager_destroy (canvas_tiles); - - /* Allocate the undo structure */ - undo_tiles = tile_manager_new (drawable_width (drawable), - drawable_height (drawable), - drawable_bytes (drawable)); - - /* Allocate the canvas blocks structure */ - canvas_tiles = tile_manager_new (drawable_width (drawable), - drawable_height (drawable), 1); - - /* Get the initial undo extents */ - xinput_airbrush_tool->x1 = xinput_airbrush_tool->x2 = x; - xinput_airbrush_tool->y1 = xinput_airbrush_tool->y2 = y; - } - -static void - xinput_airbrush_finish (XinputAirbrushTool *xinput_airbrush_tool, GimpDrawable *drawable, int tool_id) - { - /* push an undo */ - drawable_apply_image (drawable, xinput_airbrush_tool->x1, xinput_airbrush_tool->y1, - xinput_airbrush_tool->x2, xinput_airbrush_tool->y2, undo_tiles, TRUE); - undo_tiles = NULL; - - /* invalidate the drawable--have to do it here, because - * it is not done during the actual painting. - */ - gimp_drawable_invalidate_preview (drawable, TRUE); - } - -static void - xinput_airbrush_cleanup (void) - { - /* CLEANUP */ - /* If the undo tiles exist, nuke them */ - if (undo_tiles) - { - tile_manager_destroy (undo_tiles); - undo_tiles = NULL; - } - - /* If the canvas blocks exist, nuke them */ - if (canvas_tiles) - { - tile_manager_destroy (canvas_tiles); - canvas_tiles = NULL; - } - - /* Free the temporary buffer if it exist */ - if (canvas_buf) - temp_buf_free (canvas_buf); - canvas_buf = NULL; - } - -/********************************* - * Rendering functions * - *********************************/ - -/* Some of this stuff should probably be combined with the - * code it was copied from in paint_core.c; but I wanted - * to learn this stuff, so I've kept it simple. - */ - -static inline int -number_of_steps(int x0, int y0, int x1, int y1) -{ - - - int dx, dy; - - dx = abs(x0 - x1); - - dy = abs(y0 - y1); - - if (dy > dx) - { - return dy + 1; - } - else - { - return dx + 1; - } -} - - - -static void -make_stroke(AirBlob *airblob, - XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - guint last_value, - guint present_value) -{ - - int steps; - int i, j, k; - - - int dx, dy; - int x, y; - - - int x0, x1, y0, y1; - - double x0d, x1d, y0d, y1d; - - int x_min, x_max, y_min, y_max, width, height; - int number, ystart, xstart; - - guint ivalue; - double lv, pv, mv; - - double dist; - - int slopeterm; - - AirBlob *last_airblob; - AirBlob *trans_blob; - AirLine *air_line; - MaskBuf *brush_mask; - MaskBuf **bufs; - guchar *source; - guchar *dest; - int *xpoints; - int *ypoints; - - gboolean something; - - something = FALSE; - - x0 = xinput_airbrush_tool->lastx; - x1 = xinput_airbrush_tool->xcenter; - y0 = xinput_airbrush_tool->lasty; - y1 = xinput_airbrush_tool->ycenter; - - x0d = xinput_airbrush_tool->lastx; - x1d = xinput_airbrush_tool->xcenter; - y0d = xinput_airbrush_tool->lasty; - y1d = xinput_airbrush_tool->ycenter; - - last_airblob = xinput_airbrush_tool->last_airblob; - - steps = number_of_steps(x0, y0, x1, y1); - - /* - printf("Stoke Steps: %d\n", steps); - */ - - ypoints = g_new(int, steps); - xpoints = g_new(int, steps); - - bufs = g_new (MaskBuf*, steps); - - dx = abs(x0 - x1); - dy = abs(y0 - y1); - - lv = last_value; - pv = present_value; - mv = pv - lv; - - - /* - Yes I know this is bulky code :-), - --> see comment on make_mask. - - But I wanted to keep it simple while I - implemented the tool :-). I will make it - more effective later on. And yes I could - look for the three special cases. - */ - - - /* - There is also a possiblity of a bug in the - scanline function that will explain the - "jumping lines". - */ - - - - if (dy > dx) - { - /* Step in the y direction*/ - if (y0 < y1) - { - /* - Step from y0 to y1 - */ - if(x1 < x0) - { - /* - We have to x-- - */ - x = x0; - y = y0; - - number = 0; - - j = 1; - - slopeterm = dx; - - while(y < y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x--; - y++; - } - else - { - slopeterm += dx; - y++; - } - - j++; - - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - - } - else - { - /* - We have to x++ - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dx; - - j = 1; - - while(y < y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x++; - y++; - } - else - { - slopeterm += dx; - y++; - } - - j++; - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - } - } - else - { - /* Step from y0 to y1 with neg steps */ - if(x1 < x0) - { - /* - We have to x-- - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dx; - - j = 1; - - while(y > y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x--; - y--; - } - else - { - slopeterm += dx; - y--; - } - - j++; - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - } - else - { - /* - We have to x++ - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dx; - - j = 1; - - while(y > y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x++; - y--; - } - else - { - slopeterm += dx; - y--; - } - - j++; - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - } - } - - } - else - { - /* Step in the X direction*/ - if (x0 < x1) - { - /* Step from x0 to x1 */ - if(y1 < y0) - { - /* - We have to y-- - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dy; - - j = 1; - - while(x < x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y--; - x++; - } - else - { - slopeterm += dy; - x++; - } - - j++; - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - - } - else - { - /* - We have to y++ - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dy; - - j = 1; - - while(x < x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y++; - x++; - } - else - { - slopeterm += dy; - x++; - } - - j++; - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - } - } - else - { - /* Step from x0 to x1 neg direction */ - if(y1 < y0) - { - /* - We have to y-- - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dy; - - j = 1; - - while(x > x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y--; - x--; - } - else - { - slopeterm += dy; - x--; - } - - j++; - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - } - else - { - /* - We have to y++ - */ - x = x0; - y = y0; - - number = 0; - - slopeterm = dy; - - j = 1; - - while(x > x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y++; - x--; - } - else - { - slopeterm += dy; - x--; - } - - j++; - - dist = 1.0 - (double)j/(double)steps; - ivalue = lv + mv * dist; - - trans_blob = trans_air_blob(last_airblob, airblob, dist, x, y); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], ivalue); - number++; - something = TRUE; - } - } - } - } - - if(!something) - { - /* - printf("Nothing \n"); - */ - number = 0; - - dist = 1.0; - - trans_blob = trans_air_blob(last_airblob, airblob, 0.5 , x1, y1); - air_line = create_air_line(trans_blob); - - x_min = air_line->min_x; - y_min = air_line->min_y; - width = air_line->width; - height = air_line->height; - - bufs[number] = mask_buf_new(width, height); - ypoints[number] = y_min; - xpoints[number] = x_min; - make_mask(air_line, bufs[number], pv); - /* - print_mask(bufs[number]); - */ - brush_mask = mask_buf_new(width, height); - dest = brush_mask->data; - source = bufs[number]->data; - - - for(k = 0; k < bufs[number]->height; k++) - { - for(j = 0; j < bufs[number]->width; j++ ) - { - if(((int)dest[k * width + j] + (int)source[k * bufs[number]->width + j]) > 255) - { - dest[k * width + j] = 255; - } - else - { - dest[k * width + j] += source[k * bufs[number]->width + j]; - } - } - } - - - xinput_airbrush_paste (xinput_airbrush_tool, drawable, brush_mask, x_min, y_min, width, height); - - /* - print_mask(brush_mask); - */ - mask_buf_free(brush_mask); - - mask_buf_free(bufs[number]); - g_free(bufs); - /* - printf("Nothing again\n"); - */ - } - - if(something) - { - - y_min = y_max = ypoints[0]; - height = bufs[0]->height; - - x_min = x_max= xpoints[0]; - width = bufs[0]->width; - - /*printf("xmin %d, ymin %d, width %d, weight %d\n", x_min, y_min, width, height);*/ - - - for (i = 1; i < steps -1; i++) - { - /*printf("xmin %d, ymin %d, width %d, weight %d\n", xpoints[i], ypoints[i], bufs[i]->width, bufs[i]->height);*/ - - - x_min = MIN(xpoints[i], x_min); - y_min = MIN(ypoints[i], y_min); - if ((x_max + width) < (xpoints[i] + bufs[i]->width)) - { - x_max = xpoints[i]; - width = bufs[i]->width; - } - if ((y_max + height) < (ypoints[i] + bufs[i]->height)) - { - y_max = ypoints[i]; - height = bufs[i]->height; - } - } - - - width = x_max - x_min + width; - height = y_max - y_min + height; - - /*printf("Xmin %d, Ymin %d, Width %d, Height %d\n", x_min, y_min, width, height); - printf("\n");*/ - - - brush_mask = mask_buf_new(width, height); - - - dest = brush_mask->data; - - for (i = 0; i < steps - 1; i++) - { - - - ystart = ypoints[i] - y_min; - xstart = xpoints[i] - x_min; - /*printf("xstart %d, ystart %d\n", xstart, ystart);*/ - - y = width * ystart; - - source = bufs[i]->data; - - for(k = 0; k < bufs[i]->height; k++) - { - for(j = 0; j < bufs[i]->width; j++ ) - { - if(((int)dest[y + k * width + xstart + j] + (int)source[k * bufs[i]->width + j]) > 255) - { - dest[y + k * width + xstart + j] = 255; - } - else - { - dest[y + k * width + xstart + j] += source[k * bufs[i]->width + j]; - } - } - } - } - - /*printf("\n\n");*/ - - for (i = steps - 2; i >= 0; i--) - { - mask_buf_free(bufs[i]); - } - - g_free(bufs); - xinput_airbrush_paste (xinput_airbrush_tool, drawable, brush_mask, x_min, y_min, width, height); - mask_buf_free(brush_mask); - - } - else - { - /* - printf("Hmm something was FALSE\n"); - */ - } - -} - - - -/************************************************** -*************************************************** -*/ - - -static void -make_mask (AirLine *airline, - MaskBuf *dest, - guint value) -{ - - int steps; - int total_steps; - int i; - int j; - - - int dx, dy; - int x, y; - - int x0, x1, y0, y1; - - - unsigned char *s; - guint midvalue; - double ivalue; - - int rowlength; - int slopeterm; - - gboolean nothing; - - - rowlength = dest->width * dest->bytes; - - - nothing = TRUE; - - - total_steps=0; - - for (i=0; i < airline->nlines ; i++) - { - - steps = number_of_steps(airline->xcenter, airline->ycenter, - airline->line[i].x, airline->line[i].y); - total_steps += steps; - } - - /* - printf("Total Steps: %d\n", total_steps); - */ - - for (i=0; i < airline->nlines ; i++) - { - - steps = number_of_steps(airline->xcenter, airline->ycenter, - airline->line[i].x, airline->line[i].y); - - x0 = airline->xcenter - airline->min_x ; - x1 = airline->line[i].x - airline->min_x ; - - y0 = airline->ycenter - airline->min_y ; - y1 = airline->line[i].y -airline->min_y ; - - - dx = abs(x0 - x1); - dy = abs(y0 - y1); - - - - /* - Yes I know this is bulky code :-), - you could insted set the x direction - to 1 or -1, and y to - or + rowside. - Then set the first X and Y and of you - go. - - But I wanted to keep it simple while I - implemented the tool :-). I will make it - more effective later on. And yes I could - look for the three special cases. - */ - - - midvalue = value; - - - if (dy > dx) - { - /* Step in the y direction*/ - if (y0 < y1) - { - /* - Step from y0 to y1 - */ - if(x1 < x0) - { - /* - We have to x-- - */ - - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - - slopeterm = dx; - - j = 1; - - while(y < y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x--; - y++; - } - else - { - slopeterm += dx; - y++; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - - nothing = FALSE; - } - - } - else - { - /* - We have to x++ - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - slopeterm = dx; - - j = 1; - - while(y < y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x++; - y++; - } - else - { - slopeterm += dx; - y++; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - nothing = FALSE; - } - } - } - else - { - /* Step from y0 to y1 with neg steps */ - if(x1 < x0) - { - /* - We have to x-- - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - - slopeterm = dx; - - j = 1; - - while(y > y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x--; - y--; - } - else - { - slopeterm += dx; - y--; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - nothing = FALSE; - - } - } - else - { - /* - We have to x++ - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - - slopeterm = dx; - - j = 1; - - while(y > y1) - { - if (slopeterm > dy) - { - slopeterm -= dy; - x++; - y--; - } - else - { - slopeterm += dx; - y--; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - - nothing = FALSE; - } - } - } - - } - else - { - /* Step in the X direction*/ - if (x0 < x1) - { - /* Step from x0 to x1 */ - if(y1 < y0) - { - /* - We have to y-- - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - slopeterm = dy; - - j = 1; - - while(x < x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y--; - x++; - } - else - { - slopeterm += dy; - x++; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - nothing = FALSE; - } - - } - else - { - /* - We have to y++ - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - - - slopeterm = dy; - - j = 1; - - while(x < x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y++; - x++; - } - else - { - slopeterm += dy; - x++; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - - nothing = FALSE; - } - } - } - else - { - /* Step from x0 to x1 neg direction */ - if(y1 < y0) - { - /* - We have to y-- - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - - - slopeterm = dy; - - j = 1; - - while(x > x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y--; - x--; - } - else - { - slopeterm += dy; - x--; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - - nothing = FALSE; - } - } - else - { - /* - We have to y++ - */ - s = dest->data; - - x = x0; - y = y0; - - s += y * rowlength + x; - - - if (((int)*s + (int)midvalue) > 255) - { - *s = 255; - } - else - { - *s = midvalue + *s; - } - slopeterm = dy; - - j = 1; - - while(x > x1) - { - if (slopeterm > dx) - { - slopeterm -= dx; - y++; - x--; - } - else - { - slopeterm += dy; - x--; - } - - j++; - - s = dest->data; - s += y * rowlength + x; - - ivalue = value * (1.0 - (double)j/(double)steps); - - if(((int)*s + ivalue) > 255) - { - *s = 255; - } - else - { - *s = *s + ivalue; - } - - nothing = FALSE; - } - - } - } - } - } - - if (nothing) - { - printf("Hmm I retured a nothing brush\n"); - } - -} - - - - -static void -xinput_airbrush_set_paint_area (XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - int x, int y, int width, int height) -{ - int iwidth, iheight; - int x1, y1, x2, y2; - int bytes; - int dwidth, dheight; - - bytes = drawable_has_alpha (drawable) ? - drawable_bytes (drawable) : drawable_bytes (drawable) + 1; - - dwidth = drawable_width (drawable); - dheight = drawable_height (drawable); - - - x1 = CLAMP (x, 0, dwidth); - y1 = CLAMP (y, 0, dheight); - x2 = CLAMP ((x + width), 0, dwidth); - y2 = CLAMP ((y + height), 0, dheight); - - iwidth = MIN((x2 - x1), width); - iheight = MIN((y2 - y1), height); - - - - /* configure the canvas buffer */ - - if ((x2 - x1) && (y2 - y1)) - canvas_buf = temp_buf_resize (canvas_buf, bytes, x1, y1, - iwidth, iheight); - - - - -} - - -static void -render_airbrush_line (AirBrushBlob *airbrush_blob, guchar *dest, - int y, int width, XinputAirbrushTool *xinput_airbrush_tool) -{ - int i, j, k, l, m, g; - - int left, right; - - int brush_width; - - double x_dest; - double xdist, ydist, dist, angle; - double i_value; - guchar value; - - - - if (airbrush_blob->height <= 6) - { - return; - } - left = 0; - right = 0; - - j = y * SUBSAMPLE; - g = y * SUBSAMPLE; - - for (i=0; i= airbrush_blob->height) - { - if ( i == 0) - { - return; - } - else - { - left = airbrush_blob->data[g].left - airbrush_blob->min_x; - right = airbrush_blob->data[g].right - airbrush_blob->min_x; - break; - } - } - if ( i == SUBSAMPLE/2) - { - left = airbrush_blob->data[j].left - airbrush_blob->min_x; - right = airbrush_blob->data[j].right - airbrush_blob->min_x; - break; - } - - } - - brush_width = right - left; - - if (brush_width <= SUBSAMPLE*2) - { - return; - } - - dest = dest + (left/SUBSAMPLE); - - for (i=4; i <= brush_width; i = i + SUBSAMPLE) - { - x_dest = (left + i)/SUBSAMPLE; - xdist = (airbrush_blob->min_x/SUBSAMPLE) + x_dest - xinput_airbrush_tool->xcenter; - ydist = xinput_airbrush_tool->ycenter - (airbrush_blob->y/SUBSAMPLE) - y; - angle = atan2(ydist, xdist) + G_PI; - dist = hypot(xdist, ydist); - for (j=1; j< (airbrush_blob->height - 1) ; j++) - { - k = j - 1; - l = j + 1; - m = 0; - if ( (fabs(airbrush_blob->data[k].angle_right_abs - airbrush_blob->data[l].angle_right_abs) > - fabs(airbrush_blob->data[k].angle_right_abs - angle)) && - (fabs(airbrush_blob->data[k].angle_right_abs - airbrush_blob->data[l].angle_right_abs) > - fabs(airbrush_blob->data[l].angle_right_abs - angle)) - ) - { - i_value = MIN(1., (dist*SUBSAMPLE)/(airbrush_blob->data[j].dist_right)); - value = 255 * (1 - i_value); - *dest = value; - dest++; - m = 1; - break; - } - - else if ( (fabs(airbrush_blob->data[k].angle_left_abs - airbrush_blob->data[l].angle_left_abs) > - fabs(airbrush_blob->data[k].angle_left_abs - angle)) && - (fabs(airbrush_blob->data[k].angle_left_abs - airbrush_blob->data[l].angle_left_abs) > - fabs(airbrush_blob->data[l].angle_left_abs - angle)) - ) - { - i_value = MIN(1., (dist*SUBSAMPLE)/(airbrush_blob->data[j].dist_left)); - value = 255 * (1 - i_value); - *dest = value; - dest++; - m = 1; - break; - } - else if ((j == (airbrush_blob->height - 2)) && ( m == 0)) - { - *dest = 0; - dest++; - } - } - } - - -} - - - -static void -calc_width (AirBrushBlob *airbrush_blob) -{ - int i; - int min_x, max_x; - - i = (airbrush_blob->height)/2; - - min_x = airbrush_blob->data[i].left; - max_x = airbrush_blob->data[i].right; - - for (i=0; i< (airbrush_blob->height) ; i++) - - { - - if ( airbrush_blob->data[i].left <= airbrush_blob->data[i].right) - { - min_x = MIN(airbrush_blob->data[i].left, min_x); - } - - - if ( airbrush_blob->data[i].left <= airbrush_blob->data[i].right) - { - max_x = MAX(airbrush_blob->data[i].right, max_x ); - } - } - - airbrush_blob->width = max_x - min_x; - airbrush_blob->min_x = min_x; - airbrush_blob->max_x = max_x; -} - - -static void -calc_angle (AirBrushBlob *airbrush_blob, double xcenter, double ycenter) -{ - - - int i; - double y_center, x_center; - - double y_dist, x_dist; - double left_ang, right_ang; - double left_ang_abs, right_ang_abs; - int min_x, max_x; - - - - x_center = xcenter * SUBSAMPLE; - y_center = ycenter * SUBSAMPLE - airbrush_blob->y; - - i = (airbrush_blob->height)/2; - - min_x = airbrush_blob->data[i].left; - max_x = airbrush_blob->data[i].right; - - for (i=0; i< (airbrush_blob->height) ; i++) - - { - - y_dist = y_center - i; - x_dist = airbrush_blob->data[i].left - x_center; - left_ang_abs = atan2(y_dist, x_dist) + G_PI; - left_ang = atan(y_dist/x_dist); - airbrush_blob->data[i].angle_left = left_ang; - airbrush_blob->data[i].angle_left_abs = left_ang_abs; - airbrush_blob->data[i].dist_left = hypot(x_dist, y_dist); - if ( airbrush_blob->data[i].left <= airbrush_blob->data[i].right) - { - min_x = MIN(airbrush_blob->data[i].left, min_x); - } - - x_dist = airbrush_blob->data[i].right - x_center; - right_ang_abs = atan2(y_dist, x_dist) + G_PI; - right_ang = atan(y_dist/x_dist); - airbrush_blob->data[i].angle_right = right_ang; - airbrush_blob->data[i].angle_right_abs = right_ang_abs; - airbrush_blob->data[i].dist_right = hypot(x_dist, y_dist); - if ( airbrush_blob->data[i].left <= airbrush_blob->data[i].right) - { - max_x = MAX(airbrush_blob->data[i].right, max_x ); - } - - - - } - - airbrush_blob->width = max_x - min_x; - airbrush_blob->min_x = min_x; - airbrush_blob->max_x = max_x; - - -} - - - -static void -make_single_mask(AirBrushBlob *airbrush_blob, XinputAirbrushTool *xinput_airbrush_tool, MaskBuf *dest) -{ - unsigned char * s; - int h; - int i; - - h = dest->height; - s = dest->data; - - for (i=0; iwidth, xinput_airbrush_tool); - s += (dest->width * dest->bytes); - } - -} - -static void -print_line (guchar *dest, - int width) -{ - - int i; - - for (i=0; i < width; i++) - { - printf("%d ", *dest); - dest++; - } -} - -static void -print_mask(MaskBuf *dest) -{ - unsigned char * s; - int h; - int i; - - h = dest->height; - s = dest->data; - printf("\nBrush_Mask\n\n"); - for (i=0; iwidth); - s += (dest->width * dest->bytes); - printf("\n"); - } - printf("\n"); -} - -static inline MaskBuf * -blur_mask_1(MaskBuf *mask) -{ - MaskBuf *retur; - int y, x; - unsigned char *source; - unsigned char *dest; - int height, width; - - retur = mask_buf_new(mask->width, mask->height); - - source = mask->data; - dest = retur->data; - - width = mask->width; - height = mask->height; - - for (y = 1; y < (height -1); y++) - { - for(x = 1; x < (width -1); x++) - { - - dest[(y * retur->width + x)] = ( - 2 * source[((y-1) * width) + x - 1] + - 2 * source[((y-1) * width) + x] + - 2 * source[((y-1) * width) + x + 1] + - 2 * source[(y * width) + x - 1] + - source[(y * width) + x] + - 2 * source[(y * width) + x + 1] + - 2 * source[((y+1) * width) + x - 1] + - 2 * source[((y+1) * width) + x] + - source[((y+1) * width) + x + 1])/16; - } - } - - mask_buf_free(mask); - return retur; -} - - -static inline MaskBuf * -blur_mask_2(MaskBuf *mask) -{ - MaskBuf *retur; - int y, x; - unsigned char *source; - unsigned char *dest; - int height, width; - - retur = mask_buf_new(mask->width, mask->height); - - source = mask->data; - dest = retur->data; - - width = mask->width; - height = mask->height; - - for (y = 2; y < (height -2); y++) - { - for(x = 2; x < (width -2); x++) - { - - dest[(y * retur->width + x)] = ( - - - - 2 * source[((y-2) * width) + x - 2] + - 2 * source[((y-2) * width) + x - 1] + - 2 * source[((y-2) * width) + x] + - 2 * source[((y-2) * width) + x + 1] + - 2 * source[((y-2) * width) + x + 2] + - - 2 * source[((y-1) * width) + x - 2] + - 4 * source[((y-1) * width) + x - 1] + - 4 * source[((y-1) * width) + x] + - 4 * source[((y-1) * width) + x + 1] + - 2 * source[((y-1) * width) + x + 2] + - - 2 * source[(y * width) + x - 2] + - 4 * source[(y * width) + x - 1] + - 1 * source[(y * width) + x] + - 4 * source[(y * width) + x + 1] + - 1 * source[(y * width) + x + 2] + - - 2 * source[((y+1) * width) + x - 2] + - 4 * source[((y+1) * width) + x - 1] + - 4 * source[((y+1) * width) + x] + - 4 * source[((y+1) * width) + x + 1] + - 2 * source[((y+1) * width) + x + 2] + - - 2 * source[((y+2) * width) + x - 2] + - 2 * source[((y+2) * width) + x - 1] + - 2 * source[((y+2) * width) + x] + - 2 * source[((y+2) * width) + x + 1] + - 2 * source[((y+2) * width) + x + 2] - - )/64; - - } - } - - mask_buf_free(mask); - return retur; - } - - - -static inline MaskBuf * -blur_mask_3(MaskBuf *mask) -{ - MaskBuf *retur; - int y, x, y_3, y_2, y_1, y1, y2, y3, x_3, x_2,x_1, x1, x2, x3; - unsigned char *source; - unsigned char *dest; - int height, width, max_height, max_width; - - retur = mask_buf_new(mask->width, mask->height); - - source = mask->data; - dest = retur->data; - - width = mask->width; - height = mask->height; - - max_height = width * height - 3 * width; - max_width = width - 3; - - - y_3 = 0; - y_2 = width; - y_1 = 2 * width; - y = 3 * width; - y1 = 4 * width; - y2 = 5 * width; - y3 = 6 * width; - - - for (; y < max_height; y_3 += width, y_2 += width, y_1 += width, y += width, y1 += width, y2 += width, y3 += width) - { - for( x_3 = 0, x_2 = 1, x_1 = 2, x = 3, x1 = 4, x2 = 5 , x3 = 6; x < max_width; x_3++, x_2++, x_1++, x++, x1++, x2++, x3++) - { - - dest[y + x] = ( - - 1 * source[y_3 + x_3] + - 1 * source[y_3 + x_2] + - 1 * source[y_3 + x_1] + - 1 * source[y_3 + x] + - 1 * source[y_3 + x1] + - 1 * source[y_3 + x2] + - 1 * source[y_3 + x3] + - - 2 * source[y_2 + x_3] + - 2 * source[y_2 + x_2] + - 2 * source[y_2 + x_1] + - 2 * source[y_2 + x] + - 2 * source[y_2 + x1] + - 2 * source[y_2 + x2] + - 2 * source[y_2 + x3] + - - 2 * source[y_1 + x_3] + - 2 * source[y_1 + x_2] + - 8 * source[y_1 + x_1] + - 8 * source[y_1 + x] + - 8 * source[y_1 + x1] + - 2 * source[y_1 + x2] + - 2 * source[y_1 + x3] + - - 1 * source[y + x_3] + - 2 * source[y + x_2] + - 8 * source[y + x_1] + - 1 * source[y + x] + - 8 * source[y + x1] + - 2 * source[y + x2] + - 1 * source[y + x3] + - - 2 * source[y1 + x_3] + - 2 * source[y1 + x_2] + - 8 * source[y1 + x_1] + - 8 * source[y1 + x] + - 8 * source[y1 + x1] + - 2 * source[y1 + x2] + - 2 * source[y1 + x3] + - - 2 * source[y2 + x_3] + - 2 * source[y2 + x_2] + - 2 * source[y2 + x_1] + - 1 * source[y2 + x] + - 2 * source[y2 + x1] + - 2 * source[y2 + x2] + - 2 * source[y2 + x3] + - - 1 * source[y3 + x_3] + - 1 * source[y3 + x_2] + - 1 * source[y3 + x_1] + - 1 * source[y3 + x] + - 1 * source[y3 + x1] + - 1 * source[y3 + x2] + - 1 * source[y3 + x3] - - )/128; - - } - } - - mask_buf_free(mask); - return retur; -} - - -MaskBuf * -blur_mask_4(MaskBuf *mask) -{ - MaskBuf *retur; - int y, x, x_4, x_3, x_2,x_1, x1, x2, x3, x4,x5; - unsigned char *source; - unsigned char *dest; - int height, width, max_height, max_width; - - retur = mask_buf_new(mask->width, mask->height); - - source = mask->data; - dest = retur->data; - - width = mask->width; - height = mask->height; - - max_height = width * height - 3 * width; - max_width = width - 5; - - - y = width; - - - for (y=0 ; y < max_height; y += width) - { - for( x_4 = 0, x_3 = 1, x_2 = 2, x_1 = 3, x = 4, x1 = 5, x2 = 6 , x3 = 7, x4 = 8, x5 = 9; x < max_width; x_3++, x_2++, x_1++, x++, x1++, x2++, x3++) - { - - dest[y + x] = ( - - 4 * source[y + x_4] + - 4 * source[y + x_3] + - 8 * source[y + x_2] + - 16 * source[y + x_1] + - 1 * source[y + x] + - 16 * source[y + x1] + - 8 * source[y + x2] + - 4 * source[y + x3] + - 2 * source[y + x4] + - 1 * source[y + x5] - - - )/64; - - } - } - - mask_buf_free(mask); - return retur; -} - -static void -xinput_airbrush_paste (XinputAirbrushTool *xinput_airbrush_tool, - GimpDrawable *drawable, - MaskBuf *brush_mask_in, - int x, - int y, - int width, - int height) -{ - GImage *gimage; - PixelRegion srcPR; - int offx, offy; - int size; - unsigned char col[MAX_CHANNELS]; - MaskBuf *brush_mask1; - MaskBuf *brush_mask3; - MaskBuf *brush_mask2; - MaskBuf *brush_mask; - int i; - - - if (! (gimage = drawable_gimage (drawable))) - return; - - - size = height * width; - brush_mask1 = mask_buf_new(brush_mask_in->width, brush_mask_in->height); - brush_mask1 = temp_buf_copy(brush_mask_in, brush_mask1); - - /* printf("Size: %d\n", size); */ - - if (size <= 40) - { - brush_mask1 = blur_mask_1(brush_mask1); - } - else if ((size >= 40) && (size <= 90)) - { - - - for(i = 0 ; i < 2; i++) - { - brush_mask2 = blur_mask_1(brush_mask1); - brush_mask3 = blur_mask_1(brush_mask2); - brush_mask1 = blur_mask_1(brush_mask3); - } - } - else if ((size >= 91) && (size <= 1000)) - { - - - for(i = 0 ; i < 2; i++) - { - brush_mask2 = blur_mask_3(brush_mask1); - brush_mask3 = blur_mask_3(brush_mask2); - brush_mask1 = blur_mask_3(brush_mask3); - - } - - } - else if ((size >= 1001) && (size <= 5000)) - { - for(i = 0 ; i < 4; i++) - { - brush_mask2 = blur_mask_4(brush_mask1); - brush_mask3 = blur_mask_4(brush_mask2); - brush_mask1 = blur_mask_3(brush_mask3); - - } - } - - else if (size >= 5001) - { - for(i = 0 ; i < 5; i++) - { - brush_mask2 = blur_mask_3(brush_mask1); - brush_mask3 = blur_mask_4(brush_mask2); - brush_mask1 = blur_mask_3(brush_mask3); - - } - } - - - brush_mask = brush_mask1; - - /* Get the the buffer */ - xinput_airbrush_set_paint_area (xinput_airbrush_tool, drawable, x - 1, y - 1, width, height); - - /* check to make sure there is actually a canvas to draw on */ - if (!canvas_buf) - return; - - gimage_get_foreground (gimage, drawable, col); - - /* set the alpha channel */ - col[canvas_buf->bytes - 1] = OPAQUE_OPACITY; - - /* color the pixels */ - color_pixels (temp_buf_data (canvas_buf), col, - canvas_buf->width * canvas_buf->height, canvas_buf->bytes); - - /* set undo blocks */ - xinput_airbrush_set_undo_tiles (drawable, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - /* initialize any invalid canvas tiles */ - xinput_airbrush_set_canvas_tiles (canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height); - - /*DON'T FORGETT THE 100 VALUE, I.E. THE BRUSH OPACITY WHICH SHOULD BE 255*/ - - xinput_airbrush_to_canvas_tiles (xinput_airbrush_tool, brush_mask, 255); - - xinput_airbrush_canvas_tiles_to_canvas_buf(xinput_airbrush_tool); - - - /* initialize canvas buf source pixel regions */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - - /* apply the paint area to the gimage */ - gimage_apply_image (gimage, drawable, &srcPR, - FALSE, - (int) (gimp_context_get_opacity (NULL) * 255), - gimp_context_get_paint_mode (NULL), - undo_tiles, /* specify an alternative src1 */ - canvas_buf->x, canvas_buf->y); - - /* Update the undo extents */ - xinput_airbrush_tool->x1 = MIN (xinput_airbrush_tool->x1, canvas_buf->x); - xinput_airbrush_tool->y1 = MIN (xinput_airbrush_tool->y1, canvas_buf->y); - xinput_airbrush_tool->x2 = MAX (xinput_airbrush_tool->x2, (canvas_buf->x + canvas_buf->width)); - xinput_airbrush_tool->y2 = MAX (xinput_airbrush_tool->y2, (canvas_buf->y + canvas_buf->height)); - - /* Update the gimage--it is important to call gdisplays_update_area - * instead of drawable_update because we don't want the drawable - * preview to be constantly invalidated - */ - drawable_offsets (drawable, &offx, &offy); - gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, - canvas_buf->width, canvas_buf->height); - - mask_buf_free(brush_mask); - -} - - - -static void -xinput_airbrush_to_canvas_tiles (XinputAirbrushTool *xinput_airbrush_tool, - MaskBuf *brush_mask, - int brush_opacity) -{ - PixelRegion srcPR, maskPR; - - /* combine the brush mask and the canvas tiles */ - pixel_region_init (&srcPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, TRUE); - - maskPR.bytes = 1; - maskPR.x = 0; - maskPR.y = 0; - maskPR.w = srcPR.w; - maskPR.h = srcPR.h; - maskPR.rowstride = maskPR.bytes * brush_mask->width; - maskPR.data = mask_buf_data (brush_mask); - - /* combine the mask to the canvas tiles */ - combine_mask_and_region (&srcPR, &maskPR, brush_opacity); -} - - - - -static void -xinput_airbrush_canvas_tiles_to_canvas_buf(XinputAirbrushTool *xinput_airbrush_tool) -{ - PixelRegion srcPR, maskPR; - - /* combine the canvas tiles and the canvas buf */ - srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; - srcPR.y = 0; - srcPR.w = canvas_buf->width; - srcPR.h = canvas_buf->height; - srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; - srcPR.data = temp_buf_data (canvas_buf); - - pixel_region_init (&maskPR, canvas_tiles, - canvas_buf->x, canvas_buf->y, - canvas_buf->width, canvas_buf->height, FALSE); - - /* apply the canvas tiles to the canvas buf */ - apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); -} - - - -static void -xinput_airbrush_set_undo_tiles (GimpDrawable *drawable, - int x, int y, int w, int h) -{ - int i, j; - Tile *src_tile; - Tile *dest_tile; - - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - { - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - dest_tile = tile_manager_get_tile (undo_tiles, j, i, FALSE, FALSE); - if (tile_is_valid (dest_tile) == FALSE) - { - src_tile = tile_manager_get_tile (drawable_data (drawable), j, i, TRUE, FALSE); - tile_manager_map_tile (undo_tiles, j, i, src_tile); - tile_release (src_tile, FALSE); - } - } - } -} - - -static void -xinput_airbrush_set_canvas_tiles (int x, int y, int w, int h) -{ - int i, j; - Tile *tile; - - for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) - { - for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) - { - tile = tile_manager_get_tile (canvas_tiles, j, i, FALSE, FALSE); - if (tile_is_valid (tile) == FALSE) - { - tile = tile_manager_get_tile (canvas_tiles, j, i, TRUE, TRUE); - memset (tile_data_pointer (tile, 0, 0), - 0, - tile_size (tile)); - tile_release (tile, TRUE); - } - } - } -} - -/**************************/ -/* Global xinput_airbrush functions */ -/**************************/ - -void -xinput_airbrush_no_draw (Tool *tool) -{ - return; -} - -Tool * -tools_new_xinput_airbrush (void) -{ - Tool * tool; - XinputAirbrushTool * private; - - /* The tool options */ - if (! xinput_airbrush_options) - { - xinput_airbrush_options = xinput_airbrush_options_new (); - tools_register (XINPUT_AIRBRUSH, (ToolOptions *) xinput_airbrush_options); - - /* press all default buttons */ - xinput_airbrush_options_reset (); - } - - tool = tools_new_tool (XINPUT_AIRBRUSH); - private = g_new0 (XinputAirbrushTool, 1); - - private->core = draw_core_new (xinput_airbrush_no_draw); - private->last_airbrush_blob = NULL; - - tool->private = private; - - tool->button_press_func = xinput_airbrush_button_press; - tool->button_release_func = xinput_airbrush_button_release; - tool->motion_func = xinput_airbrush_motion; - tool->cursor_update_func = xinput_airbrush_cursor_update; - tool->control_func = xinput_airbrush_control; - - return tool; -} - -void -tools_free_xinput_airbrush(Tool *tool) -{ - XinputAirbrushTool * xinput_airbrush_tool; - - xinput_airbrush_tool = (XinputAirbrushTool *) tool->private; - - /* Make sure the selection core is not visible */ - if (tool->state == ACTIVE && xinput_airbrush_tool->core) - draw_core_stop (xinput_airbrush_tool->core, tool); - - /* Free the selection core */ - if (xinput_airbrush_tool->core) - draw_core_free (xinput_airbrush_tool->core); - - /* Free the last airbrush_blob, if any */ - if (xinput_airbrush_tool->last_airbrush_blob) - g_free (xinput_airbrush_tool->last_airbrush_blob); - - /* Cleanup memory */ - xinput_airbrush_cleanup (); - - /* Free the paint core */ - g_free (xinput_airbrush_tool); -} diff --git a/app/xinput_airbrush.h b/app/xinput_airbrush.h deleted file mode 100644 index db12ac2ff8..0000000000 --- a/app/xinput_airbrush.h +++ /dev/null @@ -1,30 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef __XINPUTAIRBRUSH_H__ -#define __XINPUTAIRBRUSH_H__ - -#include "tools.h" -#include "procedural_db.h" - -Tool * tools_new_xinput_airbrush (void); -void tools_free_xinput_airbrush (Tool *); - -/* Procedure definition and marshalling function */ -extern ProcRecord xinput_airbrush_proc; - -#endif /* __XINPUTAIRBRUSH_H__ */ diff --git a/configure.in b/configure.in index aa1ad4068c..4bfeb3eb90 100644 --- a/configure.in +++ b/configure.in @@ -735,6 +735,7 @@ libgimp/makefile.mingw app/Makefile app/makefile.mingw app/pdb/Makefile +app/tools/Makefile plug-ins/Makefile plug-ins/makefile.mingw plug-ins/perl/config.pl diff --git a/po/POTFILES.in b/po/POTFILES.in index e91001e8ea..b3de554b5e 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,44 +2,28 @@ # marked to allow runtime translation of messages app/about_dialog.c -app/airbrush.c app/app_procs.c -app/bezier_select.c -app/blend.c -app/brightness_contrast.c app/brush_edit.c app/brush_select.c -app/bucket_fill.c -app/by_color_select.c app/channel.c app/channel_ops.c app/channels_dialog.c -app/clone.c app/color_area.c -app/color_balance.c app/color_notebook.c -app/color_picker.c app/color_select.c app/colormap_dialog.c app/commands.c app/convert.c -app/convolve.c -app/crop.c -app/curves.c app/desaturate.c app/devices.c app/disp_callbacks.c app/docindex.c -app/dodgeburn.c app/edit_selection.c app/equalize.c -app/eraser.c app/errorconsole.c app/file_new_dialog.c app/fileops.c -app/flip_tool.c app/floating_sel.c -app/fuzzy_select.c app/gdisplay.c app/gdisplay_ops.c app/gimage_mask.c @@ -56,56 +40,34 @@ app/gimpunit.c app/global_edit.c app/gradient.c app/gradient_select.c -app/histogram_tool.c -app/hue_saturation.c app/image_new.c app/indicator_area.c app/info_dialog.c app/info_window.c -app/ink.c app/interface.c app/invert.c app/layer.c app/layer_select.c app/layers_dialog.c app/lc_dialog.c -app/levels.c -app/magnify.c app/main.c -app/measure.c app/menus.c app/module_db.c -app/move.c app/nav_window.c -app/paint_core.c app/paint_funcs.c -app/paintbrush.c app/palette.c app/palette_import.c app/palette_select.c app/paths_dialog.c app/pattern_select.c app/patterns.c -app/perspective_tool.c app/plug_in.c -app/posterize.c app/preferences_dialog.c app/qmask.c -app/rect_select.c app/resize.c app/resolution_calibrate.c -app/rotate_tool.c -app/scale_tool.c app/scan_convert.c -app/shear_tool.c -app/smudge.c -app/text_tool.c -app/threshold.c app/tips_dialog.c -app/tool_options.c -app/tools.c -app/transform_core.c -app/transform_tool.c app/undo.c app/undo_history.c app/user_install.c @@ -114,6 +76,44 @@ app/pdb/image_cmds.c app/pdb/internal_procs.c app/pdb/procedural_db.c app/pdb/procedural_db_cmds.c +app/tools/airbrush.c +app/tools/bezier_select.c +app/tools/blend.c +app/tools/brightness_contrast.c +app/tools/bucket_fill.c +app/tools/by_color_select.c +app/tools/clone.c +app/tools/color_balance.c +app/tools/color_picker.c +app/tools/convolve.c +app/tools/crop.c +app/tools/curves.c +app/tools/dodgeburn.c +app/tools/eraser.c +app/tools/flip_tool.c +app/tools/fuzzy_select.c +app/tools/histogram_tool.c +app/tools/hue_saturation.c +app/tools/ink.c +app/tools/levels.c +app/tools/magnify.c +app/tools/measure.c +app/tools/move.c +app/tools/paint_core.c +app/tools/paintbrush.c +app/tools/perspective_tool.c +app/tools/posterize.c +app/tools/rect_select.c +app/tools/rotate_tool.c +app/tools/scale_tool.c +app/tools/shear_tool.c +app/tools/smudge.c +app/tools/text_tool.c +app/tools/threshold.c +app/tools/tool_options.c +app/tools/tools.c +app/tools/transform_core.c +app/tools/transform_tool.c modules/colorsel_gtk.c modules/colorsel_triangle.c modules/colorsel_water.c diff --git a/tools/kernelgen.c b/tools/kernelgen.c index e80c7d7797..b1135aceb7 100644 --- a/tools/kernelgen.c +++ b/tools/kernelgen.c @@ -5,7 +5,7 @@ * Simple hack to create subsampling kernels for the brushes * as used in app/paint_core.c. * If you want to play with it, change some of the #defines at the - * top and copy the output to apps/paint_core_kernels.h. + * top and copy the output to apps/tools/paint_core_kernels.h. * * 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 diff --git a/tools/pdbgen/Makefile.am b/tools/pdbgen/Makefile.am index d724037f0c..eb90a96e62 100644 --- a/tools/pdbgen/Makefile.am +++ b/tools/pdbgen/Makefile.am @@ -49,26 +49,26 @@ EXTRA_DIST = \ $(pdb_sources) enum_headers = \ - ../../app/appenums.h \ - ../../app/appenv.h \ - ../../app/apptypes.h \ - ../../app/blend.h \ - ../../app/bucket_fill.h \ - ../../app/channel_ops.h \ - ../../app/clone.h \ - ../../app/color_balance.h \ - ../../app/convert.h \ - ../../app/convolve.h \ - ../../app/dodgeburn.h \ - ../../app/errors.h \ - ../../app/gimpimage.h \ - ../../app/hue_saturation.h \ - ../../app/layer.h \ - ../../app/lut_funcs.h \ - ../../app/paint_core.h \ - ../../app/paint_funcs.h \ - ../../app/plug_in.h \ - ../../app/text_tool.h + ../../app/appenums.h \ + ../../app/appenv.h \ + ../../app/apptypes.h \ + ../../app/channel_ops.h \ + ../../app/convert.h \ + ../../app/errors.h \ + ../../app/gimpimage.h \ + ../../app/layer.h \ + ../../app/lut_funcs.h \ + ../../app/paint_funcs.h \ + ../../app/plug_in.h \ + ../../app/tools/blend.h \ + ../../app/tools/bucket_fill.h \ + ../../app/tools/clone.h \ + ../../app/tools/color_balance.h \ + ../../app/tools/convolve.h \ + ../../app/tools/dodgeburn.h \ + ../../app/tools/hue_saturation.h \ + ../../app/tools/paint_core.h \ + ../../app/tools/text_tool.h pdb_scripts = \ pdbgen.pl \ diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl index 74806ef7aa..824c194583 100644 --- a/tools/pdbgen/enums.pl +++ b/tools/pdbgen/enums.pl @@ -242,55 +242,6 @@ package Gimp::CodeGen::enums; CONSOLE => '1', ERROR_CONSOLE => '2' } }, - GradientType => - { contig => 1, - header => 'blend.h', - symbols => [ qw(LINEAR BILINEAR RADIAL SQUARE CONICAL_SYMMETRIC - CONICAL_ASYMMETRIC SHAPEBURST_ANGULAR - SHAPEBURST_SPHERICAL SHAPEBURST_DIMPLED - SPIRAL_CLOCKWISE SPIRAL_ANTICLOCKWISE) ], - mapping => { LINEAR => '0', - BILINEAR => '1', - RADIAL => '2', - SQUARE => '3', - CONICAL_SYMMETRIC => '4', - CONICAL_ASYMMETRIC => '5', - SHAPEBURST_ANGULAR => '6', - SHAPEBURST_SPHERICAL => '7', - SHAPEBURST_DIMPLED => '8', - SPIRAL_CLOCKWISE => '9', - SPIRAL_ANTICLOCKWISE => '10' } - }, - BlendMode => - { contig => 1, - header => 'blend.h', - symbols => [ qw(FG_BG_RGB_MODE FG_BG_HSV_MODE FG_TRANS_MODE - CUSTOM_MODE) ], - mapping => { FG_BG_RGB_MODE => '0', - FG_BG_HSV_MODE => '1', - FG_TRANS_MODE => '2', - CUSTOM_MODE => '3' }, - nicks => { FG_BG_RGB_MODE => 'FG_BG_RGB', - FG_BG_HSV_MODE => 'FG_BG_HSV', - FG_TRANS_MODE => 'FG_TRANS', - CUSTOM_MODE => 'CUSTOM' } - }, - RepeatMode => - { contig => 1, - header => 'blend.h', - symbols => [ qw(REPEAT_NONE REPEAT_SAWTOOTH REPEAT_TRIANGULAR) ], - mapping => { REPEAT_NONE => '0', - REPEAT_SAWTOOTH => '1', - REPEAT_TRIANGULAR => '2' } - }, - BucketFillMode => - { contig => 1, - header => 'bucket_fill.h', - symbols => [ qw(FG_BUCKET_FILL BG_BUCKET_FILL PATTERN_BUCKET_FILL) ], - mapping => { FG_BUCKET_FILL => '0', - BG_BUCKET_FILL => '1', - PATTERN_BUCKET_FILL => '2' } - }, ChannelOffsetType => { contig => 1, header => 'channel_ops.h', @@ -298,21 +249,6 @@ package Gimp::CodeGen::enums; mapping => { OFFSET_BACKGROUND => '0', OFFSET_TRANSPARENT => '1' } }, - CloneType => - { contig => 1, - header => 'clone.h', - symbols => [ qw(IMAGE_CLONE PATTERN_CLONE) ], - mapping => { IMAGE_CLONE => '0', - PATTERN_CLONE => '1' } - }, - TransferMode => - { contig => 1, - header => 'color_balance.h', - symbols => [ qw(SHADOWS MIDTONES HIGHLIGHTS) ], - mapping => { SHADOWS => '0', - MIDTONES => '1', - HIGHLIGHTS => '2' } - }, ConvertPaletteType => { contig => 1, header => 'convert.h', @@ -335,30 +271,6 @@ package Gimp::CodeGen::enums; FIXED_DITHER => '3', NODESTRUCT_DITHER => '4' } }, - ConvolveType => - { contig => 1, - header => 'convolve.h', - symbols => [ qw(BLUR_CONVOLVE SHARPEN_CONVOLVE CUSTOM_CONVOLVE) ], - mapping => { BLUR_CONVOLVE => '0', - SHARPEN_CONVOLVE => '1', - CUSTOM_CONVOLVE => '2' } - }, - DodgeBurnType => - { contig => 1, - header => 'dodgeburn.h', - symbols => [ qw(DODGE BURN) ], - mapping => { DODGE => '0', - BURN => '1' } - }, - DodgeBurnMode => - { contig => 1, - header => 'dodgeburn.h', - symbols => [ qw(DODGEBURN_HIGHLIGHTS DODGEBURN_MIDTONES - DODGEBURN_SHADOWS) ], - mapping => { DODGEBURN_HIGHLIGHTS => '0', - DODGEBURN_MIDTONES => '1', - DODGEBURN_SHADOWS => '2' } - }, StackTraceMode => { contig => 1, header => 'errors.h', @@ -390,19 +302,6 @@ package Gimp::CodeGen::enums; CLIP_TO_BOTTOM_LAYER => '2', FLATTEN_IMAGE => '3' } }, - HueRange => - { contig => 1, - header => 'hue_saturation.h', - symbols => [ qw(ALL_HUES RED_HUES YELLOW_HUES GREEN_HUES CYAN_HUES - BLUE_HUES MAGENTA_HUES) ], - mapping => { ALL_HUES => '0', - RED_HUES => '1', - YELLOW_HUES => '2', - GREEN_HUES => '3', - CYAN_HUES => '4', - BLUE_HUES => '5', - MAGENTA_HUES => '6' } - }, ChannelLutType => { contig => 1, header => 'lut_funcs.h', @@ -422,9 +321,110 @@ package Gimp::CodeGen::enums; RUN_NONINTERACTIVE => '1', RUN_WITH_LAST_VALS => '2' } }, + GradientType => + { contig => 1, + header => 'tools/blend.h', + symbols => [ qw(LINEAR BILINEAR RADIAL SQUARE CONICAL_SYMMETRIC + CONICAL_ASYMMETRIC SHAPEBURST_ANGULAR + SHAPEBURST_SPHERICAL SHAPEBURST_DIMPLED + SPIRAL_CLOCKWISE SPIRAL_ANTICLOCKWISE) ], + mapping => { LINEAR => '0', + BILINEAR => '1', + RADIAL => '2', + SQUARE => '3', + CONICAL_SYMMETRIC => '4', + CONICAL_ASYMMETRIC => '5', + SHAPEBURST_ANGULAR => '6', + SHAPEBURST_SPHERICAL => '7', + SHAPEBURST_DIMPLED => '8', + SPIRAL_CLOCKWISE => '9', + SPIRAL_ANTICLOCKWISE => '10' } + }, + BlendMode => + { contig => 1, + header => 'tools/blend.h', + symbols => [ qw(FG_BG_RGB_MODE FG_BG_HSV_MODE FG_TRANS_MODE + CUSTOM_MODE) ], + mapping => { FG_BG_RGB_MODE => '0', + FG_BG_HSV_MODE => '1', + FG_TRANS_MODE => '2', + CUSTOM_MODE => '3' }, + nicks => { FG_BG_RGB_MODE => 'FG_BG_RGB', + FG_BG_HSV_MODE => 'FG_BG_HSV', + FG_TRANS_MODE => 'FG_TRANS', + CUSTOM_MODE => 'CUSTOM' } + }, + RepeatMode => + { contig => 1, + header => 'tools/blend.h', + symbols => [ qw(REPEAT_NONE REPEAT_SAWTOOTH REPEAT_TRIANGULAR) ], + mapping => { REPEAT_NONE => '0', + REPEAT_SAWTOOTH => '1', + REPEAT_TRIANGULAR => '2' } + }, + BucketFillMode => + { contig => 1, + header => 'tools/bucket_fill.h', + symbols => [ qw(FG_BUCKET_FILL BG_BUCKET_FILL PATTERN_BUCKET_FILL) ], + mapping => { FG_BUCKET_FILL => '0', + BG_BUCKET_FILL => '1', + PATTERN_BUCKET_FILL => '2' } + }, + CloneType => + { contig => 1, + header => 'tools/clone.h', + symbols => [ qw(IMAGE_CLONE PATTERN_CLONE) ], + mapping => { IMAGE_CLONE => '0', + PATTERN_CLONE => '1' } + }, + TransferMode => + { contig => 1, + header => 'tools/color_balance.h', + symbols => [ qw(SHADOWS MIDTONES HIGHLIGHTS) ], + mapping => { SHADOWS => '0', + MIDTONES => '1', + HIGHLIGHTS => '2' } + }, + ConvolveType => + { contig => 1, + header => 'tools/convolve.h', + symbols => [ qw(BLUR_CONVOLVE SHARPEN_CONVOLVE CUSTOM_CONVOLVE) ], + mapping => { BLUR_CONVOLVE => '0', + SHARPEN_CONVOLVE => '1', + CUSTOM_CONVOLVE => '2' } + }, + DodgeBurnType => + { contig => 1, + header => 'tools/dodgeburn.h', + symbols => [ qw(DODGE BURN) ], + mapping => { DODGE => '0', + BURN => '1' } + }, + DodgeBurnMode => + { contig => 1, + header => 'tools/dodgeburn.h', + symbols => [ qw(DODGEBURN_HIGHLIGHTS DODGEBURN_MIDTONES + DODGEBURN_SHADOWS) ], + mapping => { DODGEBURN_HIGHLIGHTS => '0', + DODGEBURN_MIDTONES => '1', + DODGEBURN_SHADOWS => '2' } + }, + HueRange => + { contig => 1, + header => 'tools/hue_saturation.h', + symbols => [ qw(ALL_HUES RED_HUES YELLOW_HUES GREEN_HUES CYAN_HUES + BLUE_HUES MAGENTA_HUES) ], + mapping => { ALL_HUES => '0', + RED_HUES => '1', + YELLOW_HUES => '2', + GREEN_HUES => '3', + CYAN_HUES => '4', + BLUE_HUES => '5', + MAGENTA_HUES => '6' } + }, SizeType => { contig => 1, - header => 'text_tool.h', + header => 'tools/text_tool.h', symbols => [ qw(PIXELS POINTS) ], mapping => { PIXELS => '0', POINTS => '1' } diff --git a/tools/pdbgen/pdb/color.pdb b/tools/pdbgen/pdb/color.pdb index e43b4a8715..8f478de05c 100644 --- a/tools/pdbgen/pdb/color.pdb +++ b/tools/pdbgen/pdb/color.pdb @@ -336,7 +336,7 @@ HELP ); %invoke = ( - headers => [ qw("curves.h") ], + headers => [ qw("tools/curves.h") ], vars => [ 'CurvesDialog cd', 'int x1, y1, x2, y2', 'int i, j', 'PixelRegion srcPR, destPR' ], code => <<'CODE' @@ -418,7 +418,7 @@ HELP ); %invoke = ( - headers => [ qw("curves.h") ], + headers => [ qw("tools/curves.h") ], vars => [ 'CurvesDialog cd', 'int x1, y1, x2, y2', 'int i, j', 'PixelRegion srcPR, destPR' ], code => <<'CODE' @@ -494,7 +494,7 @@ HELP } %invoke = ( - headers => [ qw("color_balance.h") ], + headers => [ qw("tools/color_balance.h") ], vars => [ 'ColorBalanceDialog cbd', 'int i', 'void *pr', 'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2' ], code => <<'CODE' @@ -588,7 +588,7 @@ HELP } %invoke = ( - headers => [ qw("histogram_tool.h" "gimpimage.h") ], + headers => [ qw("tools/histogram_tool.h" "gimpimage.h") ], vars => [ 'PixelRegion srcPR, maskPR', 'int x1, y1, x2, y2', 'HistogramToolDialog htd', 'int off_x, off_y', 'gboolean no_mask', 'Channel *mask' ], @@ -667,7 +667,7 @@ HELP } %invoke = ( - headers => [ qw("hue_saturation.h") ], + headers => [ qw("tools/hue_saturation.h") ], vars => [ 'HueSaturationDialog hsd', 'int i', 'void *pr', 'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2' ], code => <<'CODE' @@ -729,7 +729,7 @@ HELP } %invoke = ( - headers => [ qw("threshold.h") ], + headers => [ qw("tools/threshold.h") ], vars => [ 'ThresholdDialog td', 'int x1, y1, x2, y2', 'PixelRegion srcPR, destPR' ], code => <<'CODE' diff --git a/tools/pdbgen/pdb/misc_tools.pdb b/tools/pdbgen/pdb/misc_tools.pdb index 8e63f3c3e9..63846a0932 100644 --- a/tools/pdbgen/pdb/misc_tools.pdb +++ b/tools/pdbgen/pdb/misc_tools.pdb @@ -93,7 +93,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -121,7 +121,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -178,7 +178,7 @@ HELP ); %invoke = ( - headers => [ qw("blend.h") ], + headers => [ qw("tools/blend.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -237,7 +237,7 @@ HELP } %invoke = ( - headers => [ qw ("bucket_fill.h") ], + headers => [ qw ("tools/bucket_fill.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -283,7 +283,7 @@ HELP ); %invoke = ( - headers => [ qw("by_color_select.h") ], + headers => [ qw("tools/by_color_select.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -329,7 +329,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, strokes); @@ -359,7 +359,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui_default (drawable, num_strokes, strokes); CODE @@ -411,7 +411,7 @@ HELP ); %invoke = ( - headers => [ qw("color_picker.h") ], + headers => [ qw("tools/color_picker.h") ], code => <<'CODE' { if (!sample_merged) @@ -454,7 +454,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui_default (drawable, num_strokes, strokes); CODE @@ -484,7 +484,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui (drawable, pressure, convolve_type, num_strokes, strokes); CODE @@ -517,7 +517,7 @@ HELP ); %invoke = ( - headers => [ qw("crop.h") ], + headers => [ qw("tools/crop.h") ], code => <<'CODE' { if (new_width > gimage->width || new_height > gimage->height || @@ -564,7 +564,7 @@ HELP ); %invoke = ( - headers => [ qw("ellipse_select.h") ], + headers => [ qw("tools/ellipse_select.h") ], code => <<'CODE' ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, antialias, feather, feather_radius); @@ -591,7 +591,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui_default (drawable, num_strokes, strokes); CODE @@ -621,7 +621,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -651,7 +651,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -686,7 +686,8 @@ HELP @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( - headers => [ qw("flip_tool.h" "transform_core.h" "undo.h") ], + headers => [ qw("tools/flip_tool.h" "tools/transform_core.h" + "undo.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer' ], code => <<'CODE' @@ -761,7 +762,7 @@ HELP ); %invoke = ( - headers => [ qw("free_select.h") ], + headers => [ qw("tools/free_select.h") ], code => <<'CODE' free_select (gimage, num_segs, (ScanConvertPoint *) segs, operation, antialias, feather, feather_radius); @@ -811,7 +812,7 @@ HELP ); %invoke = ( - headers => [ qw("fuzzy_select.h") ], + headers => [ qw("tools/fuzzy_select.h") ], vars => [ 'GimpImage *gimage', 'Channel *new, *old_fuzzy_mask' ], code => <<'CODE' { @@ -862,7 +863,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method, gradient_length); @@ -899,7 +900,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -925,7 +926,7 @@ HELP ); %invoke = ( - headers => [ qw("pencil.h") ], + headers => [ qw("tools/pencil.h") ], code => 'success = pencil_non_gui (drawable, num_strokes, strokes);' ); } @@ -976,7 +977,7 @@ HELP @outargs = ( &drawable_out_arg('newly mapped') ); %invoke = ( - headers => [ qw("perspective_tool.h" "transform_core.h" + headers => [ qw("tools/perspective_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1060,7 +1061,7 @@ HELP ); %invoke = ( - headers => [ qw("rect_select.h") ], + headers => [ qw("tools/rect_select.h") ], code => <<'CODE' rect_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, feather, feather_radius); @@ -1097,7 +1098,7 @@ HELP @outargs = ( &drawable_out_arg('rotated') ); %invoke = ( - headers => [ qw("rotate_tool.h" "transform_core.h") ], + headers => [ qw("tools/rotate_tool.h" "tools/transform_core.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', 'GimpMatrix3 matrix' ], @@ -1176,7 +1177,7 @@ HELP @outargs = ( &drawable_out_arg('scaled') ); %invoke = ( - headers => [ qw("scale_tool.h" "transform_core.h" + headers => [ qw("tools/scale_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double scalex, scaley', @@ -1264,7 +1265,7 @@ HELP @outargs = ( &drawable_out_arg('sheared') ); %invoke = ( - headers => [ qw("shear_tool.h" "transform_core.h" + headers => [ qw("tools/shear_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1358,7 +1359,7 @@ HELP @outargs = ( &drawable_out_arg('transformed') ); %invoke = ( - headers => [ qw("transform_core.h" + headers => [ qw("tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'GimpMatrix3 matrix' ], @@ -1419,7 +1420,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -1447,7 +1448,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui_default (drawable, num_strokes, strokes); CODE @@ -1479,7 +1480,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui (drawable, exposure, dodgeburn_type, dodgeburn_mode, num_strokes, strokes); CODE @@ -1506,7 +1507,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui_default (drawable, num_strokes, strokes); CODE diff --git a/tools/pdbgen/pdb/paint_tools.pdb b/tools/pdbgen/pdb/paint_tools.pdb index 8e63f3c3e9..63846a0932 100644 --- a/tools/pdbgen/pdb/paint_tools.pdb +++ b/tools/pdbgen/pdb/paint_tools.pdb @@ -93,7 +93,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -121,7 +121,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -178,7 +178,7 @@ HELP ); %invoke = ( - headers => [ qw("blend.h") ], + headers => [ qw("tools/blend.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -237,7 +237,7 @@ HELP } %invoke = ( - headers => [ qw ("bucket_fill.h") ], + headers => [ qw ("tools/bucket_fill.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -283,7 +283,7 @@ HELP ); %invoke = ( - headers => [ qw("by_color_select.h") ], + headers => [ qw("tools/by_color_select.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -329,7 +329,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, strokes); @@ -359,7 +359,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui_default (drawable, num_strokes, strokes); CODE @@ -411,7 +411,7 @@ HELP ); %invoke = ( - headers => [ qw("color_picker.h") ], + headers => [ qw("tools/color_picker.h") ], code => <<'CODE' { if (!sample_merged) @@ -454,7 +454,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui_default (drawable, num_strokes, strokes); CODE @@ -484,7 +484,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui (drawable, pressure, convolve_type, num_strokes, strokes); CODE @@ -517,7 +517,7 @@ HELP ); %invoke = ( - headers => [ qw("crop.h") ], + headers => [ qw("tools/crop.h") ], code => <<'CODE' { if (new_width > gimage->width || new_height > gimage->height || @@ -564,7 +564,7 @@ HELP ); %invoke = ( - headers => [ qw("ellipse_select.h") ], + headers => [ qw("tools/ellipse_select.h") ], code => <<'CODE' ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, antialias, feather, feather_radius); @@ -591,7 +591,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui_default (drawable, num_strokes, strokes); CODE @@ -621,7 +621,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -651,7 +651,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -686,7 +686,8 @@ HELP @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( - headers => [ qw("flip_tool.h" "transform_core.h" "undo.h") ], + headers => [ qw("tools/flip_tool.h" "tools/transform_core.h" + "undo.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer' ], code => <<'CODE' @@ -761,7 +762,7 @@ HELP ); %invoke = ( - headers => [ qw("free_select.h") ], + headers => [ qw("tools/free_select.h") ], code => <<'CODE' free_select (gimage, num_segs, (ScanConvertPoint *) segs, operation, antialias, feather, feather_radius); @@ -811,7 +812,7 @@ HELP ); %invoke = ( - headers => [ qw("fuzzy_select.h") ], + headers => [ qw("tools/fuzzy_select.h") ], vars => [ 'GimpImage *gimage', 'Channel *new, *old_fuzzy_mask' ], code => <<'CODE' { @@ -862,7 +863,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method, gradient_length); @@ -899,7 +900,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -925,7 +926,7 @@ HELP ); %invoke = ( - headers => [ qw("pencil.h") ], + headers => [ qw("tools/pencil.h") ], code => 'success = pencil_non_gui (drawable, num_strokes, strokes);' ); } @@ -976,7 +977,7 @@ HELP @outargs = ( &drawable_out_arg('newly mapped') ); %invoke = ( - headers => [ qw("perspective_tool.h" "transform_core.h" + headers => [ qw("tools/perspective_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1060,7 +1061,7 @@ HELP ); %invoke = ( - headers => [ qw("rect_select.h") ], + headers => [ qw("tools/rect_select.h") ], code => <<'CODE' rect_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, feather, feather_radius); @@ -1097,7 +1098,7 @@ HELP @outargs = ( &drawable_out_arg('rotated') ); %invoke = ( - headers => [ qw("rotate_tool.h" "transform_core.h") ], + headers => [ qw("tools/rotate_tool.h" "tools/transform_core.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', 'GimpMatrix3 matrix' ], @@ -1176,7 +1177,7 @@ HELP @outargs = ( &drawable_out_arg('scaled') ); %invoke = ( - headers => [ qw("scale_tool.h" "transform_core.h" + headers => [ qw("tools/scale_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double scalex, scaley', @@ -1264,7 +1265,7 @@ HELP @outargs = ( &drawable_out_arg('sheared') ); %invoke = ( - headers => [ qw("shear_tool.h" "transform_core.h" + headers => [ qw("tools/shear_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1358,7 +1359,7 @@ HELP @outargs = ( &drawable_out_arg('transformed') ); %invoke = ( - headers => [ qw("transform_core.h" + headers => [ qw("tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'GimpMatrix3 matrix' ], @@ -1419,7 +1420,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -1447,7 +1448,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui_default (drawable, num_strokes, strokes); CODE @@ -1479,7 +1480,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui (drawable, exposure, dodgeburn_type, dodgeburn_mode, num_strokes, strokes); CODE @@ -1506,7 +1507,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui_default (drawable, num_strokes, strokes); CODE diff --git a/tools/pdbgen/pdb/text_tool.pdb b/tools/pdbgen/pdb/text_tool.pdb index 1b8e86fb41..c7c9aa22dd 100644 --- a/tools/pdbgen/pdb/text_tool.pdb +++ b/tools/pdbgen/pdb/text_tool.pdb @@ -253,7 +253,7 @@ HELP ); } -@headers = qw("appenv.h" "text_tool.h" "libgimp/gimplimits.h" +@headers = qw("appenv.h" "tools/text_tool.h" "libgimp/gimplimits.h" ); $extra{app}->{code} = <<'CODE'; diff --git a/tools/pdbgen/pdb/tools.pdb b/tools/pdbgen/pdb/tools.pdb index 8e63f3c3e9..63846a0932 100644 --- a/tools/pdbgen/pdb/tools.pdb +++ b/tools/pdbgen/pdb/tools.pdb @@ -93,7 +93,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -121,7 +121,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -178,7 +178,7 @@ HELP ); %invoke = ( - headers => [ qw("blend.h") ], + headers => [ qw("tools/blend.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -237,7 +237,7 @@ HELP } %invoke = ( - headers => [ qw ("bucket_fill.h") ], + headers => [ qw ("tools/bucket_fill.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -283,7 +283,7 @@ HELP ); %invoke = ( - headers => [ qw("by_color_select.h") ], + headers => [ qw("tools/by_color_select.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -329,7 +329,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, strokes); @@ -359,7 +359,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui_default (drawable, num_strokes, strokes); CODE @@ -411,7 +411,7 @@ HELP ); %invoke = ( - headers => [ qw("color_picker.h") ], + headers => [ qw("tools/color_picker.h") ], code => <<'CODE' { if (!sample_merged) @@ -454,7 +454,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui_default (drawable, num_strokes, strokes); CODE @@ -484,7 +484,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui (drawable, pressure, convolve_type, num_strokes, strokes); CODE @@ -517,7 +517,7 @@ HELP ); %invoke = ( - headers => [ qw("crop.h") ], + headers => [ qw("tools/crop.h") ], code => <<'CODE' { if (new_width > gimage->width || new_height > gimage->height || @@ -564,7 +564,7 @@ HELP ); %invoke = ( - headers => [ qw("ellipse_select.h") ], + headers => [ qw("tools/ellipse_select.h") ], code => <<'CODE' ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, antialias, feather, feather_radius); @@ -591,7 +591,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui_default (drawable, num_strokes, strokes); CODE @@ -621,7 +621,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -651,7 +651,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -686,7 +686,8 @@ HELP @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( - headers => [ qw("flip_tool.h" "transform_core.h" "undo.h") ], + headers => [ qw("tools/flip_tool.h" "tools/transform_core.h" + "undo.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer' ], code => <<'CODE' @@ -761,7 +762,7 @@ HELP ); %invoke = ( - headers => [ qw("free_select.h") ], + headers => [ qw("tools/free_select.h") ], code => <<'CODE' free_select (gimage, num_segs, (ScanConvertPoint *) segs, operation, antialias, feather, feather_radius); @@ -811,7 +812,7 @@ HELP ); %invoke = ( - headers => [ qw("fuzzy_select.h") ], + headers => [ qw("tools/fuzzy_select.h") ], vars => [ 'GimpImage *gimage', 'Channel *new, *old_fuzzy_mask' ], code => <<'CODE' { @@ -862,7 +863,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method, gradient_length); @@ -899,7 +900,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -925,7 +926,7 @@ HELP ); %invoke = ( - headers => [ qw("pencil.h") ], + headers => [ qw("tools/pencil.h") ], code => 'success = pencil_non_gui (drawable, num_strokes, strokes);' ); } @@ -976,7 +977,7 @@ HELP @outargs = ( &drawable_out_arg('newly mapped') ); %invoke = ( - headers => [ qw("perspective_tool.h" "transform_core.h" + headers => [ qw("tools/perspective_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1060,7 +1061,7 @@ HELP ); %invoke = ( - headers => [ qw("rect_select.h") ], + headers => [ qw("tools/rect_select.h") ], code => <<'CODE' rect_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, feather, feather_radius); @@ -1097,7 +1098,7 @@ HELP @outargs = ( &drawable_out_arg('rotated') ); %invoke = ( - headers => [ qw("rotate_tool.h" "transform_core.h") ], + headers => [ qw("tools/rotate_tool.h" "tools/transform_core.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', 'GimpMatrix3 matrix' ], @@ -1176,7 +1177,7 @@ HELP @outargs = ( &drawable_out_arg('scaled') ); %invoke = ( - headers => [ qw("scale_tool.h" "transform_core.h" + headers => [ qw("tools/scale_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double scalex, scaley', @@ -1264,7 +1265,7 @@ HELP @outargs = ( &drawable_out_arg('sheared') ); %invoke = ( - headers => [ qw("shear_tool.h" "transform_core.h" + headers => [ qw("tools/shear_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1358,7 +1359,7 @@ HELP @outargs = ( &drawable_out_arg('transformed') ); %invoke = ( - headers => [ qw("transform_core.h" + headers => [ qw("tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'GimpMatrix3 matrix' ], @@ -1419,7 +1420,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -1447,7 +1448,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui_default (drawable, num_strokes, strokes); CODE @@ -1479,7 +1480,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui (drawable, exposure, dodgeburn_type, dodgeburn_mode, num_strokes, strokes); CODE @@ -1506,7 +1507,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui_default (drawable, num_strokes, strokes); CODE diff --git a/tools/pdbgen/pdb/transform_tools.pdb b/tools/pdbgen/pdb/transform_tools.pdb index 8e63f3c3e9..63846a0932 100644 --- a/tools/pdbgen/pdb/transform_tools.pdb +++ b/tools/pdbgen/pdb/transform_tools.pdb @@ -93,7 +93,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -121,7 +121,7 @@ HELP ); %invoke = ( - headers => [ qw("airbrush.h") ], + headers => [ qw("tools/airbrush.h") ], code => <<'CODE' success = airbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -178,7 +178,7 @@ HELP ); %invoke = ( - headers => [ qw("blend.h") ], + headers => [ qw("tools/blend.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -237,7 +237,7 @@ HELP } %invoke = ( - headers => [ qw ("bucket_fill.h") ], + headers => [ qw ("tools/bucket_fill.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -283,7 +283,7 @@ HELP ); %invoke = ( - headers => [ qw("by_color_select.h") ], + headers => [ qw("tools/by_color_select.h") ], vars => [ 'GimpImage *gimage' ], code => <<'CODE' { @@ -329,7 +329,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui (drawable, src_drawable, clone_type, src_x, src_y, num_strokes, strokes); @@ -359,7 +359,7 @@ HELP ); %invoke = ( - headers => [ qw("clone.h") ], + headers => [ qw("tools/clone.h") ], code => <<'CODE' success = clone_non_gui_default (drawable, num_strokes, strokes); CODE @@ -411,7 +411,7 @@ HELP ); %invoke = ( - headers => [ qw("color_picker.h") ], + headers => [ qw("tools/color_picker.h") ], code => <<'CODE' { if (!sample_merged) @@ -454,7 +454,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui_default (drawable, num_strokes, strokes); CODE @@ -484,7 +484,7 @@ HELP ); %invoke = ( - headers => [ qw("convolve.h") ], + headers => [ qw("tools/convolve.h") ], code => <<'CODE' success = convolve_non_gui (drawable, pressure, convolve_type, num_strokes, strokes); CODE @@ -517,7 +517,7 @@ HELP ); %invoke = ( - headers => [ qw("crop.h") ], + headers => [ qw("tools/crop.h") ], code => <<'CODE' { if (new_width > gimage->width || new_height > gimage->height || @@ -564,7 +564,7 @@ HELP ); %invoke = ( - headers => [ qw("ellipse_select.h") ], + headers => [ qw("tools/ellipse_select.h") ], code => <<'CODE' ellipse_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, antialias, feather, feather_radius); @@ -591,7 +591,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui_default (drawable, num_strokes, strokes); CODE @@ -621,7 +621,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -651,7 +651,7 @@ HELP ); %invoke = ( - headers => [ qw("eraser.h") ], + headers => [ qw("tools/eraser.h") ], code => <<'CODE' success = eraser_non_gui (drawable, num_strokes, strokes, hardness, method, TRUE); CODE @@ -686,7 +686,8 @@ HELP @outargs = ( &drawable_out_arg('flipped') ); %invoke = ( - headers => [ qw("flip_tool.h" "transform_core.h" "undo.h") ], + headers => [ qw("tools/flip_tool.h" "tools/transform_core.h" + "undo.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer' ], code => <<'CODE' @@ -761,7 +762,7 @@ HELP ); %invoke = ( - headers => [ qw("free_select.h") ], + headers => [ qw("tools/free_select.h") ], code => <<'CODE' free_select (gimage, num_segs, (ScanConvertPoint *) segs, operation, antialias, feather, feather_radius); @@ -811,7 +812,7 @@ HELP ); %invoke = ( - headers => [ qw("fuzzy_select.h") ], + headers => [ qw("tools/fuzzy_select.h") ], vars => [ 'GimpImage *gimage', 'Channel *new, *old_fuzzy_mask' ], code => <<'CODE' { @@ -862,7 +863,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, method, gradient_length); @@ -899,7 +900,7 @@ HELP ); %invoke = ( - headers => [ qw("paintbrush.h") ], + headers => [ qw("tools/paintbrush.h") ], code => <<'CODE' success = paintbrush_non_gui_default (drawable, num_strokes, strokes); CODE @@ -925,7 +926,7 @@ HELP ); %invoke = ( - headers => [ qw("pencil.h") ], + headers => [ qw("tools/pencil.h") ], code => 'success = pencil_non_gui (drawable, num_strokes, strokes);' ); } @@ -976,7 +977,7 @@ HELP @outargs = ( &drawable_out_arg('newly mapped') ); %invoke = ( - headers => [ qw("perspective_tool.h" "transform_core.h" + headers => [ qw("tools/perspective_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1060,7 +1061,7 @@ HELP ); %invoke = ( - headers => [ qw("rect_select.h") ], + headers => [ qw("tools/rect_select.h") ], code => <<'CODE' rect_select (gimage, (int) x, (int) y, (int) width, (int) height, operation, feather, feather_radius); @@ -1097,7 +1098,7 @@ HELP @outargs = ( &drawable_out_arg('rotated') ); %invoke = ( - headers => [ qw("rotate_tool.h" "transform_core.h") ], + headers => [ qw("tools/rotate_tool.h" "tools/transform_core.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', 'GimpMatrix3 matrix' ], @@ -1176,7 +1177,7 @@ HELP @outargs = ( &drawable_out_arg('scaled') ); %invoke = ( - headers => [ qw("scale_tool.h" "transform_core.h" + headers => [ qw("tools/scale_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double scalex, scaley', @@ -1264,7 +1265,7 @@ HELP @outargs = ( &drawable_out_arg('sheared') ); %invoke = ( - headers => [ qw("shear_tool.h" "transform_core.h" + headers => [ qw("tools/shear_tool.h" "tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'double cx, cy', @@ -1358,7 +1359,7 @@ HELP @outargs = ( &drawable_out_arg('transformed') ); %invoke = ( - headers => [ qw("transform_core.h" + headers => [ qw("tools/transform_core.h" "tile_manager_pvt.h") ], vars => [ 'GimpImage *gimage', 'TileManager *float_tiles, *new_tiles', 'gboolean new_layer', 'GimpMatrix3 matrix' ], @@ -1419,7 +1420,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui (drawable, pressure, num_strokes, strokes); CODE @@ -1447,7 +1448,7 @@ HELP ); %invoke = ( - headers => [ qw("smudge.h") ], + headers => [ qw("tools/smudge.h") ], code => <<'CODE' success = smudge_non_gui_default (drawable, num_strokes, strokes); CODE @@ -1479,7 +1480,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui (drawable, exposure, dodgeburn_type, dodgeburn_mode, num_strokes, strokes); CODE @@ -1506,7 +1507,7 @@ HELP ); %invoke = ( - headers => [ qw("dodgeburn.h") ], + headers => [ qw("tools/dodgeburn.h") ], code => <<'CODE' success = dodgeburn_non_gui_default (drawable, num_strokes, strokes); CODE