gimp/app/tools/gimpiscissorstool.c

2807 lines
67 KiB
C
Raw Normal View History

1997-11-25 06:05:25 +08:00
/* 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.
1997-11-25 06:05:25 +08:00
*/
/* This tool is based on a paper from SIGGRAPH '95
* thanks to Professor D. Forsyth for prompting us to implement this tool
*/
#include <math.h>
1997-11-25 06:05:25 +08:00
#include <stdlib.h>
#include <string.h>
1997-11-25 06:05:25 +08:00
#include "appenv.h"
#include "draw_core.h"
#include "channel_pvt.h"
#include "drawable.h"
1997-11-25 06:05:25 +08:00
#include "errors.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "interface.h"
#include "iscissors.h"
#include "edit_selection.h"
#include "paint_funcs.h"
#include "rect_select.h"
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
#include "selection_options.h"
1997-11-25 06:05:25 +08:00
#include "temp_buf.h"
#include "tools.h"
#include "bezier_selectP.h"
1997-11-25 06:05:25 +08:00
#include "libgimp/gimpintl.h"
/* the intelligent scissors structures */
1997-11-25 06:05:25 +08:00
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
typedef struct _Kink Kink;
struct _Kink
1997-11-25 06:05:25 +08:00
{
int x, y; /* coordinates */
int is_a_kink; /* is this a kink? */
double normal[2]; /* normal vector to kink */
double kinkiness; /* kinkiness measure */
};
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
typedef struct _Point Point;
struct _Point
1997-11-25 06:05:25 +08:00
{
int x, y; /* coordinates */
int dir; /* direction */
int kink; /* is it a kink? */
int stable; /* is the point in a stable locale? */
double dx, dy; /* moving coordinates */
double normal[2]; /* normal vector to kink */
};
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
typedef struct _Iscissors Iscissors;
struct _Iscissors
1997-11-25 06:05:25 +08:00
{
DrawCore * core; /* Core select object */
int x, y; /* upper left hand coordinate */
int ix, iy; /* initial coordinates */
int nx, ny; /* new coordinates */
int state; /* state of iscissors */
int num_segs; /* number of points in the polygon */
int num_pts; /* number of kinks in list */
int num_kinks; /* number of kinks in list */
Channel * mask; /* selection mask */
Kink * kinks; /* kinks in the object outline */
TempBuf * edge_buf; /* edge map buffer */
};
typedef struct _IScissorsOptions IScissorsOptions;
struct _IScissorsOptions
{
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
SelectionOptions selection_options;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
double resolution;
double resolution_d;
GtkObject *resolution_w;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
double threshold;
double threshold_d;
GtkObject *threshold_w;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
double elasticity;
double elasticity_d;
GtkObject *elasticity_w;
};
1997-11-25 06:05:25 +08:00
typedef double BezierMatrix[4][4];
typedef double CRMatrix[4][4];
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
/* the intelligent scissors tool options */
static IScissorsOptions *iscissors_options = NULL;
1997-11-25 06:05:25 +08:00
/**********************************************/
/* Intelligent scissors selection apparatus */
#define IMAGE_COORDS 1
#define AA_IMAGE_COORDS 2
#define SCREEN_COORDS 3
#define SUPERSAMPLE 3
#define SUPERSAMPLE2 9
#define FREE_SELECT_MODE 0
#define BOUNDARY_MODE 1
#define POINT_WIDTH 8
#define POINT_HALFWIDTH 4
#define DEFAULT_MAX_INC 1024
#define EDGE_WIDTH 1
#define LOCALIZE_RADIUS 24
#define BLOCK_WIDTH 64
#define BLOCK_HEIGHT 64
#define CONV_WIDTH BLOCK_WIDTH
#define CONV_HEIGHT BLOCK_HEIGHT
#define HORIZONTAL 0
#define VERTICAL 1
#define SUBDIVIDE 1000
#define EDGE_STRENGTH 255
#define EPSILON 0.00001
/* functional defines */
#define BILINEAR(jk,j1k,jk1,j1k1,dx,dy) \
((1-dy) * ((1-dx)*jk + dx*j1k) + \
dy * ((1-dx)*jk1 + dx*j1k1))
/* static variables */
static Tool* last_tool;
1997-11-25 06:05:25 +08:00
/* The global array of XSegments for drawing the polygon... */
static GdkSegment *segs = NULL;
static int max_segs = 0;
static Point * pts = NULL;
static int max_pts = 0;
/* boundary resolution variables */
static double kink_thres = 0.33; /* between 0.0 -> 1.0 */
static double std_dev = 1.0; /* in pixels */
static int miss_thres = 4; /* in intensity */
/* edge map blocks variables */
static TempBuf ** edge_map_blocks = NULL;
static int horz_blocks;
static int vert_blocks;
/* convolution and basis matrixes */
static unsigned char conv1 [CONV_WIDTH * CONV_HEIGHT * MAX_CHANNELS];
static unsigned char conv2 [CONV_WIDTH * CONV_HEIGHT * MAX_CHANNELS];
static unsigned char grad [(CONV_WIDTH + 2) * (CONV_HEIGHT + 2)];
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 },
};
static CRMatrix CR_bezier_basis =
{
{ 0.0, 1.0, 0.0, 0.0 },
{ -0.16667, 1.0, 0.16667, 0.0 },
{ 0.0, 0.16667, 1.0, -0.16667 },
{ 0.0, 0.0, 1.0, 0.0 },
};
/* Local function prototypes */
static void selection_to_bezier (GtkWidget* , gpointer);
1997-11-25 06:05:25 +08:00
static void iscissors_button_press (Tool *, GdkEventButton *, gpointer);
static void iscissors_button_release (Tool *, GdkEventButton *, gpointer);
static void iscissors_motion (Tool *, GdkEventMotion *, gpointer);
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
static void iscissors_control (Tool *, ToolAction, gpointer);
1997-11-25 06:05:25 +08:00
static void iscissors_reset (Iscissors *);
static void iscissors_draw (Tool *);
static void iscissors_draw_CR (GDisplay *, Iscissors *,
Point *, int *, int);
static void CR_compose (CRMatrix, CRMatrix, CRMatrix);
static int add_segment (int *, int, int);
static int add_point (int *, int, int, int, double *);
/* boundary localization routines */
static void normalize (double *);
static double dotprod (double *, double *);
static Kink * get_kink (Kink *, int, int);
static int find_next_kink (Kink *, int, int);
static double find_distance (Kink *, int, int);
static int go_distance (Kink *, int, double, double *, double *);
static int travel_length (Kink *, int, int, int, int);
static int find_edge_xy (TempBuf *, int, double, double, double *);
static void find_boundary (Tool *);
static void shape_of_boundary (Tool *);
static void process_kinks (Tool *);
static void initial_boundary (Tool *);
static void edge_map_from_boundary (Tool *);
static void orient_boundary (Tool *);
static void reset_boundary (Tool *);
static int localize_boundary (Tool *);
static void post_process_boundary (Tool *);
static void bezierify_boundary (Tool *);
/* edge map buffer utility functions */
static TempBuf * calculate_edge_map (GImage *, int, int, int, int);
static void construct_edge_map (Tool *, TempBuf *);
/* edge map blocks utility functions */
static void set_edge_map_blocks (void *, int, int, int, int);
static void allocate_edge_map_blocks (int, int, int, int);
static void free_edge_map_blocks (void);
/* gaussian & 1st derivative */
static void gaussian_deriv (PixelRegion *, PixelRegion *, int, double);
static void make_curve (int *, int *, double, int);
static void make_curve_d (int *, int *, double, int);
/* Catmull-Rom boundary conversion */
static void CR_convert (Iscissors * , GDisplay *, int);
static void CR_convert_points (GdkPoint *, int);
static void CR_convert_line (GSList **, int, int, int, int);
static GSList * CR_insert_in_list (GSList *, int);
1997-11-25 06:05:25 +08:00
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
/* functions */
1997-11-25 06:05:25 +08:00
static void
selection_scale_update (GtkAdjustment *adjustment,
double *scale_val)
{
*scale_val = adjustment->value;
}
static void
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
selection_to_bezier(GtkWidget *w,
gpointer none)
{
Iscissors *iscissors;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
if(last_tool)
{
iscissors = (Iscissors *) last_tool->private;
last_tool->state = INACTIVE;
bezierify_boundary (last_tool);
}
}
static void
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
iscissors_options_reset (void)
{
IScissorsOptions *options = iscissors_options;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
selection_options_reset ((SelectionOptions *) options);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->resolution_w),
options->resolution_d);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->threshold_w),
options->threshold_d);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->elasticity_w),
options -> elasticity_d);
}
1997-11-25 06:05:25 +08:00
static IScissorsOptions *
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
iscissors_options_new (void)
1997-11-25 06:05:25 +08:00
{
IScissorsOptions *options;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
1997-11-25 06:05:25 +08:00
GtkWidget *vbox;
GtkWidget *abox;
GtkWidget *table;
1997-11-25 06:05:25 +08:00
GtkWidget *label;
GtkWidget *scale;
1997-11-25 06:05:25 +08:00
GtkWidget *convert_button;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
/* the new intelligent scissors tool options structure */
1997-11-25 06:05:25 +08:00
options = (IScissorsOptions *) g_malloc (sizeof (IScissorsOptions));
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
selection_options_init ((SelectionOptions *) options,
ISCISSORS,
iscissors_options_reset);
options->resolution = options->resolution_d = 40.0;
options->threshold = options->threshold_d = 15.0;
options->elasticity = options->elasticity_d = 0.30;
1997-11-25 06:05:25 +08:00
/* the main vbox */
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
vbox = ((ToolOptions *) options)->main_vbox;
/* the resolution scale */
table = gtk_table_new (5, 2, FALSE);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 6);
gtk_table_set_row_spacing (GTK_TABLE (table), 1, 2);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_set_row_spacing (GTK_TABLE (table), 3, 1);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
label = gtk_label_new (_("Curve"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
1997-11-25 06:05:25 +08:00
label = gtk_label_new (_("Resolution:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
1997-11-25 06:05:25 +08:00
gtk_widget_show (label);
abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
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->resolution_w =
gtk_adjustment_new (options->resolution_d, 1.0, 200.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->resolution_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->resolution_w), "value_changed",
1997-11-25 06:05:25 +08:00
(GtkSignalFunc) selection_scale_update,
&options->resolution);
gtk_widget_show (scale);
1997-11-25 06:05:25 +08:00
/* the threshold scale */
label = gtk_label_new (_("Edge Detect "));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
1997-11-25 06:05:25 +08:00
label = gtk_label_new (_("Threshold:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
1997-11-25 06:05:25 +08:00
gtk_widget_show (label);
abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 2, 4,
GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (abox);
options->threshold_w =
gtk_adjustment_new (options->threshold_d, 1.0, 255.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_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->threshold_w), "value_changed",
1997-11-25 06:05:25 +08:00
(GtkSignalFunc) selection_scale_update,
&options->threshold);
gtk_widget_show (scale);
1997-11-25 06:05:25 +08:00
/* the elasticity scale */
label = gtk_label_new (_("Elasticity:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (label);
options->elasticity_w =
gtk_adjustment_new (options->elasticity_d, 0.0, 1.0, 0.05, 0.05, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->elasticity_w));
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
gtk_table_attach_defaults (GTK_TABLE (table), scale, 1, 2, 4, 5);
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->elasticity_w), "value_changed",
(GtkSignalFunc) selection_scale_update,
&options -> elasticity);
gtk_widget_show (scale);
gtk_widget_show (table);
1997-11-25 06:05:25 +08:00
/* the convert to bezier button */
convert_button = gtk_button_new_with_label (_("Convert to Bezier Curve"));
gtk_box_pack_start (GTK_BOX (vbox), convert_button, FALSE, FALSE, 1);
gtk_signal_connect(GTK_OBJECT (convert_button) , "clicked",
(GtkSignalFunc) selection_to_bezier,
NULL);
1997-11-25 06:05:25 +08:00
gtk_widget_show (convert_button);
return options;
}
Tool *
tools_new_iscissors ()
{
Tool * tool;
Iscissors * private;
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
/* The tool options */
if (! iscissors_options)
{
iscissors_options = iscissors_options_new ();
tools_register (ISCISSORS, (ToolOptions *) iscissors_options);
}
1997-11-25 06:05:25 +08:00
tool = tools_new_tool (ISCISSORS);
private = g_new (Iscissors, 1);
1997-11-25 06:05:25 +08:00
private->core = draw_core_new (iscissors_draw);
private->edge_buf = NULL;
private->kinks = NULL;
private->mask = NULL;
tool->auto_snap_to = FALSE; /* Dont't snap to guides */
tool->private = (void *) private;
tool->button_press_func = iscissors_button_press;
1997-11-25 06:05:25 +08:00
tool->button_release_func = iscissors_button_release;
tool->motion_func = iscissors_motion;
tool->cursor_update_func = rect_select_cursor_update;
tool->control_func = iscissors_control;
last_tool = tool;
1997-11-25 06:05:25 +08:00
iscissors_reset (private);
1997-11-25 06:05:25 +08:00
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,
gpointer gdisp_ptr)
{
GDisplay *gdisp;
GimpDrawable *drawable;
1997-11-25 06:05:25 +08:00
Iscissors *iscissors;
int replace, op;
int x, y;
1997-11-25 06:05:25 +08:00
last_tool = tool;
1997-11-25 06:05:25 +08:00
gdisp = (GDisplay *) gdisp_ptr;
iscissors = (Iscissors *) tool->private;
drawable = gimage_active_drawable (gdisp->gimage);
1997-11-25 06:05:25 +08:00
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
&iscissors->x, &iscissors->y, FALSE, TRUE);
1997-11-25 06:05:25 +08:00
/* If the tool was being used in another image...reset it */
1997-11-25 06:05:25 +08:00
if (tool->state == ACTIVE && gdisp_ptr != tool->gdisp_ptr)
{
draw_core_stop (iscissors->core, tool);
iscissors_reset (iscissors);
}
switch (iscissors->state)
{
case FREE_SELECT_MODE:
tool->state = ACTIVE;
last_tool = NULL;
1997-11-25 06:05:25 +08:00
tool->gdisp_ptr = gdisp_ptr;
gdk_pointer_grab (gdisp->canvas->window, FALSE,
(GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK),
NULL, NULL, bevent->time);
if (bevent->state & GDK_MOD1_MASK)
{
init_edit_selection (tool, gdisp_ptr, bevent, MaskTranslate);
return;
}
else if (!(bevent->state & GDK_SHIFT_MASK) && !(bevent->state & GDK_CONTROL_MASK))
if (! (layer_is_floating_sel (gimage_get_active_layer (gdisp->gimage))) &&
gdisplay_mask_value (gdisp, bevent->x, bevent->y) > HALF_WAY)
{
/* Have to blank out the edge blocks since they might change */
iscissors_reset (iscissors);
init_edit_selection (tool, gdisp_ptr, bevent, MaskToLayerTranslate);
return;
}
/* If the edge map blocks haven't been allocated, do so now */
if (!edge_map_blocks)
1997-11-25 06:05:25 +08:00
allocate_edge_map_blocks (BLOCK_WIDTH, BLOCK_HEIGHT,
drawable_width(drawable),
drawable_height(drawable));
1997-11-25 06:05:25 +08:00
iscissors->num_segs = 0;
x = bevent->x;
y = bevent->y;
add_segment (&(iscissors->num_segs), x, y);
1997-11-25 06:05:25 +08:00
draw_core_start (iscissors->core,
gdisp->canvas->window,
tool);
break;
case BOUNDARY_MODE:
if (/*channel_value (iscissors->mask, iscissors->x, iscissors->y)*/ TRUE)
1997-11-25 06:05:25 +08:00
{
replace = 0;
if ((bevent->state & GDK_SHIFT_MASK) && !(bevent->state & GDK_CONTROL_MASK))
1997-11-25 06:05:25 +08:00
op = ADD;
else if ((bevent->state & GDK_CONTROL_MASK) && !(bevent->state & GDK_SHIFT_MASK))
op = SUB;
else if ((bevent->state & GDK_CONTROL_MASK) && (bevent->state & GDK_SHIFT_MASK))
op = INTERSECT;
else
{
op = ADD;
replace = 1;
}
tool->state = INACTIVE;
/* If we're antialiased, then recompute the
* mask...
*/
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
if (((SelectionOptions *) iscissors_options)->antialias)
CR_convert (iscissors, tool->gdisp_ptr, TRUE);
1997-11-25 06:05:25 +08:00
draw_core_stop (iscissors->core, tool);
if (replace)
gimage_mask_clear (gdisp->gimage);
else
gimage_mask_undo (gdisp->gimage);
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
if (((SelectionOptions *) iscissors_options)->feather)
1997-11-25 06:05:25 +08:00
channel_feather (iscissors->mask,
gimage_get_mask (gdisp->gimage),
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
((SelectionOptions *) iscissors_options)->feather_radius,
((SelectionOptions *) iscissors_options)->feather_radius,
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
op, 0, 0);
1997-11-25 06:05:25 +08:00
else
channel_combine_mask (gimage_get_mask (gdisp->gimage),
iscissors->mask, op, 0, 0);
iscissors_reset (iscissors);
gdisplays_flush ();
}
break;
}
}
static void
iscissors_button_release (Tool *tool,
GdkEventButton *bevent,
gpointer gdisp_ptr)
{
Iscissors *iscissors;
GDisplay *gdisp;
gdisp = (GDisplay *) gdisp_ptr;
iscissors = (Iscissors *) tool->private;
/*return;*/
last_tool = tool;
1997-11-25 06:05:25 +08:00
gdk_pointer_ungrab (bevent->time);
gdk_flush ();
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 FREE_SELECT_MODE:
/* Add one additional segment */
add_segment (&(iscissors->num_segs), segs[0].x1, segs[0].y1);
if (iscissors->num_segs >= 3)
{
/* Find the boundary */
find_boundary (tool);
/* Set the new state */
iscissors->state = BOUNDARY_MODE;
/* Start the draw core up again */
draw_core_resume (iscissors->core, tool);
return;
}
break;
case BOUNDARY_MODE:
iscissors->state = FREE_SELECT_MODE;
break;
}
}
tool->state = INACTIVE;
}
static void
iscissors_motion (Tool *tool,
GdkEventMotion *mevent,
gpointer gdisp_ptr)
{
Iscissors *iscissors;
GDisplay *gdisp;
int x, y;
1997-11-25 06:05:25 +08:00
if (tool->state != ACTIVE)
return;
gdisp = (GDisplay *) gdisp_ptr;
iscissors = (Iscissors *) tool->private;
1997-11-25 06:05:25 +08:00
switch (iscissors->state)
{
case FREE_SELECT_MODE:
x = mevent->x;
y = mevent->y;
if (add_segment (&(iscissors->num_segs), x, y))
1997-11-25 06:05:25 +08:00
gdk_draw_segments (iscissors->core->win, iscissors->core->gc,
segs + (iscissors->num_segs - 1), 1);
break;
case BOUNDARY_MODE:
break;
}
}
static void
iscissors_draw (Tool *tool)
{
GDisplay *gdisp;
Iscissors *iscissors;
int indices[4];
int i;
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
switch (iscissors->state)
{
case FREE_SELECT_MODE:
gdk_draw_segments (iscissors->core->win, iscissors->core->gc,
segs, iscissors->num_segs);
break;
case BOUNDARY_MODE:
for (i = 0; i < iscissors->num_pts; i ++)
{
indices[0] = (i < 3) ? (iscissors->num_pts + i - 3) : (i - 3);
indices[1] = (i < 2) ? (iscissors->num_pts + i - 2) : (i - 2);
indices[2] = (i < 1) ? (iscissors->num_pts + i - 1) : (i - 1);
indices[3] = i;
iscissors_draw_CR (gdisp, iscissors, pts, indices, SCREEN_COORDS);
}
break;
}
}
static void
iscissors_draw_CR (GDisplay *gdisp,
Iscissors *iscissors,
Point *pts,
int *indices,
int draw_type)
{
static GdkPoint gdk_points[256];
static int npoints = 256;
CRMatrix geometry;
CRMatrix tmp1, tmp2;
CRMatrix deltas;
double x, dx, dx2, dx3;
double y, dy, dy2, dy3;
double d, d2, d3;
int lastx, lasty;
int newx, newy;
/* int tx, ty; */
1997-11-25 06:05:25 +08:00
int index;
int i;
GimpDrawable *drawable;
drawable = gimage_active_drawable (gdisp->gimage);
1997-11-25 06:05:25 +08:00
/* construct the geometry matrix from the segment */
/* assumes that a valid segment containing 4 points is passed in */
for (i = 0; i < 4; i++)
{
switch (draw_type)
{
case IMAGE_COORDS:
geometry[i][0] = pts[indices[i]].dx;
geometry[i][1] = pts[indices[i]].dy;
break;
case AA_IMAGE_COORDS:
geometry[i][0] = pts[indices[i]].dx * SUPERSAMPLE;
geometry[i][1] = pts[indices[i]].dy * SUPERSAMPLE;
break;
case SCREEN_COORDS:
gdisplay_transform_coords_f(gdisp, (int) pts[indices[i]].dx,
1998-03-26 13:49:30 +08:00
(int) pts[indices[i]].dy, &x, &y, TRUE);
1998-03-12 14:43:44 +08:00
geometry[i][0] = x;
geometry[i][1] = y;
/*g_print("%f %f\n", x, y);*/
1997-11-25 06:05:25 +08:00
break;
}
geometry[i][2] = 0;
geometry[i][3] = 0;
}
/* subdivide the curve n times */
/* n can be adjusted to give a finer or coarser curve */
d = 1.0 / SUBDIVIDE;
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 */
CR_compose (CR_basis, geometry, tmp1);
/* compose the above results to get the deltas matrix */
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 = x;
lasty = y;
gdk_points[0].x = lastx;
gdk_points[0].y = lasty;
index = 1;
/* loop over the curve */
for (i = 0; i < SUBDIVIDE; 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);
1997-11-25 06:05:25 +08:00
/* if this point is different than the last one...then draw it */
if ((lastx != newx) || (lasty != newy))
{
/* add the point to the point buffer */
/*gdisplay_transform_coords (gdisp, newx, newy, &tx, &ty,1 );*/
/*drawable_offsets(drawable, &tx, &ty);
tx += newx;
ty += newy;*/
gdk_points[index].x = newx;
gdk_points[index].y = newy;
1997-11-25 06:05:25 +08:00
index++;
1997-11-25 06:05:25 +08:00
/* if the point buffer is full put it to the screen and zero it out */
if (index >= npoints)
{
switch (draw_type)
{
case IMAGE_COORDS: case AA_IMAGE_COORDS:
CR_convert_points (gdk_points, index);
break;
case SCREEN_COORDS:
gdk_draw_points (iscissors->core->win, iscissors->core->gc,
gdk_points, index);
break;
}
index = 0;
}
}
lastx = newx;
lasty = newy;
}
/* if there are points in the buffer, then put them on the screen */
if (index)
switch (draw_type)
{
case IMAGE_COORDS: case AA_IMAGE_COORDS:
CR_convert_points (gdk_points, index);
break;
case SCREEN_COORDS:
gdk_draw_points (iscissors->core->win, iscissors->core->gc,
gdk_points, index);
break;
}
}
static void
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
iscissors_control (Tool *tool,
ToolAction action,
gpointer gdisp_ptr)
1997-11-25 06:05:25 +08:00
{
Iscissors * iscissors;
iscissors = (Iscissors *) tool->private;
switch (action)
{
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
case PAUSE:
1997-11-25 06:05:25 +08:00
draw_core_pause (iscissors->core, tool);
break;
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
case RESUME:
1997-11-25 06:05:25 +08:00
draw_core_resume (iscissors->core, tool);
break;
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
case HALT:
1997-11-25 06:05:25 +08:00
draw_core_stop (iscissors->core, tool);
iscissors_reset (iscissors);
break;
namespace cleanups. 1999-06-21 Michael Natterer <mitschel@cs.tu-berlin.de> * app/context_manager.c: namespace cleanups. * app/commands.[ch] * app/menus.c: moved the "Toggle Selection" menu entry to "View", sprinkled some separators and made the layers/channels/paths popup menus consistent with Tigert's last ops buttons change. * app/fileops.c * app/plug_in.c: check for gdisplay_active() returning NULL in some more places. * app/[all tool related files]: - Turned the ToolAction and ToolState #define's into typedef'ed enums, so the compiler can do some more sanity checking. - Removed one more unused global variable "active_tool_layer". - Removed some #include's from tools.c. - Standardized the individual tools' structure names. - Moved showing/hiding the tool options to separate functions. - Stuff... * app/commands.c * app/disp_callbacks.c * app/gdisplay.c * app/tools.c: fixed the segfaults which happened when the image of one of the tools which have dialogs (levels/posterize/...) was deleted. My approach was to do stricter sanity checking and to set some gdisplay pointers correctly where appropriate, so I can't tell exactly where the bug was. The curves tool now(??) updates on every _second_ display change only, which is really obscure. Finding/changing the display to operate on should definitely be done by connecting to the user context's "display_changed" signal. * app/gimpset.c: emit the "remove" signal _after_ removing the pointer from the set. If this was not a bug but a feature, please let me know, we'll need two signals then.
1999-06-22 06:12:07 +08:00
default:
break;
1997-11-25 06:05:25 +08:00
}
}
static void
iscissors_reset (Iscissors *iscissors)
{
/* Reset the edge map blocks structure */
free_edge_map_blocks ();
/* free edge buffer */
if (iscissors->edge_buf)
temp_buf_free (iscissors->edge_buf);
/* free mask */
if (iscissors->mask)
channel_delete (iscissors->mask);
/* Free kinks */
if (iscissors->kinks)
g_free (iscissors->kinks);
iscissors->state = FREE_SELECT_MODE;
iscissors->mask = NULL;
iscissors->edge_buf = NULL;
iscissors->kinks = NULL;
iscissors->num_segs = 0;
iscissors->num_pts = 0;
iscissors->num_kinks = 0;
}
static int
add_segment (int *num_segs,
int x,
int y)
{
static int first = 1;
if (*num_segs >= max_segs)
{
max_segs += DEFAULT_MAX_INC;
segs = (GdkSegment *) g_realloc ((void *) segs, sizeof (GdkSegment) * max_segs);
if (!segs)
new ui for the "Layer Offset" dialog. 1999-07-22 Michael Natterer <mitschel@cs.tu-berlin.de> * app/channel_ops.[ch]: new ui for the "Layer Offset" dialog. * app/channels_dialog.c * app/layers_dialog.c: major code cleanup: Folded some callbacks into common ones, "widget" instead of "w", indentation, ... * app/commands.c * app/interface.[ch] * app/global_edit.c: the query boxes must be shown by the caller now. There's no need to split up the string for the message box manually as the Gtk 1.2 label widget handles newlines corectly. Added the "edge_lock" toggle to the "Shrink Selection" dialog. Nicer spacings for the query and message boxes. * app/ink.c: tried to grab the pointer in the blob preview but failed. Left the code there as a reminder (commented out). * app/menus.c: reordered <Image>/Select. I was bored and grep-ed the sources for ancient or deprecated stuff: * app/about_dialog.[ch] * app/actionarea.[ch] * app/app_procs.c * app/brush_edit.c * app/brush_select.c * app/color_select.c * app/convert.c * app/devices.c * app/gdisplay.c * app/gdisplay_ops.c * app/histogram_tool.[ch] * app/info_window.c * app/install.c * app/ops_buttons.c * app/palette.c * app/palette_select.c * app/paths_dialog.c * app/pattern_select.c * app/resize.c * app/scale_toolc.c * app/text_tool.c: s/container_border_width/container_set_border_width/g, s/sprintf/g_snprintf/g, replaced some constant string lengths with strlen(x). * app/bezier_select.c * app/blend.c * app/boundary.c * app/errors.[ch] * app/free_select.c * app/gimpbrushlist.c * app/gimprc.c * app/iscissors.c * app/main.c * app/patterns.[ch] * app/text_tool.c: namespace fanaticism: prefixed all gimp error functions with "gimp_" and formated the messages more uniformly. * app/gradient.c * app/gradient_select.c: same stuff as above for the ui code. There are still some sub-dialogs which need cleanup. Did some cleanup in most of these files: prototypes, removed tons of #include's, i18n fixes, s/w/widget/ as above, indentation, ...
1999-07-23 00:21:10 +08:00
gimp_fatal_error (_("add_segment(): Unable to reallocate segment array in iscissors."));
1997-11-25 06:05:25 +08:00
}
if (*num_segs)
{
segs[*num_segs].x1 = segs[*num_segs - 1].x2;
segs[*num_segs].y1 = segs[*num_segs - 1].y2;
}
else if (first)
{
segs[0].x1 = x;
segs[0].y1 = y;
}
segs[*num_segs].x2 = x;
segs[*num_segs].y2 = y;
if (! *num_segs && first)
first = 0;
else
{
(*num_segs)++;
first = 1;
}
return 1;
}
1997-11-25 06:05:25 +08:00
static int
add_point (int *num_pts,
int kink,
int x,
int y,
double *normal)
{
if (*num_pts >= max_pts)
{
max_pts += DEFAULT_MAX_INC;
pts = (Point *) g_realloc ((void *) pts, sizeof (Point) * max_pts);
if (!pts)
new ui for the "Layer Offset" dialog. 1999-07-22 Michael Natterer <mitschel@cs.tu-berlin.de> * app/channel_ops.[ch]: new ui for the "Layer Offset" dialog. * app/channels_dialog.c * app/layers_dialog.c: major code cleanup: Folded some callbacks into common ones, "widget" instead of "w", indentation, ... * app/commands.c * app/interface.[ch] * app/global_edit.c: the query boxes must be shown by the caller now. There's no need to split up the string for the message box manually as the Gtk 1.2 label widget handles newlines corectly. Added the "edge_lock" toggle to the "Shrink Selection" dialog. Nicer spacings for the query and message boxes. * app/ink.c: tried to grab the pointer in the blob preview but failed. Left the code there as a reminder (commented out). * app/menus.c: reordered <Image>/Select. I was bored and grep-ed the sources for ancient or deprecated stuff: * app/about_dialog.[ch] * app/actionarea.[ch] * app/app_procs.c * app/brush_edit.c * app/brush_select.c * app/color_select.c * app/convert.c * app/devices.c * app/gdisplay.c * app/gdisplay_ops.c * app/histogram_tool.[ch] * app/info_window.c * app/install.c * app/ops_buttons.c * app/palette.c * app/palette_select.c * app/paths_dialog.c * app/pattern_select.c * app/resize.c * app/scale_toolc.c * app/text_tool.c: s/container_border_width/container_set_border_width/g, s/sprintf/g_snprintf/g, replaced some constant string lengths with strlen(x). * app/bezier_select.c * app/blend.c * app/boundary.c * app/errors.[ch] * app/free_select.c * app/gimpbrushlist.c * app/gimprc.c * app/iscissors.c * app/main.c * app/patterns.[ch] * app/text_tool.c: namespace fanaticism: prefixed all gimp error functions with "gimp_" and formated the messages more uniformly. * app/gradient.c * app/gradient_select.c: same stuff as above for the ui code. There are still some sub-dialogs which need cleanup. Did some cleanup in most of these files: prototypes, removed tons of #include's, i18n fixes, s/w/widget/ as above, indentation, ...
1999-07-23 00:21:10 +08:00
gimp_fatal_error (_("add_point(): Unable to reallocate points array in iscissors."));
1997-11-25 06:05:25 +08:00
}
pts[*num_pts].x = x;
pts[*num_pts].y = y;
pts[*num_pts].kink = kink;
pts[*num_pts].normal[0] = normal[0];
pts[*num_pts].normal[1] = normal[1];
(*num_pts)++;
return 1;
}
static void
CR_compose (CRMatrix a,
CRMatrix b,
CRMatrix 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 void
normalize (double *vec)
{
double length;
length = sqrt (SQR (vec[0]) + SQR (vec[1]));
if (length)
{
vec[0] /= length;
vec[1] /= length;
}
}
static double
dotprod (double *vec1,
double *vec2)
{
double val;
val = vec1[0] * vec2[0] + vec1[1] * vec2[1];
return val;
}
static Kink *
get_kink (Kink *kinks,
int index,
int num_kinks)
{
if (index >= 0 && index < num_kinks)
return kinks + index;
else if (index < 0)
{
while (index < 0)
index += num_kinks;
return kinks + index;
}
else
{
while (index >= num_kinks)
index -= num_kinks;
return kinks + index;
}
/* I don't think it ever gets to this point -- Rockwalrus */
1997-11-25 06:05:25 +08:00
return NULL;
}
static int
find_next_kink (Kink *kinks,
int num_kinks,
int this)
{
if (this >= num_kinks)
return 0;
do {
this++;
} while (! kinks[this].is_a_kink);
return this;
}
static double
find_distance (Kink *kinks,
int this,
int next)
{
double dist = 0.0;
double dx, dy;
while (this != next)
{
dx = kinks[this].x - kinks[this + 1].x;
dy = kinks[this].y - kinks[this + 1].y;
dist += sqrt (SQR (dx) + SQR (dy));
this ++;
}
return dist;
}
static int
go_distance (Kink *kinks,
int this,
double dist,
double *x,
double *y)
{
double dx, dy;
double length = 0.0;
double t = 2.0;
dx = dy = 0.0;
if (dist == 0.0)
{
*x = kinks[this].x;
*y = kinks[this].y;
return 1;
}
while (dist > 0.0)
{
dx = kinks[this + 1].x - kinks[this].x;
dy = kinks[this + 1].y - kinks[this].y;
length = sqrt (SQR (dx) + SQR (dy));
dist -= length;
if (dist > 0.0)
this++;
}
t = (length + dist) / length;
*x = kinks[this].x + t * dx;
*y = kinks[this].y + t * dy;
return this;
}
static int
travel_length (Kink *kinks,
int num_kinks,
int start,
int dir,
int dist)
{
double dx, dy;
Kink * k1, * k2;
double distance = dist;
int length = 0;
while (distance > 0)
{
k1 = get_kink (kinks, start, num_kinks);
k2 = get_kink (kinks, start+dir, num_kinks);
dx = k2->x - k1->x;
dy = k2->y - k1->y;
distance -= sqrt (SQR (dx) + SQR (dy));
start += dir;
length += dir;
}
/* backup one step and return value */
return length;
}
static int
find_edge_xy (TempBuf *edge_buf,
int dir,
double x,
double y,
double *edge)
{
double dx, dy;
int ix, iy;
int xx, yy;
int rowstride, bytes;
int d11, d12, d21, d22;
unsigned char * data;
int b;
int threshold = (int) iscissors_options->threshold;
1997-11-25 06:05:25 +08:00
bytes = edge_buf->bytes;
rowstride = bytes * edge_buf->width;
x -= edge_buf->x;
y -= edge_buf->y;
ix = (int) (x + 2) - 2;
iy = (int) (y + 2) - 2;
/* If we're scouting out of bounds, return 0 */
if (ix < 0 || ix >= edge_buf->width ||
iy < 0 || iy >= edge_buf->height)
{
edge[0] = EDGE_STRENGTH;
return 1;
}
if (dir > 0)
{
dx = x - ix;
dy = y - iy;
}
else
{
dx = 1 - (x - ix);
dy = 1 - (y - iy);
}
data = temp_buf_data (edge_buf) + iy * rowstride + ix * bytes;
for (b = 0; b < bytes; b++)
{
if (dir > 0)
{
xx = ((ix + 1) >= edge_buf->width) ? 0 : bytes;
yy = ((iy + 1) >= edge_buf->height) ? 0 : rowstride;
}
else
{
xx = ((ix - 1) < 0) ? 0 : -bytes;
yy = ((iy - 1) < 0) ? 0 : -rowstride;
}
d11 = (data[0] > threshold) ? data[0] : 0;
d12 = (data[xx] > threshold) ? data[xx] : 0;
d21 = (data[yy] > threshold) ? data[yy] : 0;
d22 = (data[xx + yy] > threshold) ? data[xx + yy] : 0;
edge[b] = BILINEAR (d11, d12, d21, d22, dx, dy);
data++;
}
if (edge[0] > 0.0)
return 1;
else
return 0;
}
static void
find_boundary (Tool *tool)
{
1997-11-25 06:05:25 +08:00
/* Find directional changes */
shape_of_boundary (tool);
/* Process the kinks */
process_kinks (tool);
/* Determine the initial boundary */
initial_boundary (tool);
/* Get the edge map from the boundary extents */
edge_map_from_boundary (tool);
/* Orient the boundary based on edge detection */
orient_boundary (tool);
/* Setup the points array for localization */
reset_boundary (tool);
/* Localize the boundary based on edge detection
* and inter-segment elasticity
*/
while (localize_boundary (tool)) ;
/* Post process the points array to fit non-edge-seeking
* boundary points into the scheme of things
*/
post_process_boundary (tool);
/* convert the boundary into a mask */
CR_convert ((Iscissors *) tool->private,
app/airbrush.c app/bezier_select.c app/blend.c app/brightness_contrast.c 1999-04-12 Michael Natterer <mitschel@cs.tu-berlin.de> * app/airbrush.c * app/bezier_select.c * app/blend.c * app/brightness_contrast.c * app/bucket_fill.c * app/by_color_select.c * app/clone.c * app/color_balance.c * app/color_picker.c * app/convolve.c * app/crop.c * app/curves.c * app/ellipse_select.c * app/eraser.c * app/flip_tool.c * app/free_select.c * app/fuzzy_select.c * app/histogram_tool.c * app/hue_saturation.c * app/ink.c * app/iscissors.c * app/levels.c * app/magnify.c * app/move.c * app/paintbrush.c * app/pencil.c * app/posterize.c * app/rect_select.[ch] * app/text_tool.c * app/threshold.c * app/transform_tool.c * app/tools.[ch] * app/toolsF.h: again: all tools :( * app/Makefile.am * app/tool_options.[ch] * app/selection_options.h * app/tool_options_ui.h: new files. Ok, this time it's general enough for future extensions: - The tool options structures are organized like the gtk object system to allow derived tool options. - Renamed all create and reset functions to *_options_new() and *_options_reset() to reflect this. - Changed tools_register() again. Now it takes just a pointer to a ToolOptions structure. - Moved almost the entire tool options gui code to tool_options.c. - Visually separated the common selection options from the tool-specific ones. I'd like to do the same with opacity/paint mode in all paint tool options but I think this needs some more discussion. * app/histogram_tool.c: changed packing boxes, label alignments. * app/paintbrush.c: some more sensitive settings. The gradient feature can now be toggled with a button. Hopefully didn't break anything.
1999-04-13 01:55:06 +08:00
(GDisplay *) tool->gdisp_ptr, FALSE);
1997-11-25 06:05:25 +08:00
}
static void
shape_of_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
Kink * kinks, * k;
double vec1[2], vec2[2], vec[2];
double std_dev;
double weight;
int left, right;
int i, j;
int resolution = (int) iscissors_options->resolution;
/* int x, y; */
1997-11-25 06:05:25 +08:00
/* This function determines the kinkiness at each point in the
* original free-hand curve by finding the dotproduct between
* the two vectors formed at each point from that point to its
* immediate neighbors. A smoothing function is applied to
* determine the vectors to ameliorate the otherwise excessive
* jitter associated with original selection.
*/
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
iscissors->num_kinks = iscissors->num_segs;
if (iscissors->kinks)
g_free (iscissors->kinks);
kinks = iscissors->kinks = (Kink *) g_malloc (sizeof (Kink) *
(iscissors->num_kinks + 1));
for (i = 0,j=0; i < iscissors->num_kinks; i++)
1997-11-25 06:05:25 +08:00
{
/* untransform coords */
gdisplay_untransform_coords (gdisp, segs[i].x1, segs[i].y1,
&kinks[j].x, &kinks[j].y, FALSE, TRUE);
/*
kinks[j].x = segs[i].x1;
kinks[j].y = segs[i].y1;
*/
if(j) {
if((kinks[j].x != kinks[j-1].x) || (kinks[j].y != kinks[j-1].y))
++j;
} else j++;
1997-11-25 06:05:25 +08:00
}
iscissors->num_kinks = j;
1997-11-25 06:05:25 +08:00
for (i = 0; i < iscissors->num_kinks; i++)
{
left = travel_length (kinks, iscissors->num_kinks, i, -1, resolution);
right = travel_length (kinks, iscissors->num_kinks, i, 1, resolution);
std_dev = sqrt (-(SQR (left)) / (2 * log (EPSILON)));
if (fabs (std_dev) < EPSILON) std_dev = 1.0;
vec1[0] = 0.0;
vec1[1] = 0.0;
for (j = left; j < 0; j++)
{
k = get_kink (kinks, i+j, iscissors->num_kinks);
vec[0] = k->x - kinks[i].x;
vec[1] = k->y - kinks[i].y;
normalize (vec);
weight = exp (-SQR(j+1) / (2 * SQR (std_dev)));
vec1[0] += weight * vec[0];
vec1[1] += weight * vec[1];
}
normalize (vec1);
std_dev = sqrt (-(SQR (right)) / (2 * log (EPSILON)));
if (fabs (std_dev) < EPSILON) std_dev = 1.0;
vec2[0] = 0.0;
vec2[1] = 0.0;
for (j = 1; j <= right; j++)
{
k = get_kink (kinks, i+j, iscissors->num_kinks);
vec[0] = k->x - kinks[i].x;
vec[1] = k->y - kinks[i].y;
normalize (vec);
weight = exp (-SQR(j-1) / (2 * SQR (std_dev)));
vec2[0] += weight * vec[0];
vec2[1] += weight * vec[1];
}
normalize (vec2);
/* determine the kinkiness based on the two vectors */
kinks[i].kinkiness = (G_PI - acos (dotprod (vec1, vec2)))/ G_PI;
1997-11-25 06:05:25 +08:00
kinks[i].normal[0] = (vec1[0] + vec2[0]) / 2.0;
kinks[i].normal[1] = (vec1[1] + vec2[1]) / 2.0;
/* if the average vector is zero length... */
if (kinks[i].normal[0] < EPSILON && kinks[i].normal[1] < EPSILON)
{
/* normal = 90 degree rotation of vec1 */
kinks[i].normal[0] = -vec1[1];
kinks[i].normal[1] = vec1[0];
}
normalize (kinks[i].normal);
}
}
static void
process_kinks (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
Kink * kinks, * k_left, * k_right;
/* int x, y; */
1997-11-25 06:05:25 +08:00
int i;
GimpDrawable *drawable;
1997-11-25 06:05:25 +08:00
gdisp = (GDisplay *) tool->gdisp_ptr;
drawable = gimage_active_drawable (gdisp->gimage);
1997-11-25 06:05:25 +08:00
iscissors = (Iscissors *) tool->private;
kinks = iscissors->kinks;
for (i = 0; i < iscissors->num_kinks; i++)
{
/*FIXME*/
kinks[i].x = BOUNDS (kinks[i].x, 0, (drawable_width(drawable) - 1));
kinks[i].y = BOUNDS (kinks[i].y, 0, (drawable_height(drawable) - 1));
1997-11-25 06:05:25 +08:00
/* get local maximums */
k_left = get_kink (kinks, i-1, iscissors->num_kinks);
k_right = get_kink (kinks, i+1, iscissors->num_kinks);
if ((kinks[i].kinkiness > k_left->kinkiness) &&
(kinks[i].kinkiness >= k_right->kinkiness) &&
(kinks[i].kinkiness > kink_thres))
kinks[i].is_a_kink = 1;
else
kinks[i].is_a_kink = 0;
}
}
static void
initial_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
Kink * kinks;
double x, y;
double dist;
double res;
double i_resolution = 1.0 / iscissors_options->resolution;
1997-11-25 06:05:25 +08:00
int i, n, this, next, k;
int num_pts = 0;
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
kinks = iscissors->kinks;
/* for a connected boundary, set up the last kink as the same
* x & y coordinates as the first
*/
kinks[iscissors->num_kinks].x = kinks[0].x;
kinks[iscissors->num_kinks].y = kinks[0].y;
kinks[iscissors->num_kinks].is_a_kink = 1;
this = 0;
while ((next = find_next_kink (kinks, iscissors->num_kinks, this)))
{
/* Find the distance in pixels from the current to
* the next kink
*/
dist = find_distance (kinks, this, next);
if (dist > 0.0)
{
/* Find the number of segments that should be created
* to fill the void
*/
n = (int) (dist * i_resolution);
1997-11-25 06:05:25 +08:00
res = dist / (double) (n + 1);
add_point (&num_pts, 1, kinks[this].x, kinks[this].y, kinks[this].normal);
for (i = 1; i <= n; i++)
{
k = go_distance (kinks, this, res * i, &x, &y);
add_point (&num_pts, 0, (int) x, (int) y, kinks[k].normal);
}
}
this = next;
}
iscissors->num_pts = num_pts;
}
static void
edge_map_from_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
unsigned char black[EDGE_WIDTH] = { 0 };
int x, y, w, h;
int x1, y1, x2, y2;
int i;
GimpDrawable *drawable;
1997-11-25 06:05:25 +08:00
1997-11-25 06:05:25 +08:00
gdisp = (GDisplay *) tool->gdisp_ptr;
drawable = gimage_active_drawable (gdisp->gimage);
1997-11-25 06:05:25 +08:00
iscissors = (Iscissors *) tool->private;
x = y = w = h = x1 = y1 = x2 = y2 = 0;
x1 = drawable_width(drawable);
y1 = drawable_height(drawable);
1997-11-25 06:05:25 +08:00
/* Find the edge map extents */
for (i = 0; i < iscissors->num_pts; i++)
{
x = BOUNDS (pts[i].x - LOCALIZE_RADIUS, 0,
drawable_width(drawable));
1997-11-25 06:05:25 +08:00
y = BOUNDS (pts[i].y - LOCALIZE_RADIUS, 0,
drawable_height(drawable));
1997-11-25 06:05:25 +08:00
w = BOUNDS (pts[i].x + LOCALIZE_RADIUS, 0,
drawable_width(drawable));
1997-11-25 06:05:25 +08:00
h = BOUNDS (pts[i].y + LOCALIZE_RADIUS, 0,
drawable_height(drawable));
1997-11-25 06:05:25 +08:00
w -= x;
h -= y;
set_edge_map_blocks (gdisp->gimage, x, y, w, h);
if (x < x1)
x1 = x;
if (y < y1)
y1 = y;
if (x + w > x2)
x2 = x + w;
if (y + h > y2)
y2 = y + h;
}
1997-11-25 06:05:25 +08:00
/* construct the edge map */
iscissors->edge_buf = temp_buf_new ((x2 - x1), (y2 - y1),
EDGE_WIDTH, x1, y1, black);
construct_edge_map (tool, iscissors->edge_buf);
}
static void
orient_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
int e1, e2;
double dx1, dy1, dx2, dy2;
double edge1[EDGE_WIDTH], edge2[EDGE_WIDTH];
double max;
double angle;
int dir = 0;
1997-11-25 06:05:25 +08:00
int i, j;
int max_dir;
int max_orient;
int found;
max_dir = 0;
max_orient = 0;
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
for (i = 0; i < iscissors->num_pts; i++)
{
/* Search for the closest edge */
j = 0;
max = 0.0;
found = 0;
angle = atan2 (pts[i].normal[1], pts[i].normal[0]);
dir = ((angle > -3 * G_PI_4) && (angle < G_PI_4)) ? 1 : -1;
1997-11-25 06:05:25 +08:00
while (j < LOCALIZE_RADIUS && !found)
{
dx1 = pts[i].x + pts[i].normal[0] * j;
dy1 = pts[i].y + pts[i].normal[1] * j;
e1 = find_edge_xy (iscissors->edge_buf, dir, dx1, dy1, edge1);
dx2 = pts[i].x - pts[i].normal[0] * j;
dy2 = pts[i].y - pts[i].normal[1] * j;
e2 = find_edge_xy (iscissors->edge_buf, -dir, dx2, dy2, edge2);
e1 = e2 = 0;
if (e1 && e2)
{
if (edge1[0] > edge2[0])
pts[i].dir = dir;
else
{
pts[i].normal[0] *= -1;
pts[i].normal[1] *= -1;
pts[i].dir = -dir;
}
found = 1;
}
else if (e1)
{
pts[i].dir = dir;
found = 1;
}
else if (e2)
{
pts[i].dir = -dir;
pts[i].normal[0] *= -1;
pts[i].normal[1] *= -1;
found = 1;
}
else
{
if (edge1[0] > max)
{
max = edge1[0];
max_orient = 1;
max_dir = dir;
}
if (edge2[0] > max)
{
max = edge2[0];
max_orient = -1;
max_dir = -dir;
}
}
j++;
}
if (!found && max > miss_thres)
{
pts[i].normal[0] *= max_orient;
pts[i].normal[1] *= max_orient;
pts[i].dir = max_dir;
}
else if (!found)
{
pts[i].normal[0] = 0.0;
pts[i].normal[1] = 0.0;
pts[i].dir = 0;
}
}
}
static void
reset_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
double edge[EDGE_WIDTH];
int i;
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
for (i = 0; i < iscissors->num_pts; i++)
{
if (pts[i].dir == 0)
pts[i].stable = 1;
else if (find_edge_xy (iscissors->edge_buf,
pts[i].dir, pts[i].x, pts[i].y, edge))
pts[i].stable = 1;
else
pts[i].stable = 0;
pts[i].dx = pts[i].x;
pts[i].dy = pts[i].y;
}
}
static int
localize_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
double x, y;
double dx, dy;
double max;
double d_l, d_r;
double edge[EDGE_WIDTH];
int i, left, right;
int moved = 0;
double elasticity = iscissors_options->elasticity + 1.0;
1997-11-25 06:05:25 +08:00
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
/* this function lets the boundary crawl in its desired
* direction, but within limits set by the elasticity
* variable. The process is incremental, so this function
* needs to be repeatedly called until there is no discernable
* movement
*/
for (i = 0; i < iscissors->num_pts; i++)
{
if (!pts[i].stable)
{
x = pts[i].dx + pts[i].normal[0];
y = pts[i].dy + pts[i].normal[1];
left = (i == 0) ? iscissors->num_pts - 1 : i - 1;
right = (i == (iscissors->num_pts - 1)) ? 0 : i + 1;
dx = x - pts[left].dx;
dy = y - pts[left].dy;
d_l = sqrt (SQR (dx) + SQR (dy));
dx = x - pts[right].dx;
dy = y - pts[right].dy;
d_r = sqrt (SQR (dx) + SQR (dy));
dx = pts[left].dx - pts[right].dx;
dy = pts[left].dy - pts[right].dy;
max = (sqrt (SQR (dx) + SQR (dy)) / 2.0) * elasticity;
1997-11-25 06:05:25 +08:00
/* If moving the point along it's directional vector
* still satisfies the elasticity constraints (OR)
* the point is a kink (in which case it can violate
* elasticity completely.
*/
if (((d_l < max) && (d_r < max)) || pts[i].kink)
{
pts[i].dx = x;
pts[i].dy = y;
if (find_edge_xy (iscissors->edge_buf, pts[i].dir, x, y, edge))
pts[i].stable = 1;
else
moved++;
}
}
}
return moved;
}
static void
post_process_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
int i;
int left, right;
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
/* Relocate all points which did not manage to seek an edge
* to the average of their edge-seeking neighbors
* Also relocate points which failed to reach a stable
* edge position. These cases indicate that the point
* somehow slipped through the cracks and is headed towards
* lands unknown and most likely undesired.
*/
for (i = 0; i < iscissors->num_pts; i++)
{
/* iff you uncomment this, change it to use the drawable width&height
pts[i].x = BOUNDS (pts[i].x, 0, (gdisp->gimage->width - 1));
pts[i].y = BOUNDS (pts[i].y, 0, (gdisp->gimage->height - 1));
pts[i].dx = BOUNDS (pts[i].dx, 0, (gdisp->gimage->width - 1));
pts[i].dy = BOUNDS (pts[i].dy, 0, (gdisp->gimage->height - 1));
*/
1997-11-25 06:05:25 +08:00
if (pts[i].dir == 0 || pts[i].stable == 0)
{
left = (i == 0) ? iscissors->num_pts - 1 : i - 1;
right = (i == (iscissors->num_pts - 1)) ? 0 : i + 1;
if (pts[left].stable && pts[right].stable)
{
pts[i].dx = (pts[left].dx + pts[right].dx) / 2.0;
pts[i].dy = (pts[left].dy + pts[right].dy) / 2.0;
}
}
}
/* connect the boundary */
pts[iscissors->num_pts].dx = pts[0].dx;
pts[iscissors->num_pts].dy = pts[0].dy;
}
static void
bezierify_boundary (Tool *tool)
{
Iscissors * iscissors;
GDisplay * gdisp;
CRMatrix geometry;
CRMatrix bezier_geom;
BezierPoint * bez_pts;
BezierPoint * new_pt;
BezierPoint * last_pt;
int indices[4];
int i, j, off_x, off_y;
1997-11-25 06:05:25 +08:00
gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private;
draw_core_stop (iscissors->core, tool);
1997-11-25 06:05:25 +08:00
if (iscissors->num_pts < 4)
{
g_message (_("Boundary contains < 4 points! Cannot bezierify."));
1997-11-25 06:05:25 +08:00
return;
}
bez_pts = NULL;
last_pt = NULL;
drawable_offsets (GIMP_DRAWABLE (gdisp->gimage->active_layer),
&off_x, &off_y);
1997-11-25 06:05:25 +08:00
for (i = 0; i < iscissors->num_pts; i ++)
{
indices[0] = (i < 3) ? (iscissors->num_pts + i - 3) : (i - 3);
indices[1] = (i < 2) ? (iscissors->num_pts + i - 2) : (i - 2);
indices[2] = (i < 1) ? (iscissors->num_pts + i - 1) : (i - 1);
indices[3] = i;
for (j = 0; j < 4; j++)
{
geometry[j][0] = pts[indices[j]].dx + off_x;
geometry[j][1] = pts[indices[j]].dy + off_y;
1997-11-25 06:05:25 +08:00
geometry[j][2] = 0;
geometry[j][3] = 0;
}
CR_compose (CR_bezier_basis, geometry, bezier_geom);
for (j = 0; j < 3; j++)
{
new_pt = (BezierPoint *) g_malloc (sizeof (BezierPoint));
if (last_pt) last_pt->next = new_pt;
else bez_pts = new_pt;
new_pt->type = (j == 0) ? BEZIER_ANCHOR : BEZIER_CONTROL;
new_pt->x = bezier_geom[j][0];
new_pt->y = bezier_geom[j][1];
new_pt->next = NULL;
new_pt->prev = last_pt;
last_pt = new_pt;
}
}
/* final anchor point */
last_pt->next = bez_pts;
bez_pts->prev = last_pt;
/* Load this curve into the bezier tool */
bezier_select_load (gdisp, bez_pts, iscissors->num_pts * 3, 1);
iscissors->state = FREE_SELECT_MODE;
last_tool = NULL;
/* iscissors_reset (iscissors);
*/
1997-11-25 06:05:25 +08:00
}
static TempBuf *
calculate_edge_map (GImage *gimage,
int x,
int y,
int w,
int h)
{
TempBuf * edge_map;
PixelRegion srcPR, destPR;
int width, height;
int offx, offy;
int i, j;
int x1, y1, x2, y2;
double gradient;
double dx, dy;
int xx, yy;
unsigned char *gr, * dh, * dv, * cm;
int hmax, vmax;
int b;
1997-11-25 06:05:25 +08:00
double prev, next;
GimpDrawable *drawable;
void *pr;
drawable = gimage_active_drawable (gimage);
1997-11-25 06:05:25 +08:00
x1 = y1 = x2 = y2 = 0;
/* allocate the new edge map */
edge_map = temp_buf_new (w, h, EDGE_WIDTH, x, y, NULL);
/* calculate the extent of the search make a 1 pixel border */
x1 = BOUNDS (x, 0, drawable_width(drawable));
y1 = BOUNDS (y, 0, drawable_height(drawable));
x2 = BOUNDS (x + w, 0, drawable_width(drawable));
y2 = BOUNDS (y + h, 0, drawable_height(drawable));
1997-11-25 06:05:25 +08:00
width = x2 - x1;
height = y2 - y1;
offx = (x - x1);
offy = (y - y1);
/* Set the drawable up as the source pixel region */
/*srcPR.bytes = drawable_bytes (drawable);
1997-11-25 06:05:25 +08:00
srcPR.w = width;
srcPR.h = height;
srcPR.rowstride = gimage->width * drawable_bytes (drawable);
srcPR.data = drawable_data (drawable) + y1 * srcPR.rowstride + x1 * srcPR.bytes;*/
pixel_region_init(&srcPR, drawable_data(drawable), x1, y1, width, height, 1);
1997-11-25 06:05:25 +08:00
/* Get the horizontal derivative */
destPR.data = conv1 /*+ MAX_CHANNELS * (CONV_WIDTH * offy + offx)*/;
1997-11-25 06:05:25 +08:00
destPR.rowstride = CONV_WIDTH * MAX_CHANNELS;
destPR.tiles = NULL;
destPR.bytes = MAX_CHANNELS;
destPR.x = x1;
destPR.y = y1;
destPR.w = CONV_WIDTH;
destPR.h = CONV_HEIGHT;
destPR.dirty = 1;
for (pr =pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
gaussian_deriv (&srcPR, &destPR, HORIZONTAL, std_dev);
1997-11-25 06:05:25 +08:00
/* Get the vertical derivative */
destPR.data = conv2 + MAX_CHANNELS * (CONV_WIDTH * offy + offx);
for (pr =pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
gaussian_deriv (&srcPR, &destPR, VERTICAL, std_dev);
1997-11-25 06:05:25 +08:00
/* fill in the edge map */
for (i = 0; i < height; i++)
{
gr = grad + (CONV_WIDTH + 2) * (i+1) + 1;
dh = conv1 + destPR.rowstride * i;
dv = conv2 + destPR.rowstride * i;
for (j = 0; j < width; j++)
{
hmax = dh[0] - 128;
vmax = dv[0] - 128;
for (b = 1; b < drawable_bytes (drawable); b++)
1997-11-25 06:05:25 +08:00
{
if (abs (dh[b] - 128) > abs (hmax))
hmax = dh[b] - 128;
if (abs (dv[b] - 128) > abs (vmax))
vmax = dv[b] - 128;
}
1997-11-25 06:05:25 +08:00
/* store the information in the edge map */
dh[0] = hmax + 128;
dv[0] = vmax + 128;
/* Find the gradient */
gradient = sqrt (SQR (hmax) + SQR (vmax));
/* Make the edge gradient map extend one pixel further */
if (j == 0)
gr[-1] = (unsigned char) gradient;
if (j == (width - 1))
gr[+1] = (unsigned char) gradient;
*gr++ = (unsigned char) gradient;
dh += srcPR.bytes;
dv += srcPR.bytes;
}
}
/* Make the edge gradient map extend one row further */
memcpy (grad, grad + (CONV_WIDTH+2), (CONV_WIDTH+2));
1997-11-25 06:05:25 +08:00
memcpy (grad + (CONV_WIDTH+2) * (CONV_HEIGHT+1),
grad + (CONV_WIDTH+2) * (CONV_HEIGHT),
(CONV_WIDTH+2));
cm = temp_buf_data (edge_map);
for (i = 0; i < h; i++)
{
gr = grad + (CONV_WIDTH+2)*(i + offy + 1) + (offx + 1);
dh = conv1 + destPR.rowstride*(i + offy) + srcPR.bytes * offx;
dv = conv2 + destPR.rowstride*(i + offy) + srcPR.bytes * offx;
for (j = 0; j < w; j++)
{
dx = (double) (dh[0] - 128) / 128.0;
dy = (double) (dv[0] - 128) / 128.0;
xx = (dx > 0) ? 1 : -1;
yy = (dy > 0) ? (CONV_WIDTH + 2) : -(CONV_WIDTH + 2);
dx = fabs (dx);
dy = fabs (dy);
prev = BILINEAR (gr[0], gr[-xx], gr[-yy], gr[-xx -yy], dx, dy);
next = BILINEAR (gr[0], gr[xx], gr[yy], gr[xx + yy], dx, dy);
if (gr[0] >= prev && gr[0] >= next)
*cm++ = gr[0];
else
*cm++ = 0;
/*cm++ = dh[0];*/
/*cm++ = dv[0];*/
1997-11-25 06:05:25 +08:00
dh += srcPR.bytes;
dv += srcPR.bytes;
gr ++;
}
}
return edge_map;
1997-11-25 06:05:25 +08:00
}
static void
construct_edge_map (Tool *tool,
TempBuf *edge_buf)
{
TempBuf * block;
int index;
int x, y;
int endx, endy;
int row, col;
int offx, offy;
int x2, y2;
long sboffset;
long dboffset;
1997-11-25 06:05:25 +08:00
PixelRegion srcPR, destPR;
1998-03-12 14:43:44 +08:00
/*#define ISCISSORS_STILL_DOES_NOT_WORK */
#ifdef ISCISSORS_STILL_DOES_NOT_WORK
FILE *dump;
#endif
1997-11-25 06:05:25 +08:00
/* init some variables */
srcPR.bytes = edge_buf->bytes;
destPR.rowstride = edge_buf->bytes * edge_buf->width;
destPR.x = 0 /*edge_buf->x*/;
destPR.y = 0 /*edge_buf->y*/;
destPR.h = edge_buf->height;
destPR.w = edge_buf->width;
destPR.bytes = edge_buf->bytes;
srcPR.tiles = destPR.tiles = NULL;
1997-11-25 06:05:25 +08:00
y = edge_buf->y;
endx = edge_buf->x + edge_buf->width;
endy = edge_buf->y + edge_buf->height;
row = (y / BLOCK_HEIGHT);
/* patch the buffer with the saved portions of the image */
while (y < endy)
{
x = edge_buf->x;
col = (x / BLOCK_WIDTH);
/* calculate y offset into this row of blocks */
offy = (y - row * BLOCK_HEIGHT);
1997-11-25 06:05:25 +08:00
y2 = (row + 1) * BLOCK_HEIGHT;
if (y2 > endy) y2 = endy;
srcPR.h = y2 - y;
while (x < endx)
{
index = row * horz_blocks + col;
block = edge_map_blocks [index];
/* If the block exists, patch it into buf */
if (block)
{
srcPR.x = block->x;
srcPR.y = block->y;
/* calculate x offset into the block */
1997-11-25 06:05:25 +08:00
offx = (x - col * BLOCK_WIDTH);
x2 = (col + 1) * BLOCK_WIDTH;
if (x2 > endx) x2 = endx;
srcPR.w = x2 - x;
/* i Am going to special case this thing */
/* Calculate the offsets into source buffer */
1997-11-25 06:05:25 +08:00
srcPR.rowstride = srcPR.bytes * block->width;
sboffset = offy;
sboffset *= srcPR.rowstride;
sboffset += offx*srcPR.bytes;
srcPR.data = temp_buf_data (block) + sboffset;
/* Calculate offset into destination buffer */
dboffset = ((edge_buf->y > srcPR.y)?(0):(srcPR.y - edge_buf->y));
dboffset *= destPR.rowstride;
1998-02-15 07:35:56 +08:00
dboffset += ((edge_buf->x < srcPR.x)?((srcPR.x - edge_buf->x)*destPR.bytes):((edge_buf->x - srcPR.x)*destPR.bytes));
destPR.data = temp_buf_data (edge_buf) + dboffset;
1998-01-31 17:13:49 +08:00
/* look at this debuggin info.
printf("Pixel region dump (Y %d %d) X %d %d\n", y, endy, x, endx);
printf("index(%d) X: %d Y: %d ox: %d oy: %d \n", index, x, y, offx, offy);
printf("soff: %d doff: %d\n",sboffset,dboffset);
printf("s.x:%d s.y:%d s.w:%d s.h:%d s.rs:%d s.b%d\n",srcPR.x, srcPR.y, srcPR.w, srcPR.h,srcPR.rowstride, srcPR.bytes);
printf("d.x:%d d.y:%d d.w:%d d.h:%d d.rs:%d d.b%d\n",destPR.x,destPR.y,destPR.w,destPR.h,destPR.rowstride, destPR.bytes);
printf("e.x:%d e.y:%d e.w:%d e.h:%d\n",edge_buf->x,edge_buf->y,edge_buf->width,edge_buf->height);
1998-01-31 17:13:49 +08:00
printf("sdata:%d ddata:%d\n",srcPR.data, destPR.data);
printf("bdata:%d edata:%d\n", block->data, edge_buf->data);
if((dboffset + (srcPR.h*destPR.rowstride)) > (edge_buf->height * edge_buf -> width)) printf ("ERROR\n");
*/
if(!((dboffset + (srcPR.h*destPR.rowstride)) >
(edge_buf->height * edge_buf -> width)))
copy_region (&srcPR, &destPR);
1997-11-25 06:05:25 +08:00
}
col ++;
x = col * BLOCK_WIDTH;
1997-11-25 06:05:25 +08:00
}
row ++;
y = row * BLOCK_HEIGHT;
}
1998-03-12 14:43:44 +08:00
#ifdef ISCISSORS_STILL_DOES_NOT_WORK
/* dump the edge buffer for debugging*/
dump=fopen("dump", "wb");
fprintf(dump, "P5\n%d %d\n255\n", edge_buf->width, edge_buf->height);
fwrite(edge_buf->data, edge_buf->width * edge_buf->height, sizeof (guchar), dump);
1998-03-12 14:43:44 +08:00
fclose (dump);
#endif
1997-11-25 06:05:25 +08:00
}
/* edge map blocks utility functions */
static void
set_edge_map_blocks (void *gimage_ptr,
int x,
int y,
int w,
int h)
{
GImage * gimage;
int endx, endy;
int startx;
int index;
int x1, y1;
int x2, y2;
int row, col;
int width, height;
GimpDrawable *drawable;
1997-11-25 06:05:25 +08:00
width = height = 0;
gimage = (GImage *) gimage_ptr;
drawable = gimage_active_drawable (gimage);
width = drawable_width(drawable);
height = drawable_height(drawable);
1997-11-25 06:05:25 +08:00
startx = x;
endx = x + w;
endy = y + h;
row = y / BLOCK_HEIGHT;
while (y < endy)
{
col = x / BLOCK_WIDTH;
while (x < endx)
{
index = row * horz_blocks + col;
/* If the block doesn't exist, create and initialize it */
if (! edge_map_blocks [index])
{
/* determine memory efficient width and height of block */
x1 = col * BLOCK_WIDTH;
x2 = BOUNDS (x1 + BLOCK_WIDTH, 0, width);
w = (x2 - x1);
y1 = row * BLOCK_HEIGHT;
y2 = BOUNDS (y1 + BLOCK_HEIGHT, 0, height);
h = (y2 - y1);
/* calculate a edge map for the specified portion of the gimage */
edge_map_blocks [index] = calculate_edge_map (gimage, x1, y1, w, h);
}
col++;
x = col * BLOCK_WIDTH;
}
row ++;
y = row * BLOCK_HEIGHT;
x = startx;
}
}
static void
allocate_edge_map_blocks (int block_width,
int block_height,
int image_width,
int image_height)
{
int num_blocks;
int i;
/* calculate the number of rows and cols in the edge map block grid */
horz_blocks = (image_width + block_width - 1) / block_width;
vert_blocks = (image_height + block_height - 1) / block_height;
/* Allocate the array */
num_blocks = horz_blocks * vert_blocks;
edge_map_blocks = (TempBuf **) g_malloc (sizeof (TempBuf *) * num_blocks);
/* Initialize the array */
for (i = 0; i < num_blocks; i++)
edge_map_blocks [i] = NULL;
}
static void
free_edge_map_blocks ()
{
int i;
int num_blocks;
if (!edge_map_blocks)
return;
num_blocks = vert_blocks * horz_blocks;
1997-11-25 06:05:25 +08:00
for (i = 0; i < num_blocks; i++)
if (edge_map_blocks [i]) {
/* printf("tbf: index %d %d ",i, num_blocks);
printf("X:%d ",edge_map_blocks[i]->x);
printf("Y:%d ",edge_map_blocks[i]->y);
printf("W:%d ",edge_map_blocks[i]->width);
printf("H:%d ",edge_map_blocks[i]->height);
printf("data:%d ",edge_map_blocks[i]->data);
printf("\n");
*/
1997-11-25 06:05:25 +08:00
temp_buf_free (edge_map_blocks [i]);
}
1997-11-25 06:05:25 +08:00
g_free (edge_map_blocks);
edge_map_blocks = NULL;
}
/*********************************************/
/* Functions for gaussian convolutions */
/*********************************************/
static void
gaussian_deriv (PixelRegion *input,
PixelRegion *output,
int type,
double std_dev)
{
long width, height;
unsigned char *dest, *dp;
unsigned char *src, *sp, *s;
int bytes;
int *buf, *b;
int chan;
int i, row, col;
int start, end;
int curve_array [9];
int sum_array [9];
int * curve;
int * sum;
int val;
int total;
int length;
int initial_p[MAX_CHANNELS], initial_m[MAX_CHANNELS];
length = 3; /* static for speed */
width = input->w;
height = input->h;
bytes = input->bytes;
/* initialize */
curve = curve_array + length;
sum = sum_array + length;
buf = g_malloc (sizeof (int) * MAXIMUM (width, height) * bytes);
if (type == VERTICAL)
{
make_curve_d (curve, sum, std_dev, length);
total = sum[0] * -2;
}
else
{
make_curve (curve, sum, std_dev, length);
total = sum[length] + curve[length];
}
src = input->data;
dest = output->data;
for (col = 0; col < width; col++)
{
sp = src;
dp = dest;
b = buf;
src += bytes;
dest += bytes;
for (chan = 0; chan < bytes; chan++)
{
initial_p[chan] = sp[chan];
initial_m[chan] = sp[(height-1) * input->rowstride + chan];
}
for (row = 0; row < height; row++)
{
start = (row < length) ? -row : -length;
end = (height <= (row + length)) ? (height - row - 1) : length;
for (chan = 0; chan < bytes; chan++)
{
s = sp + (start * input->rowstride) + chan ;
val = 0;
i = start;
if (start != -length)
val += initial_p[chan] * (sum[start] - sum[-length]);
while (i <= end)
{
val += *s * curve[i++];
s += input->rowstride;
}
if (end != length)
val += initial_m[chan] * (sum[length] + curve[length] - sum[end+1]);
*b++ = val / total;
}
sp += input->rowstride;
}
b = buf;
if (type == VERTICAL)
for (row = 0; row < height; row++)
{
for (chan = 0; chan < bytes; chan++)
{
b[chan] = b[chan] + 128;
if (b[chan] > 255)
dp[chan] = 255;
else if (b[chan] < 0)
dp[chan] = 0;
else
dp[chan] = b[chan];
}
b += bytes;
dp += output->rowstride;
}
else
for (row = 0; row < height; row++)
{
for (chan = 0; chan < bytes; chan++)
{
if (b[chan] > 255)
dp[chan] = 255;
else if (b[chan] < 0)
dp[chan] = 0;
else
dp[chan] = b[chan];
}
b += bytes;
dp += output->rowstride;
}
}
if (type == HORIZONTAL)
{
make_curve_d (curve, sum, std_dev, length);
total = sum[0] * -2;
}
else
{
make_curve (curve, sum, std_dev, length);
total = sum[length] + curve[length];
}
src = output->data;
dest = output->data;
for (row = 0; row < height; row++)
{
sp = src;
dp = dest;
b = buf;
src += output->rowstride;
dest += output->rowstride;
for (chan = 0; chan < bytes; chan++)
{
initial_p[chan] = sp[chan];
initial_m[chan] = sp[(width-1) * bytes + chan];
}
for (col = 0; col < width; col++)
{
start = (col < length) ? -col : -length;
end = (width <= (col + length)) ? (width - col - 1) : length;
for (chan = 0; chan < bytes; chan++)
{
s = sp + (start * bytes) + chan;
val = 0;
i = start;
if (start != -length)
val += initial_p[chan] * (sum[start] - sum[-length]);
while (i <= end)
{
val += *s * curve[i++];
s += bytes;
}
if (end != length)
val += initial_m[chan] * (sum[length] + curve[length] - sum[end+1]);
*b++ = val / total;
}
sp += bytes;
}
b = buf;
if (type == HORIZONTAL)
for (col = 0; col < width; col++)
{
for (chan = 0; chan < bytes; chan++)
{
b[chan] = b[chan] + 128;
if (b[chan] > 255)
dp[chan] = 255;
else if (b[chan] < 0)
dp[chan] = 0;
else
dp[chan] = b[chan];
}
b += bytes;
dp += bytes;
}
else
for (col = 0; col < width; col++)
{
for (chan = 0; chan < bytes; chan++)
{
if (b[chan] > 255)
dp[chan] = 255;
else if (b[chan] < 0)
dp[chan] = 0;
else
dp[chan] = b[chan];
}
b += bytes;
dp += bytes;
}
}
g_free (buf);
}
/*
* The equations: g(r) = exp (- r^2 / (2 * sigma^2))
* r = sqrt (x^2 + y ^2)
*/
static void
make_curve (int *curve,
int *sum,
double sigma,
int length)
{
double sigma2;
int i;
sigma2 = sigma * sigma;
curve[0] = 255;
for (i = 1; i <= length; i++)
{
curve[i] = (int) (exp (- (i * i) / (2 * sigma2)) * 255);
curve[-i] = curve[i];
}
sum[-length] = 0;
for (i = -length+1; i <= length; i++)
sum[i] = sum[i-1] + curve[i-1];
}
/*
* The equations: d_g(r) = -r * exp (- r^2 / (2 * sigma^2)) / sigma^2
* r = sqrt (x^2 + y ^2)
*/
static void
make_curve_d (int *curve,
int *sum,
double sigma,
int length)
{
double sigma2;
int i;
sigma2 = sigma * sigma;
curve[0] = 0;
for (i = 1; i <= length; i++)
{
curve[i] = (int) ((i * exp (- (i * i) / (2 * sigma2)) / sigma2) * 255);
curve[-i] = -curve[i];
}
sum[-length] = 0;
sum[0] = 0;
for (i = 1; i <= length; i++)
{
sum[-length + i] = sum[-length + i - 1] + curve[-length + i - 1];
sum[i] = sum[i - 1] + curve[i - 1];
}
}
/***********************************************/
/* Functions for Catmull-Rom area conversion */
/***********************************************/
static GSList ** CR_scanlines = NULL;
1997-11-25 06:05:25 +08:00
static int start_convert;
static int width, height;
static int lastx;
static int lasty;
static void
CR_convert (Iscissors *iscissors,
GDisplay *gdisp,
int antialias)
{
int indices[4];
1998-02-15 07:35:56 +08:00
GSList *list;
1997-11-25 06:05:25 +08:00
int draw_type;
1998-02-15 07:35:56 +08:00
int *vals, val;
1997-11-25 06:05:25 +08:00
int x, w;
int i, j;
int offx, offy;
PixelRegion maskPR;
unsigned char *buf, *b;
GimpDrawable *drawable;
drawable = gimage_active_drawable(gdisp->gimage);
1997-11-25 06:05:25 +08:00
vals = NULL;
/* destroy previous region */
if (iscissors->mask)
{
channel_delete (iscissors->mask);
iscissors->mask = NULL;
}
/* get the new mask's maximum extents */
if (antialias)
{
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);
buf = (unsigned char *) g_malloc (sizeof(unsigned char *) * width);
1997-11-25 06:05:25 +08:00
}
else
{
width = gdisp->gimage->width;
height = gdisp->gimage->height;
draw_type = IMAGE_COORDS;
buf = NULL;
vals = NULL;
1997-11-25 06:05:25 +08:00
}
/* create a new mask */
iscissors->mask = channel_new_mask (gdisp->gimage, gdisp->gimage->width,
1997-11-25 06:05:25 +08:00
gdisp->gimage->height);
/* allocate room for the scanlines */
CR_scanlines = g_malloc (sizeof (GSList *) * height);
1997-11-25 06:05:25 +08:00
/* zero out the scanlines */
for (i = 0; i < height; i++)
CR_scanlines[i] = NULL;
/* scan convert the curve */
start_convert = 1;
for (i = 0; i < iscissors->num_pts; i ++)
{
indices[0] = (i < 3) ? (iscissors->num_pts + i - 3) : (i - 3);
indices[1] = (i < 2) ? (iscissors->num_pts + i - 2) : (i - 2);
indices[2] = (i < 1) ? (iscissors->num_pts + i - 1) : (i - 1);
indices[3] = i;
iscissors_draw_CR (gdisp, iscissors, pts, indices, draw_type);
}
drawable_offsets(drawable, &offx, &offy);
pixel_region_init (&maskPR, iscissors->mask->drawable.tiles, 0, 0,
iscissors->mask->drawable.width,
iscissors->mask->drawable.height, TRUE);
1997-11-25 06:05:25 +08:00
1998-03-27 08:42:56 +08:00
for (i = 0; i < height-(offy*SUPERSAMPLE); i++)
1997-11-25 06:05:25 +08:00
{
list = CR_scanlines[i];
/* zero the vals array */
if (antialias && !(i % SUPERSAMPLE))
memset (vals, 0, width * sizeof (int));
while (list)
{
1998-03-27 08:42:56 +08:00
x = (long) list->data + offx;
if ( x < 0 ) x = 0;
1997-11-25 06:05:25 +08:00
list = list->next;
if (list)
{
w = (long) list->data - x;
if (w+x > width) w = width - x;
1997-11-25 06:05:25 +08:00
if (!antialias)
1998-03-27 08:42:56 +08:00
channel_add_segment (iscissors->mask, x, i+offy, w, 255);
1997-11-25 06:05:25 +08:00
else
for (j = 0; j < w; j++)
vals[j + x] += 255;
list = g_slist_next (list);
1997-11-25 06:05:25 +08:00
}
}
if (antialias && !((i+1) % SUPERSAMPLE))
{
b = buf;
for (j = 0; j < width; j += SUPERSAMPLE)
{
val = 0;
for (x = 0; x < SUPERSAMPLE; x++)
val += vals[j + x];
1997-11-25 06:05:25 +08:00
*b++ = (unsigned char) (val / SUPERSAMPLE2);
}
1998-03-27 08:42:56 +08:00
pixel_region_set_row (&maskPR, offx/*0*/, (i / SUPERSAMPLE)+offy, iscissors->mask->drawable.width-offx, buf);
}
1997-11-25 06:05:25 +08:00
g_slist_free (CR_scanlines[i]);
CR_scanlines[i] = NULL;
1997-11-25 06:05:25 +08:00
}
if (antialias)
g_free (vals);
g_free (CR_scanlines);
CR_scanlines = NULL;
}
static void
CR_convert_points (GdkPoint *points,
int npoints)
{
int i;
if (start_convert)
start_convert = 0;
else
CR_convert_line (CR_scanlines, lastx, lasty, points[0].x, points[0].y);
for (i = 0; i < (npoints - 1); i++)
{
CR_convert_line (CR_scanlines,
points[i].x, points[i].y,
points[i+1].x, points[i+1].y);
}
lastx = points[npoints-1].x;
lasty = points[npoints-1].y;
}
static void
CR_convert_line (GSList **scanlines,
int x1,
int y1,
int x2,
int y2)
1997-11-25 06:05:25 +08:00
{
int dx, dy;
int error, inc;
int tmp;
float 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 = (float) (y2 - y1) / (float) (x2 - x1);
x1 = x2 + (0 - y2) / slope;
y1 = 0;
}
}
if (y2 >= height)
{
if (y1 >= height)
return;
if (x2 == x1)
{
y2 = height;
}
else
{
slope = (float) (y2 - y1) / (float) (x2 - x1);
x2 = x1 + (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 = CR_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 = CR_insert_in_list (*scanlines, x1);
scanlines++;
error += dx;
if (error > 0)
{
error -= dy;
x1 += inc;
}
}
}
}
static GSList *
CR_insert_in_list (GSList *list,
int x)
1997-11-25 06:05:25 +08:00
{
GSList *orig = list;
GSList *rest;
1997-11-25 06:05:25 +08:00
if (!list)
return g_slist_prepend (list, (gpointer) ((long) x));
1997-11-25 06:05:25 +08:00
while (list)
{
rest = g_slist_next (list);
1997-11-25 06:05:25 +08:00
if (x < (long) list->data)
{
rest = g_slist_prepend (rest, list->data);
1997-11-25 06:05:25 +08:00
list->next = rest;
list->data = (gpointer) ((long) x);
return orig;
}
else if (!rest)
{
g_slist_append (list, (gpointer) ((long) x));
1997-11-25 06:05:25 +08:00
return orig;
}
list = g_slist_next (list);
1997-11-25 06:05:25 +08:00
}
return orig;
}