Commit a273905c authored by EDT 1999  Austin Donnelly's avatar EDT 1999 Austin Donnelly Committed by Austin Donnelly

all-singing, all-dancing iscissors. Now scan converts so you can actually

Tue Oct  5 14:02:07 EDT 1999  Austin Donnelly  <austin@gimp.org>

	* app/iscissors.c: all-singing, all-dancing iscissors.  Now
	    scan converts so you can actually select stuff.  Doesn't leak
	    tiles either.  Still have a problem with occasional segfault
	    and CRITICAL assertion failing on addition of anchor when
	    curve not closed.
	* app/scan_convert.c: add connecting list between blocks of points
	    so we actually have a closed polygon.
	* app/tool_options.c: iscissors has just the standard feather and
	    antialias options now.
parent a3ef8368
Tue Oct 5 14:02:07 EDT 1999 Austin Donnelly <austin@gimp.org>
* app/iscissors.c: all-singing, all-dancing iscissors. Now
scan converts so you can actually select stuff. Doesn't leak
tiles either. Still have a problem with occasional segfault
and CRITICAL assertion failing on addition of anchor when
curve not closed.
* app/scan_convert.c: add connecting list between blocks of points
so we actually have a closed polygon.
* app/tool_options.c: iscissors has just the standard feather and
antialias options now.
Mon Oct 4 19:13:39 PDT 1999 Manish Singh <yosh@gimp.org> Mon Oct 4 19:13:39 PDT 1999 Manish Singh <yosh@gimp.org>
* libgimp/color_display.h * libgimp/color_display.h
......
...@@ -23,6 +23,13 @@ ...@@ -23,6 +23,13 @@
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
#ifdef DEBUG
#define TRC(x) printf x
#else
#define TRC(x)
#endif
/* Reveal our private structure */ /* Reveal our private structure */
struct ScanConverterPrivate struct ScanConverterPrivate
{ {
...@@ -113,7 +120,6 @@ convert_segment (ScanConverter *sc, ...@@ -113,7 +120,6 @@ convert_segment (ScanConverter *sc,
} }
else else
{ {
printf ("%d ===================== %d\n", x1, x2);
/* horizontal line */ /* horizontal line */
scanlines[y1] = insert_into_sorted_list (scanlines[y1], ROUND (x1)); scanlines[y1] = insert_into_sorted_list (scanlines[y1], ROUND (x1));
scanlines[y1] = insert_into_sorted_list (scanlines[y1], ROUND (x2)); scanlines[y1] = insert_into_sorted_list (scanlines[y1], ROUND (x2));
...@@ -168,6 +174,19 @@ scan_converter_add_points (ScanConverter *sc, ...@@ -168,6 +174,19 @@ scan_converter_add_points (ScanConverter *sc,
sc->first = pointlist[0]; sc->first = pointlist[0];
} }
/* link from previous point */
if (sc->got_last && npoints > 0)
{
TRC (("|| %g,%g -> %g,%g\n",
sc->last.x, sc->last.y,
pointlist[0].x, pointlist[0].y));
convert_segment (sc,
(int)sc->last.x * antialias,
(int)sc->last.y * antialias,
(int)pointlist[0].x * antialias,
(int)pointlist[0].y * antialias);
}
for (i = 0; i < (npoints - 1); i++) for (i = 0; i < (npoints - 1); i++)
{ {
convert_segment (sc, convert_segment (sc,
...@@ -177,6 +196,10 @@ scan_converter_add_points (ScanConverter *sc, ...@@ -177,6 +196,10 @@ scan_converter_add_points (ScanConverter *sc,
(int) pointlist[i + 1].y * antialias); (int) pointlist[i + 1].y * antialias);
} }
TRC (("[] %g,%g -> %g,%g\n",
pointlist[0].x, pointlist[0].y,
pointlist[npoints-1].x, pointlist[npoints-1].y));
if (npoints > 0) if (npoints > 0)
{ {
sc->got_last = TRUE; sc->got_last = TRUE;
...@@ -233,13 +256,13 @@ scan_converter_to_channel (ScanConverter *sc, ...@@ -233,13 +256,13 @@ scan_converter_to_channel (ScanConverter *sc,
for(i=0; i<heighta; i++) for(i=0; i<heighta; i++)
{ {
list = sc->scanlines[i]; list = sc->scanlines[i];
printf ("%03d: ", i); TRC (("%03d: ", i));
while (list) while (list)
{ {
printf ("%3d ", GPOINTER_TO_INT (list->data)); TRC (("%3d ", GPOINTER_TO_INT (list->data)));
list = g_slist_next (list); list = g_slist_next (list);
} }
printf ("\n"); TRC (("\n"));
} }
pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)), 0, 0, pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)), 0, 0,
......
...@@ -333,11 +333,11 @@ selection_options_init (SelectionOptions *options, ...@@ -333,11 +333,11 @@ selection_options_init (SelectionOptions *options,
{ {
case FREE_SELECT: case FREE_SELECT:
case BEZIER_SELECT: case BEZIER_SELECT:
case ISCISSORS:
break; break;
case RECT_SELECT: case RECT_SELECT:
case ELLIPSE_SELECT: case ELLIPSE_SELECT:
case FUZZY_SELECT: case FUZZY_SELECT:
case ISCISSORS:
case BY_COLOR_SELECT: case BY_COLOR_SELECT:
separator = gtk_hseparator_new (); separator = gtk_hseparator_new ();
gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
......
...@@ -52,10 +52,18 @@ ...@@ -52,10 +52,18 @@
#include "temp_buf.h" #include "temp_buf.h"
#include "tools.h" #include "tools.h"
#include "bezier_selectP.h" #include "bezier_selectP.h"
#include "scan_convert.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
#include "libgimp/gimpmath.h" #include "libgimp/gimpmath.h"
#ifdef DEBUG
#define TRC(x) printf x
#else
#define TRC(x)
#endif
/* local structures */ /* local structures */
typedef struct _ICurve ICurve; typedef struct _ICurve ICurve;
...@@ -116,18 +124,6 @@ typedef struct _IScissorsOptions IScissorsOptions; ...@@ -116,18 +124,6 @@ typedef struct _IScissorsOptions IScissorsOptions;
struct _IScissorsOptions struct _IScissorsOptions
{ {
SelectionOptions selection_options; SelectionOptions selection_options;
double resolution;
double resolution_d;
GtkObject *resolution_w;
double threshold;
double threshold_d;
GtkObject *threshold_w;
double elasticity;
double elasticity_d;
GtkObject *elasticity_w;
}; };
...@@ -204,27 +200,12 @@ static int move [8][2] = ...@@ -204,27 +200,12 @@ static int move [8][2] =
/* points for drawing curves */ /* points for drawing curves */
static GdkPoint curve_points [MAX_POINTS]; static GdkPoint curve_points [MAX_POINTS];
/* cost map blocks variables */
static TempBuf ** cost_map_blocks = NULL;
static int horz_blocks;
static int vert_blocks;
/* temporary convolution buffers -- */ /* temporary convolution buffers -- */
static guint32 sentinel0 = 0xd0d0d0d0;
static unsigned char maxgrad_conv0 [TILE_WIDTH * TILE_HEIGHT * 4] = ""; static unsigned char maxgrad_conv0 [TILE_WIDTH * TILE_HEIGHT * 4] = "";
static guint32 sentinel1 = 0xd1d1d1d1;
static unsigned char maxgrad_conv1 [TILE_WIDTH * TILE_HEIGHT * 4] = ""; static unsigned char maxgrad_conv1 [TILE_WIDTH * TILE_HEIGHT * 4] = "";
static guint32 sentinel2 = 0xd2d2d2d2;
static unsigned char maxgrad_conv2 [TILE_WIDTH * TILE_HEIGHT * 4] = ""; static unsigned char maxgrad_conv2 [TILE_WIDTH * TILE_HEIGHT * 4] = "";
static guint32 sentinel3 = 0xd3d3d3d3;
/* static unsigned char cost_conv0 [CONV_WIDTH * CONV_HEIGHT * 3];*/
static guint32 sentinel4 = 0xd4d4d4d4;
static unsigned char cost_conv1 [CONV_WIDTH * CONV_HEIGHT * 3] = "";
static guint32 sentinel5 = 0xd5d5d5d5;
static unsigned char cost_conv2 [CONV_WIDTH * CONV_HEIGHT * 3] = "";
static guint32 sentinel6 = 0xd6d6d6d6;
static int horz_deriv [9] = static int horz_deriv [9] =
{ {
...@@ -262,6 +243,8 @@ static float distance_weights [GRADIENT_SEARCH * GRADIENT_SEARCH]; ...@@ -262,6 +243,8 @@ static float distance_weights [GRADIENT_SEARCH * GRADIENT_SEARCH];
static int diagonal_weight [256]; static int diagonal_weight [256];
static int direction_value [256][4]; static int direction_value [256][4];
static gboolean initialized = FALSE; static gboolean initialized = FALSE;
static Tile *cur_tile = NULL;
/***********************************************************************/ /***********************************************************************/
/* static variables */ /* static variables */
...@@ -294,12 +277,6 @@ static void precalculate_arrays (void); ...@@ -294,12 +277,6 @@ static void precalculate_arrays (void);
static GPtrArray *plot_pixels (Iscissors *, TempBuf *, static GPtrArray *plot_pixels (Iscissors *, TempBuf *,
int, int, int, int, int, int); int, int, int, int, int, int);
static void
selection_scale_update (GtkAdjustment *adjustment,
double *scale_val)
{
*scale_val = adjustment->value;
}
static void static void
...@@ -308,13 +285,6 @@ iscissors_options_reset (void) ...@@ -308,13 +285,6 @@ iscissors_options_reset (void)
IScissorsOptions *options = iscissors_options; IScissorsOptions *options = iscissors_options;
selection_options_reset ((SelectionOptions *) options); 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);
} }
static IScissorsOptions * static IScissorsOptions *
...@@ -322,107 +292,11 @@ iscissors_options_new (void) ...@@ -322,107 +292,11 @@ iscissors_options_new (void)
{ {
IScissorsOptions *options; IScissorsOptions *options;
GtkWidget *vbox;
GtkWidget *abox;
GtkWidget *table;
GtkWidget *label;
GtkWidget *scale;
/* the new intelligent scissors tool options structure */ /* the new intelligent scissors tool options structure */
options = g_new (IScissorsOptions, 1); options = g_new (IScissorsOptions, 1);
selection_options_init ((SelectionOptions *) options, selection_options_init ((SelectionOptions *) options,
ISCISSORS, ISCISSORS,
iscissors_options_reset); iscissors_options_reset);
options->resolution = options->resolution_d = 40.0;
options->threshold = options->threshold_d = 15.0;
options->elasticity = options->elasticity_d = 0.30;
/* the main vbox */
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);
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);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
label = gtk_label_new (_("Resolution:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 0, 2,
GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (abox);
options->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",
(GtkSignalFunc) selection_scale_update,
&options->resolution);
gtk_widget_show (scale);
/* the threshold scale */
label = gtk_label_new (_("Edge Detect "));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
label = gtk_label_new (_("Threshold:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 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",
(GtkSignalFunc) selection_scale_update,
&options->threshold);
gtk_widget_show (scale);
/* the elasticity scale */
label = gtk_label_new (_("Elasticity:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
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));
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);
return options; return options;
} }
...@@ -471,7 +345,7 @@ tools_free_iscissors (Tool *tool) ...@@ -471,7 +345,7 @@ tools_free_iscissors (Tool *tool)
iscissors = (Iscissors *) tool->private; iscissors = (Iscissors *) tool->private;
printf("tools_free_iscissors\n"); TRC (("tools_free_iscissors\n"));
/* XXX? Undraw curve */ /* XXX? Undraw curve */
/*iscissors->draw = DRAW_CURVE;*/ /*iscissors->draw = DRAW_CURVE;*/
...@@ -560,11 +434,11 @@ iscissors_button_press (Tool *tool, ...@@ -560,11 +434,11 @@ iscissors_button_press (Tool *tool,
draw_core_resume (iscissors->core, tool); draw_core_resume (iscissors->core, tool);
grab_pointer = 1; grab_pointer = 1;
} }
#if 0
/* XXX not yet */
/* If the iscissors is connected, check if the click was inside */ /* If the iscissors is connected, check if the click was inside */
else if (iscissors->connected && iscissors->region && else if (iscissors->connected && iscissors->mask &&
gregion_point_inside (iscissors->region, iscissors->x, iscissors->y)) channel_value (iscissors->mask, iscissors->x, iscissors->y))
{ {
/* Undraw the curve */ /* Undraw the curve */
tool->state = INACTIVE; tool->state = INACTIVE;
...@@ -572,9 +446,9 @@ iscissors_button_press (Tool *tool, ...@@ -572,9 +446,9 @@ iscissors_button_press (Tool *tool,
draw_core_stop (iscissors->core, tool); draw_core_stop (iscissors->core, tool);
replace = 0; replace = 0;
if (bevent->state & ShiftMask) if (bevent->state & GDK_SHIFT_MASK)
op = ADD; op = ADD;
else if (bevent->state & ControlMask) else if (bevent->state & GDK_CONTROL_MASK)
op = SUB; op = SUB;
else else
{ {
...@@ -583,7 +457,7 @@ iscissors_button_press (Tool *tool, ...@@ -583,7 +457,7 @@ iscissors_button_press (Tool *tool,
} }
if (replace) if (replace)
selection_clear (gdisp->select, gdisp_ptr); gimage_mask_clear (gdisp->gimage);
else else
gimage_mask_undo (gdisp->gimage); gimage_mask_undo (gdisp->gimage);
...@@ -599,10 +473,10 @@ iscissors_button_press (Tool *tool, ...@@ -599,10 +473,10 @@ iscissors_button_press (Tool *tool,
iscissors_reset (iscissors); iscissors_reset (iscissors);
selection_start (gdisp->select, 0, True); selection_start (gdisp->select, TRUE);
} }
#endif /* 0 */
/* if we're not connected, we're adding a new point */ /* if we're not connected, we're adding a new point */
else if (!iscissors->connected) else if (!iscissors->connected)
{ {
...@@ -625,6 +499,54 @@ iscissors_button_press (Tool *tool, ...@@ -625,6 +499,54 @@ iscissors_button_press (Tool *tool,
} }
static void
iscissors_convert (Iscissors *iscissors, gpointer gdisp_ptr)
{
GDisplay *gdisp = (GDisplay *) gdisp_ptr;
ScanConverter *sc;
ScanConvertPoint *pts;
guint npts;
GSList *list;
ICurve *icurve;
guint packed;
int i;
int index;
sc = scan_converter_new (gdisp->gimage->width, gdisp->gimage->height, 1);
/* go over the curves in reverse order, adding the points we have */
list = iscissors->curves;
index = g_slist_length (list);
while (index)
{
index--;
icurve = (ICurve *) g_slist_nth_data (list, index);
npts = icurve->points->len;
pts = g_new (ScanConvertPoint, npts);
for (i=0; i < npts; i ++)
{
packed = GPOINTER_TO_INT (g_ptr_array_index (icurve->points, i));
pts[i].x = packed & 0x0000ffff;
pts[i].y = packed >> 16;
}
scan_converter_add_points (sc, npts, pts);
g_free (pts);
}
if (iscissors->mask)
channel_delete (iscissors->mask);
iscissors->mask = scan_converter_to_channel (sc, gdisp->gimage);
scan_converter_free (sc);
channel_invalidate_bounds (iscissors->mask);
}
static void static void
iscissors_button_release (Tool *tool, iscissors_button_release (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
...@@ -637,7 +559,7 @@ iscissors_button_release (Tool *tool, ...@@ -637,7 +559,7 @@ iscissors_button_release (Tool *tool,
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
iscissors = (Iscissors *) tool->private; iscissors = (Iscissors *) tool->private;
printf("iscissors_button_release\n"); TRC (("iscissors_button_release\n"));
/* Make sure X didn't skip the button release event -- as it's known /* Make sure X didn't skip the button release event -- as it's known
* to do */ * to do */
...@@ -695,10 +617,10 @@ iscissors_button_release (Tool *tool, ...@@ -695,10 +617,10 @@ iscissors_button_release (Tool *tool,
iscissors->ix = curve->x2 = iscissors->x; iscissors->ix = curve->x2 = iscissors->x;
iscissors->iy = curve->y2 = iscissors->y; iscissors->iy = curve->y2 = iscissors->y;
curve->points = NULL; curve->points = NULL;
printf("create new curve segment\n"); TRC (("create new curve segment\n"));
iscissors->curves = g_slist_append (iscissors->curves, iscissors->curves = g_slist_append (iscissors->curves,
(void *) curve); (void *) curve);
printf("calculate curve\n"); TRC (("calculate curve\n"));
calculate_curve (tool, curve); calculate_curve (tool, curve);
} }
} }
...@@ -729,18 +651,16 @@ iscissors_button_release (Tool *tool, ...@@ -729,18 +651,16 @@ iscissors_button_release (Tool *tool,
} }
} }
printf("button_release: draw core resume\n"); TRC (("button_release: draw core resume\n"));
/* Draw only the boundary */ /* Draw only the boundary */
iscissors->state = WAITING; iscissors->state = WAITING;
iscissors->draw = DRAW_CURVE; iscissors->draw = DRAW_CURVE;
draw_core_resume (iscissors->core, tool); draw_core_resume (iscissors->core, tool);
#if 0
/* convert the curves into a region */ /* convert the curves into a region */
if (iscissors->connected) if (iscissors->connected)
iscissors_convert (iscissors, gdisp_ptr); iscissors_convert (iscissors, gdisp_ptr);
#endif /* 0 */
} }
static void static void
...@@ -814,7 +734,7 @@ iscissors_draw (Tool *tool) ...@@ -814,7 +734,7 @@ iscissors_draw (Tool *tool)
int tx1, ty1, tx2, ty2; int tx1, ty1, tx2, ty2;
int txn, tyn; int txn, tyn;
printf("iscissors_draw\n"); TRC (("iscissors_draw\n"));
gdisp = (GDisplay *) tool->gdisp_ptr; gdisp = (GDisplay *) tool->gdisp_ptr;
iscissors = (Iscissors *) tool->private; iscissors = (Iscissors *) tool->private;
...@@ -905,7 +825,6 @@ iscissors_draw_curve (GDisplay *gdisp, ...@@ -905,7 +825,6 @@ iscissors_draw_curve (GDisplay *gdisp,
ICurve *curve) ICurve *curve)
{ {
gpointer *point; gpointer *point;
int i;
guint len; guint len;
int tx, ty; int tx, ty;
int npts; int npts;
...@@ -992,13 +911,13 @@ iscissors_control (Tool *tool, ...@@ -992,13 +911,13 @@ iscissors_control (Tool *tool,
static void static void
iscissors_reset (Iscissors *iscissors) iscissors_reset (Iscissors *iscissors)
{ {
printf("iscissors_reset\n"); TRC( ("iscissors_reset\n"));