configure.in app/Makefile.am moved all tool sources to app/tools

2001-01-22  Sven Neumann  <sven@gimp.org>

        * configure.in
        * app/Makefile.am
        * app/tools/Makefile.am: moved all tool sources to app/tools

        * app/app_procs.c
        * app/brush_select.c
        * app/commands.c
        * app/context_manager.c
        * app/convert.c
        * app/cursorutil.c
        * app/devices.c
        * app/disp_callbacks.c
        * app/edit_selection.c
        * app/gdisplay.c
        * app/gimage.c
        * app/gimage_mask.c
        * app/gimpbrush.c
        * app/gimpbrushgenerated.c
        * app/gimpbrushpipe.c
        * app/gimpdnd.c
        * app/gimprc.c
        * app/global_edit.c
        * app/info_window.c
        * app/interface.c
        * app/menus.c
        * app/path.c
        * app/paths_dialog.c
        * app/paths_dialogP.h
        * app/scale.c
        * app/scroll.c
        * app/undo.c
        * app/pdb/color_cmds.c
        * app/pdb/text_tool_cmds.c
        * app/pdb/tools_cmds.c
        * po/POTFILES.in
        * tools/kernelgen.c
        * tools/pdbgen/Makefile.am
        * tools/pdbgen/enums.pl
        * tools/pdbgen/pdb/color.pdb
        * tools/pdbgen/pdb/text_tool.pdb
        * tools/pdbgen/pdb/tools.pdb: changed accordingly
This commit is contained in:
Sven Neumann 2001-01-22 01:46:28 +00:00 committed by Sven Neumann
parent 47b036faf0
commit fafae590e3
184 changed files with 683 additions and 49976 deletions

View File

@ -1,3 +1,47 @@
2001-01-22 Sven Neumann <sven@gimp.org>
* configure.in
* app/Makefile.am
* app/tools/Makefile.am: moved all tool sources to app/tools
* app/app_procs.c
* app/brush_select.c
* app/commands.c
* app/context_manager.c
* app/convert.c
* app/cursorutil.c
* app/devices.c
* app/disp_callbacks.c
* app/edit_selection.c
* app/gdisplay.c
* app/gimage.c
* app/gimage_mask.c
* app/gimpbrush.c
* app/gimpbrushgenerated.c
* app/gimpbrushpipe.c
* app/gimpdnd.c
* app/gimprc.c
* app/global_edit.c
* app/info_window.c
* app/interface.c
* app/menus.c
* app/path.c
* app/paths_dialog.c
* app/paths_dialogP.h
* app/scale.c
* app/scroll.c
* app/undo.c
* app/pdb/color_cmds.c
* app/pdb/text_tool_cmds.c
* app/pdb/tools_cmds.c
* po/POTFILES.in
* tools/kernelgen.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/color.pdb
* tools/pdbgen/pdb/text_tool.pdb
* tools/pdbgen/pdb/tools.pdb: changed accordingly
2001-01-22 Daniel Egger <egger@suse.de>
* libgimp/gimpcolor.c: #include "gimppalette_pdb.h"

View File

@ -49,7 +49,7 @@
</contact>
</entry>
<entry size="big" difficulty="medium" status="0%" target="1.4">
<entry size="big" difficulty="medium" status="10%" target="1.4">
<title>Code reorganization</title>
<description>
<p>
@ -63,7 +63,7 @@
</contact>
</entry>
<entry size="medium" difficulty="medium" status="20%" target="1.4">
<entry size="medium" difficulty="medium" status="40%" target="1.4">
<title>Unify color data types</title>
<description>
<p>

View File

@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = pdb
SUBDIRS = pdb tools
scriptdata =
@ -15,8 +15,6 @@ bin_PROGRAMS = gimp
gimp_SOURCES = \
about_dialog.c \
about_dialog.h \
airbrush.c \
airbrush.h \
app_procs.c \
app_procs.h \
appenums.h \
@ -27,17 +25,8 @@ gimp_SOURCES = \
authors.h \
batch.c \
batch.h \
bezier_select.c \
bezier_select.h \
bezier_selectP.h \
blend.c \
blend.h \
blob.c \
blob.h \
boundary.c \
boundary.h \
brightness_contrast.c \
brightness_contrast.h \
brush_edit.c \
brush_edit.h \
brush_header.h \
@ -45,28 +34,18 @@ gimp_SOURCES = \
brush_scale.h \
brush_select.c \
brush_select.h \
bucket_fill.c \
bucket_fill.h \
by_color_select.c \
by_color_select.h \
channel.c \
channel.h \
channels_dialog.c \
channels_dialog.h \
channel_ops.c \
channel_ops.h \
clone.c \
clone.h \
color_area.c \
color_area.h \
color_balance.c \
color_balance.h \
color_notebook.c \
color_notebook.h \
color_panel.c \
color_panel.h \
color_picker.c \
color_picker.h \
color_select.c \
color_select.h \
color_transfer.c \
@ -81,14 +60,8 @@ gimp_SOURCES = \
context_manager.h \
convert.c \
convert.h \
convolve.c \
convolve.h \
crop.c \
crop.h \
cursorutil.c \
cursorutil.h \
curves.c \
curves.h \
datafiles.c \
datafiles.h \
desaturate.c \
@ -102,8 +75,6 @@ gimp_SOURCES = \
disp_callbacks.h \
docindex.c \
docindex.h \
dodgeburn.c \
dodgeburn.h \
draw_core.c \
draw_core.h \
drawable.c \
@ -111,10 +82,6 @@ gimp_SOURCES = \
drawable_pvt.h \
edit_selection.c \
edit_selection.h \
ellipse_select.c \
ellipse_select.h \
eraser.c \
eraser.h \
errorconsole.c \
errorconsole.h \
errors.c \
@ -124,17 +91,11 @@ gimp_SOURCES = \
fileops.c \
fileops.h \
fileopsP.h \
flip_tool.c \
flip_tool.h \
floating_sel.c \
floating_sel.h \
file_new_dialog.c \
file_new_dialog.h \
free_select.c \
free_select.h \
fsdither.h \
fuzzy_select.c \
fuzzy_select.h \
gdisplay.c \
gdisplay.h \
gdisplay_ops.c \
@ -208,10 +169,6 @@ gimp_SOURCES = \
gximage.h \
histogramwidget.c \
histogramwidget.h \
histogram_tool.c \
histogram_tool.h \
hue_saturation.c \
hue_saturation.h \
image_map.c \
image_map.h \
image_new.c \
@ -224,14 +181,10 @@ gimp_SOURCES = \
info_dialog.h \
info_window.c \
info_window.h \
ink.c \
ink.h \
interface.c \
interface.h \
invert.c \
invert.h \
iscissors.c \
iscissors.h \
layer.c \
layer.h \
layer_select.c \
@ -242,22 +195,14 @@ gimp_SOURCES = \
lc_dialog.c \
lc_dialog.h \
lc_dialogP.h \
levels.c \
levels.h \
lut_funcs.c \
lut_funcs.h \
magnify.c \
magnify.h \
main.c \
marching_ants.h \
measure.c \
measure.h \
menus.c \
menus.h \
module_db.c \
module_db.h \
move.c \
move.h \
nav_window.c \
nav_window.h \
ops_buttons.c \
@ -269,14 +214,8 @@ gimp_SOURCES = \
palette_select.c \
palette_select.h \
paletteP.h \
paint_core.c \
paint_core.h \
paint_core_kernels.h \
paint_funcs.c \
paint_funcs.h \
paint_options.h \
paintbrush.c \
paintbrush.h \
parasitelist.c \
parasitelist.h \
path.c \
@ -291,10 +230,6 @@ gimp_SOURCES = \
pattern_select.h \
patterns.c \
patterns.h \
pencil.c \
pencil.h \
perspective_tool.c \
perspective_tool.h \
pixel_processor.c \
pixel_processor.h \
pixel_region.c \
@ -303,25 +238,16 @@ gimp_SOURCES = \
pixmaps2.h \
plug_in.c \
plug_in.h \
posterize.c \
posterize.h \
preferences_dialog.c \
preferences_dialog.h \
qmask.c \
qmask.h \
rect_select.c \
rect_select.h \
rect_selectP.h \
resolution_calibrate.c \
resolution_calibrate.h \
resize.c \
resize.h \
rotate_tool.c \
rotate_tool.h \
scale.c \
scale.h \
scale_tool.c \
scale_tool.h \
scan_convert.c \
scan_convert.h \
scroll.c \
@ -331,16 +257,8 @@ gimp_SOURCES = \
selection_options.h \
session.h \
session.c \
shear_tool.c \
shear_tool.h \
smudge.c \
smudge.h \
temp_buf.c \
temp_buf.h \
text_tool.c \
text_tool.h \
threshold.c \
threshold.h \
tile.c \
tile.h \
tile_pvt.h \
@ -353,14 +271,6 @@ gimp_SOURCES = \
tile_swap.h \
tips_dialog.c \
tips_dialog.h \
tool_options.c \
tool_options.h \
tools.c \
tools.h \
transform_core.c \
transform_core.h \
transform_tool.c \
transform_tool.h \
undo.c \
undo.h \
undo_history.c \
@ -400,6 +310,7 @@ INCLUDES = \
gimp_LDADD = \
pdb/libapppdb.la \
tools/libapptools.la \
$(top_builddir)/libgimp/libgimpi.a \
$(GTK_LIBS) \
$(GIMP_THREAD_LIBS) \

View File

@ -68,13 +68,14 @@
#include "scale.h"
#include "selection.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
#ifdef DISPLAY_FILTERS
#include "gdisplay_color_ui.h"
#endif /* DISPLAY_FILTERS */
#include "tools/tools.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -1,440 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "airbrush.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gradient.h"
#include "gimpimage.h"
#include "gimpbrush.h"
#include "gimpcontext.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "paint_options.h"
#include "selection.h"
#include "temp_buf.h"
#include "tools.h"
#include "libgimp/gimpintl.h"
/* The maximum amount of pressure that can be exerted */
#define MAX_PRESSURE 0.075
/* Default pressure setting */
#define AIRBRUSH_PRESSURE_DEFAULT 10.0
#define AIRBRUSH_INCREMENTAL_DEFAULT FALSE
#define OFF 0
#define ON 1
/* the airbrush structures */
typedef struct _AirbrushTimeout AirbrushTimeout;
struct _AirbrushTimeout
{
PaintCore *paint_core;
GimpDrawable *drawable;
};
typedef struct _AirbrushOptions AirbrushOptions;
struct _AirbrushOptions
{
PaintOptions paint_options;
gdouble rate;
gdouble rate_d;
GtkObject *rate_w;
gdouble pressure;
gdouble pressure_d;
GtkObject *pressure_w;
};
/* local function prototypes */
static gpointer airbrush_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state);
static gpointer airbrush_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state);
/* the airbrush tool options */
static AirbrushOptions *airbrush_options = NULL;
/* local variables */
static gint timer; /* timer for successive paint applications */
static gint timer_state = OFF; /* state of airbrush tool */
static AirbrushTimeout airbrush_timeout;
static gdouble non_gui_pressure;
static gboolean non_gui_incremental;
/* forward function declarations */
static void airbrush_motion (PaintCore *, GimpDrawable *,
PaintPressureOptions *,
gdouble, PaintApplicationMode);
static gint airbrush_time_out (gpointer);
/* functions */
static void
airbrush_options_reset (void)
{
AirbrushOptions *options = airbrush_options;
paint_options_reset ((PaintOptions *) options);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w),
options->rate_d);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->pressure_w),
options->pressure_d);
}
static AirbrushOptions *
airbrush_options_new (void)
{
AirbrushOptions *options;
GtkWidget *vbox;
GtkWidget *table;
GtkWidget *scale;
/* the new airbrush tool options structure */
options = g_new (AirbrushOptions, 1);
paint_options_init ((PaintOptions *) options,
AIRBRUSH,
airbrush_options_reset);
options->rate = options->rate_d = 80.0;
options->pressure = options->pressure_d = AIRBRUSH_PRESSURE_DEFAULT;
/* the main vbox */
vbox = ((ToolOptions *) options)->main_vbox;
/* the rate scale */
table = gtk_table_new (2, 2, FALSE);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 1);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
options->rate_w =
gtk_adjustment_new (options->rate_d, 0.0, 150.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w));
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed",
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
&options->rate);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("Rate:"), 1.0, 1.0,
scale, 1, FALSE);
/* the pressure scale */
options->pressure_w =
gtk_adjustment_new (options->pressure_d, 0.0, 100.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->pressure_w));
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (options->pressure_w), "value_changed",
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
&options->pressure);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
_("Pressure:"), 1.0, 1.0,
scale, 1, FALSE);
gtk_widget_show (table);
return options;
}
Tool *
tools_new_airbrush (void)
{
Tool * tool;
PaintCore * private;
/* The tool options */
if (! airbrush_options)
{
airbrush_options = airbrush_options_new ();
tools_register (AIRBRUSH, (ToolOptions *) airbrush_options);
}
tool = paint_core_new (AIRBRUSH);
private = (PaintCore *) tool->private;
private->paint_func = airbrush_paint_func;
private->pick_colors = TRUE;
private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH;
return tool;
}
static gpointer
airbrush_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
GimpBrush *brush;
gdouble rate;
if (!drawable)
return NULL;
brush = gimp_context_get_brush (NULL);
switch (state)
{
case INIT_PAINT :
/* timer_state = OFF; */
if (timer_state == ON)
{
g_warning ("killing stray timer, please report to lewing@gimp.org");
gtk_timeout_remove (timer);
}
timer_state = OFF;
break;
case MOTION_PAINT :
if (timer_state == ON)
gtk_timeout_remove (timer);
timer_state = OFF;
airbrush_motion (paint_core, drawable,
airbrush_options->paint_options.pressure_options,
airbrush_options->pressure,
airbrush_options->paint_options.incremental ?
INCREMENTAL : CONSTANT);
if (airbrush_options->rate != 0.0)
{
airbrush_timeout.paint_core = paint_core;
airbrush_timeout.drawable = drawable;
rate = airbrush_options->paint_options.pressure_options->rate ?
(10000 / (airbrush_options->rate * 2.0 * paint_core->curpressure)) :
(10000 / airbrush_options->rate);
timer = gtk_timeout_add (rate, airbrush_time_out, NULL);
timer_state = ON;
}
break;
case FINISH_PAINT :
if (timer_state == ON)
gtk_timeout_remove (timer);
timer_state = OFF;
break;
default :
break;
}
return NULL;
}
void
tools_free_airbrush (Tool *tool)
{
if (timer_state == ON)
gtk_timeout_remove (timer);
timer_state = OFF;
paint_core_free (tool);
}
static gint
airbrush_time_out (gpointer client_data)
{
/* service the timer */
airbrush_motion (airbrush_timeout.paint_core,
airbrush_timeout.drawable,
airbrush_options->paint_options.pressure_options,
airbrush_options->pressure,
airbrush_options->paint_options.incremental ?
INCREMENTAL : CONSTANT);
gdisplays_flush ();
/* restart the timer */
if (airbrush_options->rate != 0.0)
{
if (airbrush_options->paint_options.pressure_options->rate)
{
/* set a new timer */
timer = gtk_timeout_add ((10000 / (airbrush_options->rate * 2.0 * airbrush_timeout.paint_core->curpressure)),
airbrush_time_out, NULL);
return FALSE;
}
else
return TRUE;
}
else
return FALSE;
}
static void
airbrush_motion (PaintCore *paint_core,
GimpDrawable *drawable,
PaintPressureOptions *pressure_options,
double pressure,
PaintApplicationMode mode)
{
GImage *gimage;
TempBuf *area;
guchar col[MAX_CHANNELS];
gdouble scale;
if (!drawable)
return;
if (! (gimage = gimp_drawable_gimage (drawable)))
return;
if (pressure_options->size)
scale = paint_core->curpressure;
else
scale = 1.0;
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
return;
/* color the pixels */
if (pressure_options->color)
{
GimpRGB color;
gradient_get_color_at (gimp_context_get_gradient (NULL),
paint_core->curpressure, &color);
gimp_rgba_get_uchar (&color,
&col[RED_PIX],
&col[GREEN_PIX],
&col[BLUE_PIX],
&col[ALPHA_PIX]);
mode = INCREMENTAL;
color_pixels (temp_buf_data (area), col,
area->width * area->height, area->bytes);
}
else if (paint_core->brush && paint_core->brush->pixmap)
{
mode = INCREMENTAL;
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
scale, SOFT);
}
else
{
gimp_image_get_foreground (gimage, drawable, col);
col[area->bytes - 1] = OPAQUE_OPACITY;
color_pixels (temp_buf_data (area), col,
area->width * area->height, area->bytes);
}
if (pressure_options->pressure)
pressure = pressure * 2.0 * paint_core->curpressure;
/* paste the newly painted area to the image */
paint_core_paste_canvas (paint_core, drawable,
MIN (pressure, 255),
(gint) (gimp_context_get_opacity (NULL) * 255),
gimp_context_get_paint_mode (NULL),
SOFT, scale, mode);
}
static gpointer
airbrush_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
airbrush_motion (paint_core, drawable, &non_gui_pressure_options,
non_gui_pressure, non_gui_incremental);
return NULL;
}
gboolean
airbrush_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array)
{
AirbrushOptions *options = airbrush_options;
gdouble pressure = AIRBRUSH_PRESSURE_DEFAULT;
if(options)
pressure = options->pressure;
return airbrush_non_gui (drawable, pressure, num_strokes, stroke_array);
}
gboolean
airbrush_non_gui (GimpDrawable *drawable,
gdouble pressure,
gint num_strokes,
gdouble *stroke_array)
{
gint i;
if (paint_core_init (&non_gui_paint_core, drawable,
stroke_array[0], stroke_array[1]))
{
/* Set the paint core's paint func */
non_gui_paint_core.paint_func = airbrush_non_gui_paint_func;
non_gui_pressure = pressure;
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
airbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
for (i = 1; i < num_strokes; i++)
{
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
paint_core_interpolate (&non_gui_paint_core, drawable);
non_gui_paint_core.lastx = non_gui_paint_core.curx;
non_gui_paint_core.lasty = non_gui_paint_core.cury;
}
/* Finish the painting */
paint_core_finish (&non_gui_paint_core, drawable, -1);
/* Cleanup */
paint_core_cleanup ();
return TRUE;
}
return FALSE;
}

View File

@ -1,35 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __AIRBRUSH_H__
#define __AIRBRUSH_H__
gboolean airbrush_non_gui (GimpDrawable *drawable,
gdouble pressure,
gint num_strokes,
gdouble *stroke_array);
gboolean airbrush_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array);
Tool * tools_new_airbrush (void);
void tools_free_airbrush (Tool *tool);
#endif /* __AIRBRUSH_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,153 +0,0 @@
/* airbrush_blob.h: routines for manipulating scan converted convex
* polygons.
*
* Copyright 1998, Owen Taylor <otaylor@gtk.org>
*
* > Please contact the above author before modifying the copy <
* > of this file in the GIMP distribution. Thanks. <
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __AIRBRUSHBLOB_H__
#define __AIRBRUSHBLOB_H__
typedef enum {
CROSS = 0,
CROSS_LEFT = 1,
CROSS_RIGHT = 2,
CROSS_WHOLE_LINE = 3,
CROSS_NORMAL = 4
} CrossType;
typedef enum {
RIGHT_LEFT = 0,
LEFT_RIGHT = 1,
TOP_BOT = 2,
BOT_TOP = 3,
NONE = 4
} MoveType;
/* The AirBlob, which is a abstract of a real AirBrushBlob */
typedef struct _AirBlob AirBlob;
typedef struct _AirPoint AirPoint;
typedef struct _SupportLine SupportLine;
struct _AirPoint {
int x;
int y;
};
struct _SupportLine {
double size;
double dist;
};
struct _AirBlob {
double direction_abs;
double direction;
double ycenter;
double xcenter;
SupportLine main_line;
SupportLine minor_line;
SupportLine maincross_line;
SupportLine minorcross_line;
};
/* The AirLine is a reslut of a AirBlob */
typedef struct _AirLine AirLine;
struct _AirLine {
int xcenter;
int ycenter;
AirPoint line[16];
int min_x, min_y;
int max_x, max_y;
int width, height;
int nlines;
};
typedef struct _AirBrushBlobPoint AirBrushBlobPoint;
typedef struct _AirBrushBlobSpan AirBrushBlobSpan;
typedef struct _AirBrushBlob AirBrushBlob;
struct _AirBrushBlobPoint {
int x;
int y;
};
struct _AirBrushBlobSpan {
int left;
double angle_left;
double angle_left_abs;
double dist_left;
int right;
double angle_right;
double angle_right_abs;
double dist_right;
CrossType cross_type;
int x_cross;
int center;
double dist;
};
struct _AirBrushBlob {
int y;
int height;
int width;
int min_x;
int max_x;
MoveType move;
double direction_abs;
double direction;
CrossType cross;
AirBrushBlobSpan data[1];
};
typedef struct _AirBrush AirBrush;
struct _AirBrush {
AirBrushBlob airbrush_blob;
AirBlob airblob;
};
AirBlob *create_air_blob (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl, double direction_abs, double direction);
AirBlob *trans_air_blob(AirBlob *airblob_last, AirBlob *airblob_present, double dist, int xc, int yc);
AirLine *create_air_line(AirBlob *airblob);
AirBrushBlob *airbrush_blob_convex_union (AirBrushBlob *b1, AirBrushBlob *b2);
AirBrushBlob *airbrush_blob_ellipse (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl);
void airbrush_blob_bounds (AirBrushBlob *b, int *x, int *y, int *width, int *height);
#endif /* __AIRBRUSHBLOB_H__ */

View File

@ -46,7 +46,6 @@
#include "batch.h"
#include "brush_select.h"
#include "color_transfer.h"
#include "curves.h"
#include "colormaps.h"
#include "context_manager.h"
#include "devices.h"
@ -65,11 +64,9 @@
#include "gradient_select.h"
#include "gradient.h"
#include "gximage.h"
#include "hue_saturation.h"
#include "image_render.h"
#include "interface.h"
#include "lc_dialog.h"
#include "levels.h"
#include "menus.h"
#include "paint_funcs.h"
#include "palette.h"
@ -81,7 +78,6 @@
#include "temp_buf.h"
#include "tile_swap.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
#include "unitrc.h"
#include "xcf.h"
@ -97,6 +93,11 @@
#include "color_select.h"
#include "gimpparasite.h"
#include "tools/curves.h"
#include "tools/hue_saturation.h"
#include "tools/levels.h"
#include "tools/tools.h"
#include "pdb/internal_procs.h"
#include "libgimp/gimplimits.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BEZIER_SELECT_H__
#define __BEZIER_SELECT_H__
Tool * tools_new_bezier_select (void);
void tools_free_bezier_select (Tool *tool);
gboolean bezier_tool_selected (void);
#endif /* __BEZIER_SELECT_H__ */

View File

@ -1,116 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BEZIER_SELECTP_H__
#define __BEZIER_SELECTP_H__
#include "draw_core.h"
#define BEZIER_START 1
#define BEZIER_ADD 2
#define BEZIER_EDIT 4
#define BEZIER_DRAG 8
#define BEZIER_ANCHOR 1
#define BEZIER_CONTROL 2
#define BEZIER_MOVE 3
#define IMAGE_COORDS 1
#define AA_IMAGE_COORDS 2
#define SCREEN_COORDS 3
#define SUBDIVIDE 1000
enum { EXTEND_EDIT, EXTEND_ADD, EXTEND_REMOVE, EXTEND_NEW };
struct _BezierPoint
{
gint type; /* type of point (anchor/control/move) */
gdouble x, y; /* location of point in image space */
gint sx, sy; /* location of point in screen space */
BezierPoint *next; /* next point on curve */
BezierPoint *prev; /* prev point on curve */
BezierPoint *next_curve; /* Next curve segment */
gint pointflags; /* Status of point 0 = not selected
* 1 = selected
*/
};
struct _BezierSelect
{
gint state; /* start, add, edit or drag */
gint draw; /* all or part */
gint closed; /* is the last curve closed */
DrawCore *core; /* Core drawing object */
BezierPoint *points; /* the curve */
BezierPoint *cur_anchor; /* the current active anchor point */
BezierPoint *cur_control; /* the current active control point */
BezierPoint *last_point; /* the last point on the curve */
gint num_points; /* number of points in the curve */
Channel *mask; /* null if the curve is open */
GSList **scanlines; /* used in converting a curve */
};
/* All data that are passed to the bezier_draw_curve must
* have this structure as the first element.
*/
typedef struct
{
gint count;
} CountCurves;
typedef void (* BezierPointsFunc) (BezierSelect *bezier_sel,
GdkPoint *points,
gint n_points,
gpointer data);
/* Functions */
gint bezier_select_load (GDisplay *gdisp,
BezierPoint *points,
gint n_points,
gint closed);
void bezier_draw_curve (BezierSelect *bezier_sel,
BezierPointsFunc func,
gint coord,
gpointer data);
void bezier_select_reset (BezierSelect *bezier_sel);
void bezier_select_free (BezierSelect *bezier_sel);
void bezier_add_point (BezierSelect *bezier_sel,
gint type,
gdouble x,
gdouble y);
void bezier_paste_bezierselect_to_current (GDisplay *gdisp,
BezierSelect *bezier_sel);
void bezier_select_mode (gint);
void bezier_stroke (BezierSelect *bezier_sel,
GDisplay *gdisp,
gint subdivisions,
gint open_path);
void bezier_to_selection (BezierSelect *bezier_sel,
GDisplay *gdisp);
gint bezier_distance_along (BezierSelect *bezier_sel,
gint open_path,
gdouble dist,
gint *x,
gint *y,
gdouble *gradient);
void bezier_draw (GDisplay *gdisp,
BezierSelect *bezier_sel);
#endif /* __BEZIER_SELECTP_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,78 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BLEND_H__
#define __BLEND_H__
typedef enum
{
LINEAR,
BILINEAR,
RADIAL,
SQUARE,
CONICAL_SYMMETRIC,
CONICAL_ASYMMETRIC,
SHAPEBURST_ANGULAR,
SHAPEBURST_SPHERICAL,
SHAPEBURST_DIMPLED,
SPIRAL_CLOCKWISE,
SPIRAL_ANTICLOCKWISE,
GRADIENT_TYPE_LAST /*< skip >*/
} GradientType;
typedef enum /*< chop=_MODE >*/
{
FG_BG_RGB_MODE,
FG_BG_HSV_MODE,
FG_TRANS_MODE,
CUSTOM_MODE,
BLEND_MODE_LAST /*< skip >*/
} BlendMode;
typedef enum
{
REPEAT_NONE,
REPEAT_SAWTOOTH,
REPEAT_TRIANGULAR,
REPEAT_LAST /*< skip >*/
} RepeatMode;
void blend (GimpImage *gimage,
GimpDrawable *drawable,
BlendMode blend_mode,
gint paint_mode,
GradientType gradient_type,
gdouble opacity,
gdouble offset,
RepeatMode repeat,
gint supersample,
gint max_depth,
gdouble threshold,
gdouble startx,
gdouble starty,
gdouble endx,
gdouble endy,
GimpProgressFunc progress_callback,
gpointer progress_data);
Tool * tools_new_blend (void);
void tools_free_blend (Tool *tool);
#endif /* __BLEND_H__ */

View File

@ -1,774 +0,0 @@
/* blob.c: routines for manipulating scan converted convex
* polygons.
*
* Copyright 1998-1999, Owen Taylor <otaylor@gtk.org>
*
* > Please contact the above author before modifying the copy <
* > of this file in the GIMP distribution. Thanks. <
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "blob.h"
#include "libgimp/gimpmath.h"
static Blob *
blob_new (int y, int height)
{
Blob *result;
result = g_malloc (sizeof (Blob) + sizeof(BlobSpan) * (height-1));
result->y = y;
result->height = height;
return result;
}
typedef enum {
EDGE_NONE = 0,
EDGE_LEFT = 1 << 0,
EDGE_RIGHT = 1 << 1
} EdgeType;
static void
blob_fill (Blob *b, EdgeType *present)
{
int start;
int x1, x2, i1, i2;
int i;
/* Mark empty lines at top and bottom as unused */
start = 0;
while (!(present[start]))
{
b->data[start].left = 0;
b->data[start].right = -1;
start++;
}
if (present[start] != (EDGE_RIGHT | EDGE_LEFT))
{
if (present[start] == EDGE_RIGHT)
b->data[start].left = b->data[start].right;
else
b->data[start].right = b->data[start].left;
present[start] = EDGE_RIGHT | EDGE_LEFT;
}
for (i=b->height-1;!present[i];i--)
{
b->data[i].left = 0;
b->data[i].right = -1;
}
if (present[i] != (EDGE_RIGHT | EDGE_LEFT))
{
if (present[i] == EDGE_RIGHT)
b->data[i].left = b->data[i].right;
else
b->data[i].right = b->data[i].left;
present[i] = EDGE_RIGHT | EDGE_LEFT;
}
/* Restore missing edges */
/* We fill only interior regions of convex hull, as if we were filling
polygons. But since we draw ellipses with nearest points, not interior
points, maybe it would look better if we did the same here. Probably
not a big deal either way after anti-aliasing */
/* left edge */
for (i1=start; i1<b->height-2; i1++)
{
/* Find empty gaps */
if (!(present[i1+1] & EDGE_LEFT))
{
int increment; /* fractional part */
int denom; /* denominator of fraction */
int step; /* integral step */
int frac; /* fractional step */
int reverse;
/* find bottom of gap */
i2 = i1+2;
while (!(present[i2] & EDGE_LEFT) && i2 < b->height) i2++;
if (i2 < b->height)
{
denom = i2-i1;
x1 = b->data[i1].left;
x2 = b->data[i2].left;
step = (x2-x1)/denom;
frac = x2-x1 - step*denom;
if (frac < 0)
{
frac = -frac;
reverse = 1;
}
else
reverse = 0;
increment = 0;
for (i=i1+1; i<i2; i++)
{
x1 += step;
increment += frac;
if (increment >= denom)
{
increment -= denom;
x1 += reverse ? -1 : 1;
}
if (increment == 0 || reverse)
b->data[i].left = x1;
else
b->data[i].left = x1 + 1;
}
}
i1 = i2-1; /* advance to next possibility */
}
}
/* right edge */
for (i1=start; i1<b->height-2; i1++)
{
/* Find empty gaps */
if (!(present[i1+1] & EDGE_RIGHT))
{
int increment; /* fractional part */
int denom; /* denominator of fraction */
int step; /* integral step */
int frac; /* fractional step */
int reverse;
/* find bottom of gap */
i2 = i1+2;
while (!(present[i2] & EDGE_RIGHT) && i2 < b->height) i2++;
if (i2 < b->height)
{
denom = i2-i1;
x1 = b->data[i1].right;
x2 = b->data[i2].right;
step = (x2-x1)/denom;
frac = x2-x1 - step*denom;
if (frac < 0)
{
frac = -frac;
reverse = 1;
}
else
reverse = 0;
increment = 0;
for (i=i1+1; i<i2; i++)
{
x1 += step;
increment += frac;
if (increment >= denom)
{
increment -= denom;
x1 += reverse ? -1 : 1;
}
if (reverse && increment != 0)
b->data[i].right = x1 - 1;
else
b->data[i].right = x1;
}
}
i1 = i2-1; /* advance to next possibility */
}
}
}
static void
blob_make_convex (Blob *b, EdgeType *present)
{
int x1, x2, y1, y2, i1, i2;
int i;
int start;
/* Walk through edges, deleting points that aren't on convex hull */
start = 0;
while (!(present[start])) start++;
/* left edge */
i1 = start-1;
i2 = start;
x1 = b->data[start].left - b->data[start].right;
y1 = 0;
for (i=start+1;i<b->height;i++)
{
if (!(present[i] & EDGE_LEFT))
continue;
x2 = b->data[i].left - b->data[i2].left;
y2 = i-i2;
while (x2*y1 - x1*y2 < 0) /* clockwise rotation */
{
present[i2] &= ~EDGE_LEFT;
i2 = i1;
while (!(present[--i1] & EDGE_LEFT) && i1>=start);
if (i1<start)
{
x1 = b->data[start].left - b->data[start].right;
y1 = 0;
}
else
{
x1 = b->data[i2].left - b->data[i1].left;
y1 = i2 - i1;
}
x2 = b->data[i].left - b->data[i2].left;
y2 = i - i2;
}
x1 = x2;
y1 = y2;
i1 = i2;
i2 = i;
}
/* Right edge */
i1 = start -1;
i2 = start;
x1 = b->data[start].right - b->data[start].left;
y1 = 0;
for (i=start+1;i<b->height;i++)
{
if (!(present[i] & EDGE_RIGHT))
continue;
x2 = b->data[i].right - b->data[i2].right;
y2 = i-i2;
while (x2*y1 - x1*y2 > 0) /* counter-clockwise rotation */
{
present[i2] &= ~EDGE_RIGHT;
i2 = i1;
while (!(present[--i1] & EDGE_RIGHT) && i1>=start);
if (i1<start)
{
x1 = b->data[start].right - b->data[start].left;
y1 = 0;
}
else
{
x1 = b->data[i2].right - b->data[i1].right;
y1 = i2 - i1;
}
x2 = b->data[i].right - b->data[i2].right;
y2 = i - i2;
}
x1 = x2;
y1 = y2;
i1 = i2;
i2 = i;
}
blob_fill (b, present);
}
Blob *
blob_convex_union (Blob *b1, Blob *b2)
{
Blob *result;
int y;
int i, j;
EdgeType *present;
/* Create the storage for the result */
y = MIN(b1->y,b2->y);
result = blob_new (y, MAX(b1->y+b1->height,b2->y+b2->height)-y);
if (result->height == 0)
return result;
present = g_new0 (EdgeType, result->height);
/* Initialize spans from original objects */
for (i=0, j=b1->y-y; i<b1->height; i++,j++)
{
if (b1->data[i].right >= b1->data[i].left)
{
present[j] = EDGE_LEFT | EDGE_RIGHT;
result->data[j].left = b1->data[i].left;
result->data[j].right = b1->data[i].right;
}
}
for (i=0, j=b2->y-y; i<b2->height; i++,j++)
{
if (b2->data[i].right >= b2->data[i].left)
{
if (present[j])
{
if (result->data[j].left > b2->data[i].left)
result->data[j].left = b2->data[i].left;
if (result->data[j].right < b2->data[i].right)
result->data[j].right = b2->data[i].right;
}
else
{
present[j] = EDGE_LEFT | EDGE_RIGHT;
result->data[j].left = b2->data[i].left;
result->data[j].right = b2->data[i].right;
}
}
}
blob_make_convex (result, present);
g_free (present);
return result;
}
static void
blob_line_add_pixel (Blob *b, int x, int y)
{
if (b->data[y-b->y].left > b->data[y-b->y].right)
b->data[y-b->y].left = b->data[y-b->y].right = x;
else
{
b->data[y-b->y].left = MIN (b->data[y-b->y].left, x);
b->data[y-b->y].right = MAX (b->data[y-b->y].right, x);
}
}
void
blob_line (Blob *b, int x0, int y0, int x1, int y1)
{
int dx, dy, d;
int incrE, incrNE;
int x, y;
int xstep = 1;
int ystep = 1;
dx = x1 - x0;
dy = y1 - y0;
if (dx < 0)
{
dx = -dx;
xstep = -1;
}
if (dy < 0)
{
dy = -dy;
ystep = -1;
}
/* for (y = y0; y != y1 + ystep ; y += ystep)
{
b->data[y-b->y].left = 0;
b->data[y-b->y].right = -1;
}*/
x = x0;
y = y0;
if (dy < dx)
{
d = 2*dy - dx; /* initial value of d */
incrE = 2 * dy; /* increment used for move to E */
incrNE = 2 * (dy-dx); /* increment used for move to NE */
blob_line_add_pixel (b, x, y);
while (x != x1)
{
if (d <= 0)
{
d += incrE;
x += xstep;
}
else
{
d += incrNE;
x += xstep;
y += ystep;
}
blob_line_add_pixel (b, x, y);
}
}
else
{
d = 2*dx - dy; /* initial value of d */
incrE = 2 * dx; /* increment used for move to E */
incrNE = 2 * (dx-dy); /* increment used for move to NE */
blob_line_add_pixel (b, x, y);
while (y != y1)
{
if (d <= 0)
{
d += incrE;
y += ystep;
}
else
{
d += incrNE;
x += xstep;
y += ystep;
}
blob_line_add_pixel (b, x, y);
}
}
}
#define TABLE_SIZE 256
#define ELLIPSE_SHIFT 2
#define TABLE_SHIFT 12
#define TOTAL_SHIFT (ELLIPSE_SHIFT + TABLE_SHIFT)
/*
* The choose of this values limits the maximal image_size to
* 16384 x 16384 pixels. The values will overflow as soon as
* x or y > INT_MAX / (1 << (ELLIPSE_SHIFT + TABLE_SHIFT)) / SUBSAMPLE
*
* Alternatively the code could be change the code as follows:
*
* xc_base = floor (xc)
* xc_shift = 0.5 + (xc - xc_base) * (1 << TOTAL_SHIFT);
*
* gint x = xc_base + (xc_shift + c * xp_shift + s * xq_shift +
* (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
*
* which would change the limit from the image to the ellipse size
*/
static int trig_initialized = 0;
static int trig_table[TABLE_SIZE];
/* Return blob for the given (convex) polygon
*/
Blob *
blob_polygon (BlobPoint *points, int npoints)
{
int i;
int im1;
int ip1;
int ymin, ymax;
Blob *result;
EdgeType *present;
ymax = points[0].y;
ymin = points[0].y;
for (i=1; i < npoints; i++)
{
if (points[i].y > ymax)
ymax = points[i].y;
if (points[i].y < ymin)
ymin = points[i].y;
}
result = blob_new (ymin, ymax - ymin + 1);
present = g_new0 (EdgeType, result->height);
im1 = npoints - 1;
i = 0;
ip1 = 1;
for (; i < npoints ; i++)
{
int sides = 0;
int j = points[i].y - ymin;
if (points[i].y < points[im1].y)
sides |= EDGE_RIGHT;
else if (points[i].y > points[im1].y)
sides |= EDGE_LEFT;
if (points[ip1].y < points[i].y)
sides |= EDGE_RIGHT;
else if (points[ip1].y > points[i].y)
sides |= EDGE_LEFT;
if (sides & EDGE_RIGHT)
{
if (present[j] & EDGE_RIGHT)
{
result->data[j].right = MAX (result->data[j].right, points[i].x);
}
else
{
present[j] |= EDGE_RIGHT;
result->data[j].right = points[i].x;
}
}
if (sides & EDGE_LEFT)
{
if (present[j] & EDGE_LEFT)
{
result->data[j].left = MIN (result->data[j].left, points[i].x);
}
else
{
present[j] |= EDGE_LEFT;
result->data[j].left = points[i].x;
}
}
im1 = i;
ip1++;
if (ip1 == npoints)
ip1 = 0;
}
blob_fill (result, present);
g_free (present);
return result;
}
/* Scan convert a square specified by _offsets_ of major and
minor axes, and by center into a blob */
Blob *
blob_square (double xc, double yc, double xp, double yp, double xq, double yq)
{
BlobPoint points[4];
/* Make sure we order points ccw */
if (xp * yq - yq * xp < 0)
{
xq = -xq;
yq = -yq;
}
points[0].x = xc + xp + xq;
points[0].y = yc + yp + yq;
points[1].x = xc + xp - xq;
points[1].y = yc + yp - yq;
points[2].x = xc - xp - xq;
points[2].y = yc - yp - yq;
points[3].x = xc - xp + xq;
points[3].y = yc - yp + yq;
return blob_polygon (points, 4);
}
/* Scan convert a diamond specified by _offsets_ of major and
minor axes, and by center into a blob */
Blob *
blob_diamond (double xc, double yc, double xp, double yp, double xq, double yq)
{
BlobPoint points[4];
/* Make sure we order points ccw */
if (xp * yq - yq * xp < 0)
{
xq = -xq;
yq = -yq;
}
points[0].x = xc + xp;
points[0].y = yc + yp;
points[1].x = xc - xq;
points[1].y = yc - yq;
points[2].x = xc - xp;
points[2].y = yc - yp;
points[3].x = xc + xq;
points[3].y = yc + yq;
return blob_polygon (points, 4);
}
/* Scan convert an ellipse specified by _offsets_ of major and
minor axes, and by center into a blob */
Blob *
blob_ellipse (double xc, double yc, double xp, double yp, double xq, double yq)
{
int i;
Blob *r;
gdouble r1, r2;
gint maxy, miny;
gint step;
double max_radius;
gint xc_shift, yc_shift;
gint xp_shift, yp_shift;
gint xq_shift, yq_shift;
EdgeType *present;
if (!trig_initialized)
{
trig_initialized = 1;
for (i=0; i<256; i++)
trig_table[i] = 0.5 + sin(i * (G_PI / 128.)) * (1 << TABLE_SHIFT);
}
/* Make sure we traverse ellipse in ccw direction */
if (xp * yq - yq * xp < 0)
{
xq = -xq;
yq = -yq;
}
/* Compute bounds as if we were drawing a rectangle */
maxy = ceil (yc + fabs (yp) + fabs(yq));
miny = floor (yc - fabs (yp) - fabs(yq));
r = blob_new (miny, maxy - miny + 1);
present = g_new0 (EdgeType, r->height);
/* Figure out a step that will draw most of the points */
r1 = sqrt (xp * xp + yp * yp);
r2 = sqrt (xq * xq + yq * yq);
max_radius = MAX (r1, r2);
step = TABLE_SIZE;
while (step > 1 && (TABLE_SIZE / step < 4*max_radius))
step >>= 1;
/* Fill in the edge points */
xc_shift = 0.5 + xc * (1 << TOTAL_SHIFT);
yc_shift = 0.5 + yc * (1 << TOTAL_SHIFT);
xp_shift = 0.5 + xp * (1 << ELLIPSE_SHIFT);
yp_shift = 0.5 + yp * (1 << ELLIPSE_SHIFT);
xq_shift = 0.5 + xq * (1 << ELLIPSE_SHIFT);
yq_shift = 0.5 + yq * (1 << ELLIPSE_SHIFT);
for (i = 0 ; i < TABLE_SIZE ; i += step)
{
gint s = trig_table[i];
gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE];
gint x = (xc_shift + c * xp_shift + s * xq_shift +
(1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
gint y = ((yc_shift + c * yp_shift + s * yq_shift +
(1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - r->y;
gint dydi = c * yq_shift - s * yp_shift;
if (dydi <= 0) /* left edge */
{
if (present[y] & EDGE_LEFT)
{
r->data[y].left = MIN (r->data[y].left, x);
}
else
{
present[y] |= EDGE_LEFT;
r->data[y].left = x;
}
}
if (dydi >= 0) /* right edge */
{
if (present[y] & EDGE_RIGHT)
{
r->data[y].right = MAX (r->data[y].right, x);
}
else
{
present[y] |= EDGE_RIGHT;
r->data[y].right = x;
}
}
}
/* Now fill in missing points */
blob_fill (r, present);
g_free (present);
return r;
}
void
blob_bounds(Blob *b, int *x, int *y, int *width, int *height)
{
int i;
int x0, x1, y0, y1;
i = 0;
while (i<b->height && b->data[i].left > b->data[i].right)
i++;
if (i<b->height)
{
y0 = b->y + i;
x0 = b->data[i].left;
x1 = b->data[i].right + 1;
while (i<b->height && b->data[i].left <= b->data[i].right)
{
x0 = MIN(b->data[i].left, x0);
x1 = MAX(b->data[i].right+1, x1);
i++;
}
y1 = b->y + i;
}
else
{
x0 = y0 = 0;
x1 = y1 = 0;
}
*x = x0;
*y = y0;
*width = x1 - x0;
*height = y1 - y0;
}
void
blob_dump(Blob *b) {
int i,j;
for (i=0; i<b->height; i++)
{
for (j=0;j<b->data[i].left;j++)
putchar(' ');
for (j=b->data[i].left;j<=b->data[i].right;j++)
putchar('*');
putchar('\n');
}
}

View File

@ -1,82 +0,0 @@
/* blob.h: routines for manipulating scan converted convex
* polygons.
*
* Copyright 1998, Owen Taylor <otaylor@gtk.org>
*
* > Please contact the above author before modifying the copy <
* > of this file in the GIMP distribution. Thanks. <
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __BLOB_H__
#define __BLOB_H__
typedef struct _BlobPoint BlobPoint;
typedef struct _BlobSpan BlobSpan;
typedef struct _Blob Blob;
struct _BlobPoint
{
gint x;
gint y;
};
struct _BlobSpan
{
gint left;
gint right;
};
struct _Blob
{
gint y;
gint height;
BlobSpan data[1];
};
Blob * blob_convex_union (Blob *b1,
Blob *b2);
Blob * blob_polygon (BlobPoint *points,
gint npoints);
Blob * blob_square (gdouble xc,
gdouble yc,
gdouble xp,
gdouble yp,
gdouble xq,
gdouble yq);
Blob * blob_diamond (gdouble xc,
gdouble yc,
gdouble xp,
gdouble yp,
gdouble xq,
gdouble yq);
Blob * blob_ellipse (gdouble xc,
gdouble yc,
gdouble xp,
gdouble yp,
gdouble xq,
gdouble yq);
void blob_bounds (Blob *b,
gint *x,
gint *y,
gint *width,
gint *height);
#endif /* __BLOB_H__ */

View File

@ -1,499 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "brightness_contrast.h"
#include "drawable.h"
#include "gimpcontext.h"
#include "gimplut.h"
#include "gimpui.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "image_map.h"
#include "lut_funcs.h"
#include "tool_options.h"
#include "tools.h"
#include "libgimp/gimpintl.h"
#define SLIDER_WIDTH 200
#define BRIGHTNESS 0x1
#define CONTRAST 0x2
#define ALL (BRIGHTNESS | CONTRAST)
/* the brightness-contrast structures */
typedef struct _BrightnessContrast BrightnessContrast;
struct _BrightnessContrast
{
gint x, y; /* coords for last mouse click */
};
typedef struct _BrightnessContrastDialog BrightnessContrastDialog;
struct _BrightnessContrastDialog
{
GtkWidget *shell;
GtkWidget *gimage_name;
GtkAdjustment *brightness_data;
GtkAdjustment *contrast_data;
GimpDrawable *drawable;
ImageMap image_map;
gdouble brightness;
gdouble contrast;
gboolean preview;
GimpLut *lut;
};
/* the brightness-contrast tool options */
static ToolOptions *brightness_contrast_options = NULL;
/* the brightness-contrast dialog */
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
/* brightness contrast action functions */
static void brightness_contrast_control (Tool *tool,
ToolAction action,
GDisplay *gdisp);
static BrightnessContrastDialog * brightness_contrast_dialog_new (void);
static void brightness_contrast_update (BrightnessContrastDialog *,
gint);
static void brightness_contrast_preview (BrightnessContrastDialog *);
static void brightness_contrast_reset_callback (GtkWidget *, gpointer);
static void brightness_contrast_ok_callback (GtkWidget *, gpointer);
static void brightness_contrast_cancel_callback (GtkWidget *, gpointer);
static void brightness_contrast_preview_update (GtkWidget *, gpointer);
static void brightness_contrast_brightness_adjustment_update (GtkAdjustment *,
gpointer);
static void brightness_contrast_contrast_adjustment_update (GtkAdjustment *,
gpointer);
/* brightness-contrast select action functions */
static void
brightness_contrast_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
switch (action)
{
case PAUSE:
break;
case RESUME:
break;
case HALT:
brightness_contrast_dialog_hide ();
break;
default:
break;
}
}
Tool *
tools_new_brightness_contrast (void)
{
Tool * tool;
BrightnessContrast * private;
/* The tool options */
if (!brightness_contrast_options)
{
brightness_contrast_options =
tool_options_new (_("Brightness-Contrast"));
tools_register (BRIGHTNESS_CONTRAST, brightness_contrast_options);
}
tool = tools_new_tool (BRIGHTNESS_CONTRAST);
private = g_new0 (BrightnessContrast, 1);
tool->scroll_lock = TRUE; /* Disallow scrolling */
tool->preserve = FALSE; /* Don't preserve on drawable change */
tool->private = (void *) private;
tool->control_func = brightness_contrast_control;
return tool;
}
void
brightness_contrast_dialog_hide (void)
{
if (brightness_contrast_dialog)
brightness_contrast_cancel_callback (NULL,
(gpointer) brightness_contrast_dialog);
}
void
tools_free_brightness_contrast (Tool *tool)
{
BrightnessContrast * bc;
bc = (BrightnessContrast *) tool->private;
/* Close the brightness-contrast dialog */
brightness_contrast_dialog_hide ();
g_free (bc);
}
void
brightness_contrast_initialize (GDisplay *gdisp)
{
if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage)))
{
g_message (_("Brightness-Contrast does not operate on indexed drawables."));
return;
}
/* The brightness-contrast dialog */
if (!brightness_contrast_dialog)
brightness_contrast_dialog = brightness_contrast_dialog_new ();
else
if (!GTK_WIDGET_VISIBLE (brightness_contrast_dialog->shell))
gtk_widget_show (brightness_contrast_dialog->shell);
brightness_contrast_dialog->brightness = 0.0;
brightness_contrast_dialog->contrast = 0.0;
brightness_contrast_dialog->drawable =
gimp_image_active_drawable (gdisp->gimage);
brightness_contrast_dialog->image_map =
image_map_create (gdisp, brightness_contrast_dialog->drawable);
brightness_contrast_update (brightness_contrast_dialog, ALL);
}
/********************************/
/* Brightness Contrast dialog */
/********************************/
static BrightnessContrastDialog *
brightness_contrast_dialog_new (void)
{
BrightnessContrastDialog *bcd;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *table;
GtkWidget *label;
GtkWidget *abox;
GtkWidget *spinbutton;
GtkWidget *slider;
GtkWidget *toggle;
GtkObject *data;
bcd = g_new (BrightnessContrastDialog, 1);
bcd->preview = TRUE;
bcd->lut = gimp_lut_new ();
/* The shell and main vbox */
bcd->shell =
gimp_dialog_new (_("Brightness-Contrast"), "brightness_contrast",
tools_help_func, NULL,
GTK_WIN_POS_NONE,
FALSE, TRUE, FALSE,
_("OK"), brightness_contrast_ok_callback,
bcd, NULL, NULL, TRUE, FALSE,
_("Reset"), brightness_contrast_reset_callback,
bcd, NULL, NULL, TRUE, FALSE,
_("Cancel"), brightness_contrast_cancel_callback,
bcd, NULL, NULL, FALSE, TRUE,
NULL);
vbox = gtk_vbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (bcd->shell)->vbox), vbox);
/* The table containing sliders */
table = gtk_table_new (2, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
/* Create the brightness scale widget */
label = gtk_label_new (_("Brightness:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
data = gtk_adjustment_new (0, -127, 127.0, 1.0, 10.0, 0.0);
bcd->brightness_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1);
abox = gtk_vbox_new (FALSE, 0);
spinbutton = gtk_spin_button_new (bcd->brightness_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (data), "value_changed",
GTK_SIGNAL_FUNC (brightness_contrast_brightness_adjustment_update),
bcd);
gtk_widget_show (label);
gtk_widget_show (slider);
gtk_widget_show (spinbutton);
gtk_widget_show (abox);
/* Create the contrast scale widget */
label = gtk_label_new (_("Contrast:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
data = gtk_adjustment_new (0, -127.0, 127.0, 1.0, 10.0, 0.0);
bcd->contrast_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2);
abox = gtk_vbox_new (FALSE, 0);
spinbutton = gtk_spin_button_new (bcd->contrast_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (data), "value_changed",
GTK_SIGNAL_FUNC (brightness_contrast_contrast_adjustment_update),
bcd);
gtk_widget_show (label);
gtk_widget_show (slider);
gtk_widget_show (spinbutton);
gtk_widget_show (abox);
/* Horizontal box for preview toggle button */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
/* The preview toggle */
toggle = gtk_check_button_new_with_label (_("Preview"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bcd->preview);
gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
GTK_SIGNAL_FUNC (brightness_contrast_preview_update),
bcd);
gtk_widget_show (toggle);
gtk_widget_show (hbox);
gtk_widget_show (table);
gtk_widget_show (vbox);
gtk_widget_show (bcd->shell);
return bcd;
}
static void
brightness_contrast_update (BrightnessContrastDialog *bcd,
gint update)
{
if (update & BRIGHTNESS)
{
gtk_adjustment_set_value (bcd->brightness_data, bcd->brightness);
}
if (update & CONTRAST)
{
gtk_adjustment_set_value (bcd->contrast_data, bcd->contrast);
}
}
static void
brightness_contrast_preview (BrightnessContrastDialog *bcd)
{
if (!bcd->image_map)
{
g_message ("brightness_contrast_preview(): No image map");
return;
}
active_tool->preserve = TRUE;
brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0,
bcd->contrast / 127.0,
gimp_drawable_bytes (bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
(void *) bcd->lut);
active_tool->preserve = FALSE;
}
static void
brightness_contrast_reset_callback (GtkWidget *widget,
gpointer data)
{
BrightnessContrastDialog *bcd;
bcd = (BrightnessContrastDialog *) data;
bcd->brightness = 0.0;
bcd->contrast = 0.0;
brightness_contrast_update (bcd, ALL);
if (bcd->preview)
brightness_contrast_preview (bcd);
}
static void
brightness_contrast_ok_callback (GtkWidget *widget,
gpointer data)
{
BrightnessContrastDialog *bcd;
bcd = (BrightnessContrastDialog *) data;
gimp_dialog_hide (bcd->shell);
active_tool->preserve = TRUE;
if (!bcd->preview)
{
brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0,
bcd->contrast / 127.0,
gimp_drawable_bytes (bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
(void *) bcd->lut);
}
if (bcd->image_map)
image_map_commit (bcd->image_map);
active_tool->preserve = FALSE;
bcd->image_map = NULL;
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
brightness_contrast_cancel_callback (GtkWidget *widget,
gpointer data)
{
BrightnessContrastDialog *bcd;
bcd = (BrightnessContrastDialog *) data;
gimp_dialog_hide (bcd->shell);
if (bcd->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (bcd->image_map);
active_tool->preserve = FALSE;
bcd->image_map = NULL;
gdisplays_flush ();
}
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
brightness_contrast_preview_update (GtkWidget *widget,
gpointer data)
{
BrightnessContrastDialog *bcd;
bcd = (BrightnessContrastDialog *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
{
bcd->preview = TRUE;
brightness_contrast_preview (bcd);
}
else
{
bcd->preview = FALSE;
if (bcd->image_map)
{
active_tool->preserve = TRUE;
image_map_clear (bcd->image_map);
active_tool->preserve = FALSE;
gdisplays_flush ();
}
}
}
static void
brightness_contrast_brightness_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
BrightnessContrastDialog *bcd;
bcd = (BrightnessContrastDialog *) data;
if (bcd->brightness != adjustment->value)
{
bcd->brightness = adjustment->value;
if (bcd->preview)
brightness_contrast_preview (bcd);
}
}
static void
brightness_contrast_contrast_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
BrightnessContrastDialog *bcd;
bcd = (BrightnessContrastDialog *) data;
if (bcd->contrast != adjustment->value)
{
bcd->contrast = adjustment->value;
if (bcd->preview)
brightness_contrast_preview (bcd);
}
}

View File

@ -1,31 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BRIGHTNESS_CONTRAST_H__
#define __BRIGHTNESS_CONTRAST_H__
Tool * tools_new_brightness_contrast (void);
void tools_free_brightness_contrast (Tool *tool);
void brightness_contrast_dialog_hide (void);
void brightness_contrast_initialize (GDisplay *gdisp);
#endif /* __BRIGHTNESS_CONTRAST_H__ */

View File

@ -37,10 +37,11 @@
#include "gimplist.h"
#include "gimprc.h"
#include "gimpui.h"
#include "paint_options.h"
#include "session.h"
#include "temp_buf.h"
#include "tools/paint_options.h"
#include "pdb/procedural_db.h"
#include "libgimp/gimphelpui.h"

View File

@ -1,663 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "apptypes.h"
#include "appenv.h"
#include "bucket_fill.h"
#include "channel.h"
#include "cursorutil.h"
#include "drawable.h"
#include "fuzzy_select.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimage_mask.h"
#include "gimpcontext.h"
#include "gimprc.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "paint_options.h"
#include "patterns.h"
#include "pixel_region.h"
#include "selection.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "pdb/procedural_db.h"
#include "libgimp/gimpintl.h"
/* the bucket fill structures */
typedef struct _BucketTool BucketTool;
struct _BucketTool
{
gint target_x; /* starting x coord */
gint target_y; /* starting y coord */
};
typedef struct _BucketOptions BucketOptions;
struct _BucketOptions
{
PaintOptions paint_options;
gboolean sample_merged;
gboolean sample_merged_d;
GtkWidget *sample_merged_w;
gdouble threshold;
/* gdouble threshold_d; (from gimprc) */
GtkObject *threshold_w;
BucketFillMode fill_mode;
BucketFillMode fill_mode_d;
GtkWidget *fill_mode_w[3];
};
/* the bucket fill tool options */
static BucketOptions *bucket_options = NULL;
/* local function prototypes */
static void bucket_fill_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void bucket_fill_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void bucket_fill_cursor_update (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp);
static void bucket_fill_line_color (guchar *,
guchar *,
guchar *,
gboolean ,
gint ,
gint );
static void bucket_fill_line_pattern (guchar *,
guchar *,
TempBuf *,
gboolean ,
gint ,
gint ,
gint ,
gint );
/* functions */
static void
bucket_options_reset (void)
{
BucketOptions *options = bucket_options;
paint_options_reset ((PaintOptions *) options);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
options->sample_merged_d);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->threshold_w),
default_threshold);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->fill_mode_w[options->fill_mode_d]), TRUE);
}
static BucketOptions *
bucket_options_new (void)
{
BucketOptions *options;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *scale;
GtkWidget *frame;
/* the new bucket fill tool options structure */
options = g_new (BucketOptions, 1);
paint_options_init ((PaintOptions *) options,
BUCKET_FILL,
bucket_options_reset);
options->sample_merged = options->sample_merged_d = FALSE;
options->threshold = default_threshold;
options->fill_mode = options->fill_mode_d = FG_BUCKET_FILL;
/* the main vbox */
vbox = ((ToolOptions *) options)->main_vbox;
/* the sample merged toggle */
options->sample_merged_w =
gtk_check_button_new_with_label (_("Sample Merged"));
gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled",
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&options->sample_merged);
gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0);
gtk_widget_show (options->sample_merged_w);
/* the threshold scale */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Threshold:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
options->threshold_w =
gtk_adjustment_new (default_threshold, 1.0, 255.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w));
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (options->threshold_w), "value_changed",
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
&options->threshold);
gtk_widget_show (scale);
gtk_widget_show (hbox);
/* fill type */
frame =
gimp_radio_group_new2 (TRUE, _("Fill Type"),
gimp_radio_button_update,
&options->fill_mode, (gpointer) options->fill_mode,
_("FG Color Fill"),
(gpointer) FG_BUCKET_FILL,
&options->fill_mode_w[0],
_("BG Color Fill"),
(gpointer) BG_BUCKET_FILL,
&options->fill_mode_w[1],
_("Pattern Fill"),
(gpointer) PATTERN_BUCKET_FILL,
&options->fill_mode_w[2],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
return options;
}
/* bucket fill action functions */
static void
bucket_fill_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
BucketTool *bucket_tool;
gboolean use_offsets;
bucket_tool = (BucketTool *) tool->private;
use_offsets = (bucket_options->sample_merged) ? FALSE : TRUE;
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
&bucket_tool->target_x,
&bucket_tool->target_y, FALSE, use_offsets);
/* Make the tool active and set the gdisplay which owns it */
gdk_pointer_grab (gdisp->canvas->window, FALSE,
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK,
NULL, NULL, bevent->time);
/* Make the tool active and set the gdisplay which owns it */
tool->gdisp = gdisp;
tool->state = ACTIVE;
}
static void
bucket_fill_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
BucketTool *bucket_tool;
Argument *return_vals;
gint nreturn_vals;
bucket_tool = (BucketTool *) tool->private;
gdk_pointer_ungrab (bevent->time);
gdk_flush ();
/* if the 3rd button isn't pressed, fill the selected region */
if (! (bevent->state & GDK_BUTTON3_MASK))
{
return_vals =
procedural_db_run_proc ("gimp_bucket_fill",
&nreturn_vals,
PDB_DRAWABLE, gimp_drawable_get_ID (gimp_image_active_drawable (gdisp->gimage)),
PDB_INT32, (gint32) bucket_options->fill_mode,
PDB_INT32, (gint32) gimp_context_get_paint_mode (NULL),
PDB_FLOAT, (gdouble) gimp_context_get_opacity (NULL) * 100,
PDB_FLOAT, (gdouble) bucket_options->threshold,
PDB_INT32, (gint32) bucket_options->sample_merged,
PDB_FLOAT, (gdouble) bucket_tool->target_x,
PDB_FLOAT, (gdouble) bucket_tool->target_y,
PDB_END);
if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS)
gdisplays_flush ();
else
g_message (_("Bucket Fill operation failed."));
procedural_db_destroy_args (return_vals, nreturn_vals);
}
tool->state = INACTIVE;
}
static void
bucket_fill_cursor_update (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
Layer *layer;
GdkCursorType ctype = GDK_TOP_LEFT_ARROW;
CursorModifier cmodifier = CURSOR_MODIFIER_NONE;
gint x, y;
gint off_x, off_y;
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
&x, &y, FALSE, FALSE);
if ((layer = gimp_image_get_active_layer (gdisp->gimage)))
{
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
if (x >= off_x && y >= off_y &&
x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) &&
y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer))))
{
/* One more test--is there a selected region?
* if so, is cursor inside?
*/
if (gimage_mask_is_empty (gdisp->gimage) ||
gimage_mask_value (gdisp->gimage, x, y))
{
ctype = GIMP_MOUSE_CURSOR;
switch (bucket_options->fill_mode)
{
case FG_BUCKET_FILL:
cmodifier = CURSOR_MODIFIER_FOREGROUND;
break;
case BG_BUCKET_FILL:
cmodifier = CURSOR_MODIFIER_BACKGROUND;
break;
case PATTERN_BUCKET_FILL:
cmodifier = CURSOR_MODIFIER_PATTERN;
break;
}
}
}
}
gdisplay_install_tool_cursor (gdisp, ctype,
BUCKET_FILL,
cmodifier,
FALSE);
}
static void
bucket_fill_modifier_key_func (Tool *tool,
GdkEventKey *kevent,
GDisplay *gdisp)
{
switch (kevent->keyval)
{
case GDK_Alt_L: case GDK_Alt_R:
break;
case GDK_Shift_L: case GDK_Shift_R:
break;
case GDK_Control_L: case GDK_Control_R:
switch (bucket_options->fill_mode)
{
case FG_BUCKET_FILL:
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[BG_BUCKET_FILL]), TRUE);
break;
case BG_BUCKET_FILL:
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[FG_BUCKET_FILL]), TRUE);
break;
default:
break;
}
break;
}
}
void
bucket_fill (GimpImage *gimage,
GimpDrawable *drawable,
BucketFillMode fill_mode,
gint paint_mode,
gdouble opacity,
gdouble threshold,
gboolean sample_merged,
gdouble x,
gdouble y)
{
TileManager *buf_tiles;
PixelRegion bufPR, maskPR;
Channel *mask = NULL;
gint bytes;
gboolean has_alpha;
gint x1, y1, x2, y2;
guchar col [MAX_CHANNELS];
guchar *d1, *d2;
GPattern *pattern;
TempBuf *pat_buf;
gboolean new_buf = FALSE;
pat_buf = NULL;
if (fill_mode == FG_BUCKET_FILL)
gimp_image_get_foreground (gimage, drawable, col);
else if (fill_mode == BG_BUCKET_FILL)
gimp_image_get_background (gimage, drawable, col);
else if (fill_mode == PATTERN_BUCKET_FILL)
{
pattern = gimp_context_get_pattern (NULL);
if (!pattern)
{
g_message (_("No available patterns for this operation."));
return;
}
/* If the pattern doesn't match the image in terms of color type,
* transform it. (ie pattern is RGB, image is indexed)
*/
if (((pattern->mask->bytes == 3) && !gimp_drawable_is_rgb (drawable)) ||
((pattern->mask->bytes == 1) && !gimp_drawable_is_gray (drawable)))
{
int size;
if ((pattern->mask->bytes == 1) && gimp_drawable_is_rgb (drawable))
pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height,
3, 0, 0, NULL);
else
pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height,
1, 0, 0, NULL);
d1 = temp_buf_data (pattern->mask);
d2 = temp_buf_data (pat_buf);
size = pattern->mask->width * pattern->mask->height;
while (size--)
{
gimp_image_transform_color (gimage, drawable, d1, d2,
(pattern->mask->bytes == 3) ? RGB : GRAY);
d1 += pattern->mask->bytes;
d2 += pat_buf->bytes;
}
new_buf = TRUE;
}
else
pat_buf = pattern->mask;
}
gimp_add_busy_cursors ();
bytes = gimp_drawable_bytes (drawable);
has_alpha = gimp_drawable_has_alpha (drawable);
/* If there is no selection mask, the do a seed bucket
* fill...To do this, calculate a new contiguous region
*/
if (! gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2))
{
mask = find_contiguous_region (gimage, drawable, TRUE, (int) threshold,
(int) x, (int) y, sample_merged);
channel_bounds (mask, &x1, &y1, &x2, &y2);
/* make sure we handle the mask correctly if it was sample-merged */
if (sample_merged)
{
gint off_x, off_y;
/* Limit the channel bounds to the drawable's extents */
gimp_drawable_offsets (drawable, &off_x, &off_y);
x1 = CLAMP (x1, off_x, (off_x + gimp_drawable_width (drawable)));
y1 = CLAMP (y1, off_y, (off_y + gimp_drawable_height (drawable)));
x2 = CLAMP (x2, off_x, (off_x + gimp_drawable_width (drawable)));
y2 = CLAMP (y2, off_y, (off_y + gimp_drawable_height (drawable)));
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
/* translate mask bounds to drawable coords */
x1 -= off_x;
y1 -= off_y;
x2 -= off_x;
y2 -= off_y;
}
else
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
/* if the gimage doesn't have an alpha channel,
* make sure that the temp buf does. We need the
* alpha channel to fill with the region calculated above
*/
if (! has_alpha)
{
bytes ++;
has_alpha = TRUE;
}
}
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
if (mask)
bucket_fill_region (fill_mode, &bufPR, &maskPR, col, pat_buf, x1, y1, has_alpha);
else
bucket_fill_region (fill_mode, &bufPR, NULL, col, pat_buf, x1, y1, has_alpha);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimp_image_apply_image (gimage, drawable, &bufPR, TRUE,
(opacity * 255) / 100, paint_mode, NULL, x1, y1);
/* update the image */
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
/* free the temporary buffer */
tile_manager_destroy (buf_tiles);
/* free the mask */
if (mask)
channel_delete (mask);
if (new_buf)
temp_buf_free (pat_buf);
gimp_remove_busy_cursors (NULL);
}
static void
bucket_fill_line_color (guchar *buf,
guchar *mask,
guchar *col,
gboolean has_alpha,
gint bytes,
gint width)
{
gint alpha, b;
alpha = (has_alpha) ? bytes - 1 : bytes;
while (width--)
{
for (b = 0; b < alpha; b++)
buf[b] = col[b];
if (has_alpha)
{
if (mask)
buf[alpha] = *mask++;
else
buf[alpha] = OPAQUE_OPACITY;
}
buf += bytes;
}
}
static void
bucket_fill_line_pattern (guchar *buf,
guchar *mask,
TempBuf *pattern,
gboolean has_alpha,
gint bytes,
gint x,
gint y,
gint width)
{
guchar *pat, *p;
gint alpha, b;
gint i;
/* Get a pointer to the appropriate scanline of the pattern buffer */
pat = temp_buf_data (pattern) +
(y % pattern->height) * pattern->width * pattern->bytes;
alpha = (has_alpha) ? bytes - 1 : bytes;
for (i = 0; i < width; i++)
{
p = pat + ((i + x) % pattern->width) * pattern->bytes;
for (b = 0; b < alpha; b++)
buf[b] = p[b];
if (has_alpha)
{
if (mask)
buf[alpha] = *mask++;
else
buf[alpha] = OPAQUE_OPACITY;
}
buf += bytes;
}
}
void
bucket_fill_region (BucketFillMode fill_mode,
PixelRegion *bufPR,
PixelRegion *maskPR,
guchar *col,
TempBuf *pattern,
gint off_x,
gint off_y,
gboolean has_alpha)
{
guchar *s, *m;
gint y;
void *pr;
for (pr = pixel_regions_register (2, bufPR, maskPR);
pr != NULL;
pr = pixel_regions_process (pr))
{
s = bufPR->data;
if (maskPR)
m = maskPR->data;
else
m = NULL;
for (y = 0; y < bufPR->h; y++)
{
switch (fill_mode)
{
case FG_BUCKET_FILL:
case BG_BUCKET_FILL:
bucket_fill_line_color (s, m, col, has_alpha, bufPR->bytes, bufPR->w);
break;
case PATTERN_BUCKET_FILL:
bucket_fill_line_pattern (s, m, pattern, has_alpha, bufPR->bytes,
off_x + bufPR->x, off_y + y + bufPR->y, bufPR->w);
break;
}
s += bufPR->rowstride;
if (maskPR)
m += maskPR->rowstride;
}
}
}
/**********************************/
/* Global bucket fill functions */
/**********************************/
Tool *
tools_new_bucket_fill (void)
{
Tool *tool;
BucketTool *private;
/* The tool options */
if (! bucket_options)
{
bucket_options = bucket_options_new ();
tools_register (BUCKET_FILL, (ToolOptions *) bucket_options);
/* press all default buttons */
bucket_options_reset ();
}
tool = tools_new_tool (BUCKET_FILL);
private = g_new0 (BucketTool, 1);
tool->scroll_lock = TRUE; /* Disallow scrolling */
tool->private = (gpointer) private;
tool->button_press_func = bucket_fill_button_press;
tool->button_release_func = bucket_fill_button_release;
tool->modifier_key_func = bucket_fill_modifier_key_func;
tool->cursor_update_func = bucket_fill_cursor_update;
return tool;
}
void
tools_free_bucket_fill (Tool *tool)
{
BucketTool *bucket_tool;
bucket_tool = (BucketTool *) tool->private;
g_free (bucket_tool);
}

View File

@ -1,54 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BUCKET_FILL_H__
#define __BUCKET_FILL_H__
typedef enum
{
FG_BUCKET_FILL,
BG_BUCKET_FILL,
PATTERN_BUCKET_FILL
} BucketFillMode;
void bucket_fill (GimpImage *gimage,
GimpDrawable *drawable,
BucketFillMode fill_mode,
gint paint_mode,
gdouble opacity,
gdouble threshold,
gboolean sample_merged,
gdouble x,
gdouble y);
void bucket_fill_region (BucketFillMode fill_mode,
PixelRegion *bufPR,
PixelRegion *maskPR,
guchar *col,
TempBuf *pattern,
gint off_x,
gint off_y,
gboolean has_alpha);
Tool * tools_new_bucket_fill (void);
void tools_free_bucket_fill (Tool *tool);
#endif /* __BUCKET_FILL_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BY_COLOR_SELECT_H__
#define __BY_COLOR_SELECT_H__
Tool * tools_new_by_color_select (void);
void tools_free_by_color_select (Tool *tool);
void by_color_select_initialize (GDisplay *gdisp);
void by_color_select_initialize_by_image (GImage *gimage);
void by_color_select (GimpImage *gimage,
GimpDrawable *drawable,
guchar *color,
gint threshold,
SelectOps op,
gboolean antialias,
gboolean feather,
gdouble feather_radius,
gboolean sample_merged);
#endif /* __BY_COLOR_SELECT_H__ */

View File

@ -1,773 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "draw_core.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "gimpcontext.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "paint_options.h"
#include "patterns.h"
#include "pixel_region.h"
#include "clone.h"
#include "selection.h"
#include "temp_buf.h"
#include "tools.h"
#include "cursorutil.h"
#include "libgimp/gimpintl.h"
#define TARGET_HEIGHT 15
#define TARGET_WIDTH 15
/* default types */
#define CLONE_DEFAULT_TYPE IMAGE_CLONE
#define CLONE_DEFAULT_ALIGNED ALIGN_NO
/* the clone structures */
typedef enum
{
ALIGN_NO,
ALIGN_YES,
ALIGN_REGISTERED
} AlignType;
typedef struct _CloneOptions CloneOptions;
struct _CloneOptions
{
PaintOptions paint_options;
CloneType type;
CloneType type_d;
GtkWidget *type_w[2]; /* 2 radio buttons */
AlignType aligned;
AlignType aligned_d;
GtkWidget *aligned_w[3]; /* 3 radio buttons */
};
/* forward function declarations */
static gpointer clone_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state);
static void clone_draw (Tool *tool);
static void clone_motion (PaintCore *paint_core,
GimpDrawable *drawable,
GimpDrawable *src_drawable,
PaintPressureOptions *pressure_options,
CloneType type,
gint offset_x,
gint offset_y);
static void clone_line_image (GImage *dest,
GImage *src,
GimpDrawable *d_drawable,
GimpDrawable *s_drawable,
guchar *s,
guchar *d,
gint has_alpha,
gint src_bytes,
gint dest_bytes,
gint width);
static void clone_line_pattern (GImage *dest,
GimpDrawable *drawable,
GPattern *pattern,
guchar *d,
gint x,
gint y,
gint bytes,
gint width);
/* the clone tool options */
static CloneOptions *clone_options = NULL;
/* local variables */
static gint src_x = 0; /* */
static gint src_y = 0; /* position of clone src */
static gint dest_x = 0; /* */
static gint dest_y = 0; /* position of clone src */
static gint offset_x = 0; /* */
static gint offset_y = 0; /* offset for cloning */
static gint first = TRUE;
static gint trans_tx, trans_ty; /* transformed target */
static GDisplay *the_src_gdisp = NULL; /* ID of source gdisplay */
static GimpDrawable *src_drawable_ = NULL; /* source drawable */
static GimpDrawable *non_gui_src_drawable;
static gint non_gui_offset_x;
static gint non_gui_offset_y;
static CloneType non_gui_type;
/* functions */
static void
clone_options_reset (void)
{
CloneOptions *options = clone_options;
paint_options_reset ((PaintOptions *) options);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->aligned_w[options->aligned_d]), TRUE);
}
static CloneOptions *
clone_options_new (void)
{
CloneOptions *options;
GtkWidget *vbox;
GtkWidget *frame;
/* the new clone tool options structure */
options = g_new (CloneOptions, 1);
paint_options_init ((PaintOptions *) options,
CLONE,
clone_options_reset);
options->type = options->type_d = CLONE_DEFAULT_TYPE;
options->aligned = options->aligned_d = CLONE_DEFAULT_ALIGNED;
/* the main vbox */
vbox = ((ToolOptions *) options)->main_vbox;
frame = gimp_radio_group_new2 (TRUE, _("Source"),
gimp_radio_button_update,
&options->type, (gpointer) options->type,
_("Image Source"), (gpointer) IMAGE_CLONE,
&options->type_w[0],
_("Pattern Source"), (gpointer) PATTERN_CLONE,
&options->type_w[1],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
frame = gimp_radio_group_new2 (TRUE, _("Alignment"),
gimp_radio_button_update,
&options->aligned, (gpointer) options->aligned,
_("Non Aligned"), (gpointer) ALIGN_NO,
&options->aligned_w[0],
_("Aligned"), (gpointer) ALIGN_YES,
&options->aligned_w[1],
_("Registered"), (gpointer) ALIGN_REGISTERED,
&options->aligned_w[2],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
return options;
}
static void
clone_src_drawable_destroyed_cb (GimpDrawable *drawable,
GimpDrawable **src_drawable)
{
if (drawable == *src_drawable)
{
*src_drawable = NULL;
the_src_gdisp = NULL;
}
}
static void
clone_set_src_drawable (GimpDrawable *drawable)
{
if (src_drawable_ == drawable)
return;
if (src_drawable_)
gtk_signal_disconnect_by_data (GTK_OBJECT (src_drawable_), &src_drawable_);
src_drawable_ = drawable;
if (drawable)
{
gtk_signal_connect (GTK_OBJECT (drawable), "destroy",
GTK_SIGNAL_FUNC (clone_src_drawable_destroyed_cb),
&src_drawable_);
}
}
static gpointer
clone_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
GDisplay *gdisp;
GDisplay *src_gdisp;
gint x1, y1, x2, y2;
static gint orig_src_x, orig_src_y;
gdisp = (GDisplay *) active_tool->gdisp;
switch (state)
{
case PRETRACE_PAINT:
draw_core_pause (paint_core->core, active_tool);
break;
case MOTION_PAINT:
x1 = paint_core->curx;
y1 = paint_core->cury;
x2 = paint_core->lastx;
y2 = paint_core->lasty;
/* If the control key is down, move the src target and return */
if (paint_core->state & GDK_CONTROL_MASK)
{
src_x = x1;
src_y = y1;
first = TRUE;
}
/* otherwise, update the target */
else
{
dest_x = x1;
dest_y = y1;
if (clone_options->aligned == ALIGN_REGISTERED)
{
offset_x = 0;
offset_y = 0;
}
else if (first)
{
offset_x = src_x - dest_x;
offset_y = src_y - dest_y;
first = FALSE;
}
src_x = dest_x + offset_x;
src_y = dest_y + offset_y;
clone_motion (paint_core, drawable, src_drawable_,
clone_options->paint_options.pressure_options,
clone_options->type, offset_x, offset_y);
}
break;
case INIT_PAINT:
if (paint_core->state & GDK_CONTROL_MASK)
{
the_src_gdisp = gdisp;
clone_set_src_drawable(drawable);
src_x = paint_core->curx;
src_y = paint_core->cury;
first = TRUE;
}
else if (clone_options->aligned == ALIGN_NO)
{
first = TRUE;
orig_src_x = src_x;
orig_src_y = src_y;
}
if (clone_options->type == PATTERN_CLONE)
if (! gimp_context_get_pattern (NULL))
g_message (_("No patterns available for this operation."));
break;
case FINISH_PAINT:
draw_core_stop (paint_core->core, active_tool);
if (clone_options->aligned == ALIGN_NO && !first)
{
src_x = orig_src_x;
src_y = orig_src_y;
}
return NULL;
break;
default:
break;
}
/* Calculate the coordinates of the target */
src_gdisp = the_src_gdisp;
if (!src_gdisp)
{
the_src_gdisp = gdisp;
src_gdisp = the_src_gdisp;
}
if (state == INIT_PAINT)
/* Initialize the tool drawing core */
draw_core_start (paint_core->core,
src_gdisp->canvas->window,
active_tool);
else if (state == POSTTRACE_PAINT)
{
/* Find the target cursor's location onscreen */
gdisplay_transform_coords (src_gdisp, src_x, src_y,
&trans_tx, &trans_ty, 1);
draw_core_resume (paint_core->core, active_tool);
}
return NULL;
}
void
clone_cursor_update (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
Layer *layer;
GdkCursorType ctype = GDK_TOP_LEFT_ARROW;
gint x, y;
gdisplay_untransform_coords (gdisp, (double) mevent->x, (double) mevent->y,
&x, &y, TRUE, FALSE);
if ((layer = gimp_image_get_active_layer (gdisp->gimage)))
{
int off_x, off_y;
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
if (x >= off_x && y >= off_y &&
x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) &&
y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer))))
{
/* One more test--is there a selected region?
* if so, is cursor inside?
*/
if (gimage_mask_is_empty (gdisp->gimage))
ctype = GIMP_MOUSE_CURSOR;
else if (gimage_mask_value (gdisp->gimage, x, y))
ctype = GIMP_MOUSE_CURSOR;
}
}
if (clone_options->type == IMAGE_CLONE)
{
if (mevent->state & GDK_CONTROL_MASK)
ctype = GIMP_CROSSHAIR_SMALL_CURSOR;
else if (!src_drawable_)
ctype = GIMP_BAD_CURSOR;
}
gdisplay_install_tool_cursor (gdisp, ctype,
ctype == GIMP_CROSSHAIR_SMALL_CURSOR ?
TOOL_TYPE_NONE : CLONE,
CURSOR_MODIFIER_NONE,
FALSE);
}
Tool *
tools_new_clone (void)
{
Tool * tool;
PaintCore * private;
/* The tool options */
if (! clone_options)
{
clone_options = clone_options_new ();
tools_register (CLONE, (ToolOptions *) clone_options);
/* press all default buttons */
clone_options_reset ();
}
tool = paint_core_new (CLONE);
/* the clone tool provides its own cursor_update_function
until I figure out somethinh nicer -- Sven */
tool->cursor_update_func = clone_cursor_update;
private = (PaintCore *) tool->private;
private->paint_func = clone_paint_func;
private->core->draw_func = clone_draw;
private->flags |= TOOL_TRACES_ON_WINDOW;
return tool;
}
void
tools_free_clone (Tool *tool)
{
paint_core_free (tool);
}
static void
clone_draw (Tool *tool)
{
PaintCore * paint_core;
paint_core = (PaintCore *) tool->private;
if (paint_core->core->gc != NULL && clone_options->type == IMAGE_CLONE)
{
gdk_draw_line (paint_core->core->win, paint_core->core->gc,
trans_tx - (TARGET_WIDTH >> 1), trans_ty,
trans_tx + (TARGET_WIDTH >> 1), trans_ty);
gdk_draw_line (paint_core->core->win, paint_core->core->gc,
trans_tx, trans_ty - (TARGET_HEIGHT >> 1),
trans_tx, trans_ty + (TARGET_HEIGHT >> 1));
}
}
static void
clone_motion (PaintCore *paint_core,
GimpDrawable *drawable,
GimpDrawable *src_drawable,
PaintPressureOptions *pressure_options,
CloneType type,
int offset_x,
int offset_y)
{
GImage *gimage;
GImage *src_gimage = NULL;
unsigned char * s;
unsigned char * d;
TempBuf * orig;
TempBuf * area;
void * pr;
int y;
int x1, y1, x2, y2;
int has_alpha = -1;
PixelRegion srcPR, destPR;
GPattern *pattern;
gint opacity;
gdouble scale;
pr = NULL;
pattern = NULL;
/* Make sure we still have a source if we are doing image cloning */
if (type == IMAGE_CLONE)
{
if (!src_drawable)
return;
if (! (src_gimage = gimp_drawable_gimage (src_drawable)))
return;
/* Determine whether the source image has an alpha channel */
has_alpha = gimp_drawable_has_alpha (src_drawable);
}
/* We always need a destination image */
if (! (gimage = gimp_drawable_gimage (drawable)))
return;
if (pressure_options->size)
scale = paint_core->curpressure;
else
scale = 1.0;
/* Get a region which can be used to paint to */
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
return;
switch (type)
{
case IMAGE_CLONE:
/* Set the paint area to transparent */
temp_buf_data_clear (area);
/* If the source gimage is different from the destination,
* then we should copy straight from the destination image
* to the canvas.
* Otherwise, we need a call to get_orig_image to make sure
* we get a copy of the unblemished (offset) image
*/
if (src_drawable != drawable)
{
x1 = CLAMP (area->x + offset_x, 0, gimp_drawable_width (src_drawable));
y1 = CLAMP (area->y + offset_y, 0, gimp_drawable_height (src_drawable));
x2 = CLAMP (area->x + offset_x + area->width,
0, gimp_drawable_width (src_drawable));
y2 = CLAMP (area->y + offset_y + area->height,
0, gimp_drawable_height (src_drawable));
if (!(x2 - x1) || !(y2 - y1))
return;
pixel_region_init (&srcPR, gimp_drawable_data (src_drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
}
else
{
x1 = CLAMP (area->x + offset_x, 0, gimp_drawable_width (drawable));
y1 = CLAMP (area->y + offset_y, 0, gimp_drawable_height (drawable));
x2 = CLAMP (area->x + offset_x + area->width,
0, gimp_drawable_width (drawable));
y2 = CLAMP (area->y + offset_y + area->height,
0, gimp_drawable_height (drawable));
if (!(x2 - x1) || !(y2 - y1))
return;
/* get the original image */
orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2);
srcPR.bytes = orig->bytes;
srcPR.x = 0; srcPR.y = 0;
srcPR.w = x2 - x1;
srcPR.h = y2 - y1;
srcPR.rowstride = srcPR.bytes * orig->width;
srcPR.data = temp_buf_data (orig);
}
offset_x = x1 - (area->x + offset_x);
offset_y = y1 - (area->y + offset_y);
/* configure the destination */
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = srcPR.w;
destPR.h = srcPR.h;
destPR.rowstride = destPR.bytes * area->width;
destPR.data = temp_buf_data (area) + offset_y * destPR.rowstride +
offset_x * destPR.bytes;
pr = pixel_regions_register (2, &srcPR, &destPR);
break;
case PATTERN_CLONE:
pattern = gimp_context_get_pattern (NULL);
if (!pattern)
return;
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = area->width;
destPR.h = area->height;
destPR.rowstride = destPR.bytes * area->width;
destPR.data = temp_buf_data (area);
pr = pixel_regions_register (1, &destPR);
break;
}
for (; pr != NULL; pr = pixel_regions_process (pr))
{
s = srcPR.data;
d = destPR.data;
for (y = 0; y < destPR.h; y++)
{
switch (type)
{
case IMAGE_CLONE:
clone_line_image (gimage, src_gimage, drawable, src_drawable, s, d,
has_alpha, srcPR.bytes, destPR.bytes, destPR.w);
s += srcPR.rowstride;
break;
case PATTERN_CLONE:
clone_line_pattern (gimage, drawable, pattern, d,
area->x + offset_x, area->y + y + offset_y,
destPR.bytes, destPR.w);
break;
}
d += destPR.rowstride;
}
}
opacity = 255.0 * gimp_context_get_opacity (NULL);
if (pressure_options->opacity)
opacity = opacity * 2.0 * paint_core->curpressure;
/* paste the newly painted canvas to the gimage which is being worked on */
paint_core_paste_canvas (paint_core, drawable,
MIN (opacity, 255),
(int) (gimp_context_get_opacity (NULL) * 255),
gimp_context_get_paint_mode (NULL),
pressure_options->pressure ? PRESSURE : SOFT,
scale, CONSTANT);
}
static void
clone_line_image (GImage *dest,
GImage *src,
GimpDrawable *d_drawable,
GimpDrawable *s_drawable,
unsigned char *s,
unsigned char *d,
int has_alpha,
int src_bytes,
int dest_bytes,
int width)
{
unsigned char rgb[3];
int src_alpha, dest_alpha;
src_alpha = src_bytes - 1;
dest_alpha = dest_bytes - 1;
while (width--)
{
gimp_image_get_color (src, gimp_drawable_type (s_drawable), rgb, s);
gimp_image_transform_color (dest, d_drawable, rgb, d, RGB);
if (has_alpha)
d[dest_alpha] = s[src_alpha];
else
d[dest_alpha] = OPAQUE_OPACITY;
s += src_bytes;
d += dest_bytes;
}
}
static void
clone_line_pattern (GImage *dest,
GimpDrawable *drawable,
GPattern *pattern,
unsigned char *d,
int x,
int y,
int bytes,
int width)
{
guchar *pat, *p;
gint color, alpha;
gint i;
/* Make sure x, y are positive */
while (x < 0)
x += pattern->mask->width;
while (y < 0)
y += pattern->mask->height;
/* Get a pointer to the appropriate scanline of the pattern buffer */
pat = temp_buf_data (pattern->mask) +
(y % pattern->mask->height) * pattern->mask->width * pattern->mask->bytes;
color = (pattern->mask->bytes == 3) ? RGB : GRAY;
alpha = bytes - 1;
for (i = 0; i < width; i++)
{
p = pat + ((i + x) % pattern->mask->width) * pattern->mask->bytes;
gimp_image_transform_color (dest, drawable, p, d, color);
d[alpha] = OPAQUE_OPACITY;
d += bytes;
}
}
static gpointer
clone_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
clone_motion (paint_core, drawable, non_gui_src_drawable,
&non_gui_pressure_options,
non_gui_type, non_gui_offset_x, non_gui_offset_y);
return NULL;
}
gboolean
clone_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array)
{
GimpDrawable *src_drawable = NULL;
CloneType clone_type = CLONE_DEFAULT_TYPE;
gdouble local_src_x = 0.0;
gdouble local_src_y = 0.0;
CloneOptions *options = clone_options;
if (options)
{
clone_type = options->type;
src_drawable = src_drawable_;
local_src_x = src_x;
local_src_y = src_y;
}
return clone_non_gui (drawable,
src_drawable,
clone_type,
local_src_x,local_src_y,
num_strokes, stroke_array);
}
gboolean
clone_non_gui (GimpDrawable *drawable,
GimpDrawable *src_drawable,
CloneType clone_type,
gdouble src_x,
gdouble src_y,
gint num_strokes,
gdouble *stroke_array)
{
gint i;
if (paint_core_init (&non_gui_paint_core, drawable,
stroke_array[0], stroke_array[1]))
{
/* Set the paint core's paint func */
non_gui_paint_core.paint_func = clone_non_gui_paint_func;
non_gui_type = clone_type;
non_gui_src_drawable = src_drawable;
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
non_gui_offset_x = (int) (src_x - non_gui_paint_core.startx);
non_gui_offset_y = (int) (src_y - non_gui_paint_core.starty);
clone_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
for (i = 1; i < num_strokes; i++)
{
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
paint_core_interpolate (&non_gui_paint_core, drawable);
non_gui_paint_core.lastx = non_gui_paint_core.curx;
non_gui_paint_core.lasty = non_gui_paint_core.cury;
}
/* Finish the painting */
paint_core_finish (&non_gui_paint_core, drawable, -1);
/* Cleanup */
paint_core_cleanup ();
return TRUE;
}
else
return FALSE;
}

View File

@ -1,44 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CLONE_H__
#define __CLONE_H__
typedef enum
{
IMAGE_CLONE,
PATTERN_CLONE
} CloneType;
gboolean clone_non_gui (GimpDrawable *drawable,
GimpDrawable *src_drawable,
CloneType clone_type,
gdouble src_x,
gdouble src_y,
gint num_strokes,
gdouble *stroke_array);
gboolean clone_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array);
Tool * tools_new_clone (void);
void tools_free_clone (Tool *tool);
#endif /* __CLONE_H__ */

View File

@ -1,749 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "color_balance.h"
#include "color_transfer.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "image_map.h"
#include "pixel_region.h"
#include "tools.h"
#include "tool_options.h"
#include "libgimp/gimpintl.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpcolorspace.h"
#define CYAN_RED 0x1
#define MAGENTA_GREEN 0x2
#define YELLOW_BLUE 0x4
#define ALL (CYAN_RED | MAGENTA_GREEN | YELLOW_BLUE)
/* the color balance structures */
typedef struct _ColorBalance ColorBalance;
struct _ColorBalance
{
gint x, y; /* coords for last mouse click */
};
/* the color balance tool options */
static ToolOptions *color_balance_options = NULL;
/* the color balance dialog */
static ColorBalanceDialog *color_balance_dialog = NULL;
/* color balance action functions */
static void color_balance_control (Tool *tool,
ToolAction action,
GDisplay *gdisp);
static ColorBalanceDialog * color_balance_dialog_new (void);
static void color_balance_update (ColorBalanceDialog *cbd,
gint );
static void color_balance_preview (ColorBalanceDialog *cbd);
static void color_balance_reset_callback (GtkWidget *widget,
gpointer data);
static void color_balance_ok_callback (GtkWidget *widget,
gpointer data);
static void color_balance_cancel_callback (GtkWidget *widget,
gpointer data);
static void color_balance_range_callback (GtkWidget *widget,
gpointer data);
static void color_balance_preserve_update (GtkWidget *widget,
gpointer data);
static void color_balance_preview_update (GtkWidget *widget,
gpointer data);
static void color_balance_cr_adjustment_update (GtkAdjustment *adj,
gpointer data);
static void color_balance_mg_adjustment_update (GtkAdjustment *adj,
gpointer data);
static void color_balance_yb_adjustment_update (GtkAdjustment *adj,
gpointer data);
/* color balance machinery */
void
color_balance (PixelRegion *srcPR,
PixelRegion *destPR,
void *data)
{
ColorBalanceDialog *cbd;
guchar *src, *s;
guchar *dest, *d;
gboolean alpha;
gint r, g, b;
gint r_n, g_n, b_n;
gint w, h;
cbd = (ColorBalanceDialog *) data;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
alpha = (srcPR->bytes == 4) ? TRUE : FALSE;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
r = s[RED_PIX];
g = s[GREEN_PIX];
b = s[BLUE_PIX];
r_n = cbd->r_lookup[r];
g_n = cbd->g_lookup[g];
b_n = cbd->b_lookup[b];
if (cbd->preserve_luminosity)
{
gimp_rgb_to_hls_int (&r_n, &g_n, &b_n);
g_n = gimp_rgb_to_l_int (r, g, b);
gimp_hls_to_rgb_int (&r_n, &g_n, &b_n);
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
/* color balance action functions */
static void
color_balance_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
ColorBalance * color_bal;
color_bal = (ColorBalance *) tool->private;
switch (action)
{
case PAUSE:
break;
case RESUME:
break;
case HALT:
color_balance_dialog_hide ();
break;
default:
break;
}
}
Tool *
tools_new_color_balance (void)
{
Tool * tool;
ColorBalance * private;
/* The tool options */
if (!color_balance_options)
{
color_balance_options = tool_options_new (_("Color Balance"));
tools_register (COLOR_BALANCE, color_balance_options);
}
tool = tools_new_tool (COLOR_BALANCE);
private = g_new0 (ColorBalance, 1);
tool->scroll_lock = TRUE; /* Disallow scrolling */
tool->preserve = FALSE; /* Don't preserve on drawable change */
tool->private = (void *) private;
tool->control_func = color_balance_control;
return tool;
}
void
color_balance_dialog_hide (void)
{
if (color_balance_dialog)
color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog);
}
void
tools_free_color_balance (Tool *tool)
{
ColorBalance * color_bal;
color_bal = (ColorBalance *) tool->private;
/* Close the color select dialog */
color_balance_dialog_hide ();
g_free (color_bal);
}
void
color_balance_initialize (GDisplay *gdisp)
{
gint i;
if (! gimp_drawable_is_rgb (gimp_image_active_drawable (gdisp->gimage)))
{
g_message (_("Color balance operates only on RGB color drawables."));
return;
}
/* The color balance dialog */
if (!color_balance_dialog)
color_balance_dialog = color_balance_dialog_new ();
else
if (!GTK_WIDGET_VISIBLE (color_balance_dialog->shell))
gtk_widget_show (color_balance_dialog->shell);
for (i = 0; i < 3; i++)
{
color_balance_dialog->cyan_red[i] = 0.0;
color_balance_dialog->magenta_green[i] = 0.0;
color_balance_dialog->yellow_blue[i] = 0.0;
}
color_balance_dialog->drawable = gimp_image_active_drawable (gdisp->gimage);
color_balance_dialog->image_map =
image_map_create (gdisp, color_balance_dialog->drawable);
color_balance_update (color_balance_dialog, ALL);
}
/**************************/
/* Color Balance dialog */
/**************************/
static ColorBalanceDialog *
color_balance_dialog_new (void)
{
ColorBalanceDialog *cbd;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *table;
GtkWidget *start_label;
GtkWidget *end_label;
GtkWidget *label;
GtkWidget *spinbutton;
GtkWidget *slider;
GtkWidget *toggle;
GtkWidget *radio_button;
GtkObject *data;
GSList *group = NULL;
gint i;
gchar *appl_mode_names[] =
{
N_("Shadows"),
N_("Midtones"),
N_("Highlights")
};
cbd = g_new (ColorBalanceDialog, 1);
cbd->preserve_luminosity = TRUE;
cbd->preview = TRUE;
cbd->application_mode = SHADOWS;
/* The shell and main vbox */
cbd->shell = gimp_dialog_new (_("Color Balance"), "color_balance",
tools_help_func, NULL,
GTK_WIN_POS_NONE,
FALSE, TRUE, FALSE,
_("OK"), color_balance_ok_callback,
cbd, NULL, NULL, TRUE, FALSE,
_("Reset"), color_balance_reset_callback,
cbd, NULL, NULL, TRUE, FALSE,
_("Cancel"), color_balance_cancel_callback,
cbd, NULL, NULL, FALSE, TRUE,
NULL);
vbox = gtk_vbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (cbd->shell)->vbox), vbox);
/* Horizontal box for application mode */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Color Levels:"));
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
/* cyan-red spinbutton */
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0);
cbd->cyan_red_data = GTK_ADJUSTMENT (data);
spinbutton = gtk_spin_button_new (cbd->cyan_red_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
gtk_widget_show (spinbutton);
/* magenta-green spinbutton */
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0);
cbd->magenta_green_data = GTK_ADJUSTMENT (data);
spinbutton = gtk_spin_button_new (cbd->magenta_green_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
gtk_widget_show (spinbutton);
/* yellow-blue spinbutton */
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0);
cbd->yellow_blue_data = GTK_ADJUSTMENT (data);
spinbutton = gtk_spin_button_new (cbd->yellow_blue_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
gtk_widget_show (spinbutton);
gtk_widget_show (hbox);
/* The table containing sliders */
table = gtk_table_new (3, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
/* Create the cyan-red scale widget */
start_label = gtk_label_new (_("Cyan"));
gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
slider = gtk_hscale_new (cbd->cyan_red_data);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1);
gtk_signal_connect (GTK_OBJECT (cbd->cyan_red_data), "value_changed",
GTK_SIGNAL_FUNC (color_balance_cr_adjustment_update),
cbd);
end_label = gtk_label_new (_("Red"));
gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0);
gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (start_label);
gtk_widget_show (end_label);
gtk_widget_show (slider);
/* Create the magenta-green scale widget */
start_label = gtk_label_new (_("Magenta"));
gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
slider = gtk_hscale_new (cbd->magenta_green_data);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2);
gtk_signal_connect (GTK_OBJECT (cbd->magenta_green_data), "value_changed",
GTK_SIGNAL_FUNC (color_balance_mg_adjustment_update),
cbd);
end_label = gtk_label_new (_("Green"));
gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0);
gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (start_label);
gtk_widget_show (end_label);
gtk_widget_show (slider);
/* Create the yellow-blue scale widget */
start_label = gtk_label_new (_("Yellow"));
gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
slider = gtk_hscale_new (cbd->yellow_blue_data);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 2, 3);
gtk_signal_connect (GTK_OBJECT (cbd->yellow_blue_data), "value_changed",
GTK_SIGNAL_FUNC (color_balance_yb_adjustment_update),
cbd);
end_label = gtk_label_new (_("Blue"));
gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0);
gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (start_label);
gtk_widget_show (end_label);
gtk_widget_show (slider);
gtk_widget_show (table);
/* Horizontal box for application mode */
hbox = gtk_hbox_new (TRUE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
/* the radio buttons for application mode */
for (i = 0; i < 3; i++)
{
radio_button =
gtk_radio_button_new_with_label (group, gettext (appl_mode_names[i]));
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
gtk_box_pack_start (GTK_BOX (hbox), radio_button, TRUE, FALSE, 0);
gtk_object_set_user_data (GTK_OBJECT (radio_button), (gpointer) i);
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
GTK_SIGNAL_FUNC (color_balance_range_callback),
cbd);
gtk_widget_show (radio_button);
}
gtk_widget_show (hbox);
/* Horizontal box for preview and preserve luminosity toggle buttons */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
/* The preserve luminosity toggle */
toggle = gtk_check_button_new_with_label (_("Preserve Luminosity"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
cbd->preserve_luminosity);
gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
GTK_SIGNAL_FUNC (color_balance_preserve_update),
cbd);
gtk_widget_show (toggle);
/* The preview toggle */
toggle = gtk_check_button_new_with_label (_("Preview"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cbd->preview);
gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
GTK_SIGNAL_FUNC (color_balance_preview_update),
cbd);
gtk_widget_show (toggle);
gtk_widget_show (hbox);
gtk_widget_show (vbox);
gtk_widget_show (cbd->shell);
return cbd;
}
static void
color_balance_update (ColorBalanceDialog *cbd,
gint update)
{
if (update & CYAN_RED)
{
gtk_adjustment_set_value (cbd->cyan_red_data,
cbd->cyan_red[cbd->application_mode]);
}
if (update & MAGENTA_GREEN)
{
gtk_adjustment_set_value (cbd->magenta_green_data,
cbd->magenta_green[cbd->application_mode]);
}
if (update & YELLOW_BLUE)
{
gtk_adjustment_set_value (cbd->yellow_blue_data,
cbd->yellow_blue[cbd->application_mode]);
}
}
void
color_balance_create_lookup_tables (ColorBalanceDialog *cbd)
{
gdouble *cyan_red_transfer[3];
gdouble *magenta_green_transfer[3];
gdouble *yellow_blue_transfer[3];
gint i;
gint32 r_n, g_n, b_n;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
for (i = 0; i < 256; i++)
{
r_n = i;
g_n = i;
b_n = i;
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = CLAMP0255 (r_n);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = CLAMP0255 (g_n);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = CLAMP0255 (b_n);
cbd->r_lookup[i] = r_n;
cbd->g_lookup[i] = g_n;
cbd->b_lookup[i] = b_n;
}
}
static void
color_balance_preview (ColorBalanceDialog *cbd)
{
if (!cbd->image_map)
{
g_message ("color_balance_preview(): No image map");
return;
}
active_tool->preserve = TRUE;
color_balance_create_lookup_tables (cbd);
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
active_tool->preserve = FALSE;
}
static void
color_balance_reset_callback (GtkWidget *widget,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
cbd->cyan_red[cbd->application_mode] = 0.0;
cbd->magenta_green[cbd->application_mode] = 0.0;
cbd->yellow_blue[cbd->application_mode] = 0.0;
color_balance_update (cbd, ALL);
if (cbd->preview)
color_balance_preview (cbd);
}
static void
color_balance_ok_callback (GtkWidget *widget,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
gimp_dialog_hide (cbd->shell);
active_tool->preserve = TRUE;
if (!cbd->preview)
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
if (cbd->image_map)
image_map_commit (cbd->image_map);
active_tool->preserve = FALSE;
cbd->image_map = NULL;
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
color_balance_cancel_callback (GtkWidget *widget,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
gimp_dialog_hide (cbd->shell);
if (cbd->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (cbd->image_map);
active_tool->preserve = FALSE;
gdisplays_flush ();
cbd->image_map = NULL;
}
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
color_balance_range_callback (GtkWidget *widget,
gpointer data)
{
ColorBalanceDialog *cbd;
TransferMode range;
cbd = (ColorBalanceDialog *) data;
range = (TransferMode) gtk_object_get_user_data (GTK_OBJECT (widget));
cbd->application_mode = range;
color_balance_update (cbd, ALL);
}
static void
color_balance_preserve_update (GtkWidget *widget,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
cbd->preserve_luminosity = TRUE;
else
cbd->preserve_luminosity = FALSE;
if (cbd->preview)
color_balance_preview (cbd);
}
static void
color_balance_preview_update (GtkWidget *widget,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
{
cbd->preview = TRUE;
color_balance_preview (cbd);
}
else
{
cbd->preview = FALSE;
if (cbd->image_map)
{
active_tool->preserve = TRUE;
image_map_clear (cbd->image_map);
active_tool->preserve = FALSE;
gdisplays_flush ();
}
}
}
static void
color_balance_cr_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
if (cbd->cyan_red[cbd->application_mode] != adjustment->value)
{
cbd->cyan_red[cbd->application_mode] = adjustment->value;
if (cbd->preview)
color_balance_preview (cbd);
}
}
static void
color_balance_mg_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
if (cbd->magenta_green[cbd->application_mode] != adjustment->value)
{
cbd->magenta_green[cbd->application_mode] = adjustment->value;
if (cbd->preview)
color_balance_preview (cbd);
}
}
static void
color_balance_yb_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
ColorBalanceDialog *cbd;
cbd = (ColorBalanceDialog *) data;
if (cbd->yellow_blue[cbd->application_mode] != adjustment->value)
{
cbd->yellow_blue[cbd->application_mode] = adjustment->value;
if (cbd->preview)
color_balance_preview (cbd);
}
}

View File

@ -1,68 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_BALANCE_H__
#define __COLOR_BALANCE_H__
typedef enum
{
SHADOWS,
MIDTONES,
HIGHLIGHTS
} TransferMode;
typedef struct _ColorBalanceDialog ColorBalanceDialog;
struct _ColorBalanceDialog
{
GtkWidget *shell;
GtkAdjustment *cyan_red_data;
GtkAdjustment *magenta_green_data;
GtkAdjustment *yellow_blue_data;
GimpDrawable *drawable;
ImageMap image_map;
gdouble cyan_red[3];
gdouble magenta_green[3];
gdouble yellow_blue[3];
guchar r_lookup[256];
guchar g_lookup[256];
guchar b_lookup[256];
gboolean preserve_luminosity;
gboolean preview;
TransferMode application_mode;
};
Tool * tools_new_color_balance (void);
void tools_free_color_balance (Tool *tool);
void color_balance_initialize (GDisplay *gdisp);
void color_balance_dialog_hide (void);
void color_balance (PixelRegion *srcPR,
PixelRegion *destPR,
void *data);
void color_balance_create_lookup_tables (ColorBalanceDialog *cbd);
#endif /* __COLOR_BALANCE_H__ */

View File

@ -1,824 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "apptypes.h"
#include "libgimp/gimpcolorarea.h"
#include "appenv.h"
#include "color_picker.h"
#include "draw_core.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "gimprc.h"
#include "cursorutil.h"
#include "info_dialog.h"
#include "palette.h"
#include "tools.h"
#include "tool_options.h"
#include "libgimp/gimpintl.h"
/* maximum information buffer size */
#define MAX_INFO_BUF 8
/* the color picker structures */
typedef struct _ColorPickerOptions ColorPickerOptions;
struct _ColorPickerOptions
{
ToolOptions tool_options;
gboolean sample_merged;
gboolean sample_merged_d;
GtkWidget *sample_merged_w;
gboolean sample_average;
gboolean sample_average_d;
GtkWidget *sample_average_w;
gdouble average_radius;
gdouble average_radius_d;
GtkObject *average_radius_w;
gboolean update_active;
gboolean update_active_d;
GtkWidget *update_active_w;
};
typedef struct _ColorPickerTool ColorPickerTool;
struct _ColorPickerTool
{
DrawCore *core; /* Core select object */
gint centerx; /* starting x coord */
gint centery; /* starting y coord */
};
/* the color picker tool options */
static ColorPickerOptions * color_picker_options = NULL;
/* the color value */
gint col_value[5] = { 0, 0, 0, 0, 0 };
/* the color picker dialog */
static gint update_type;
static GimpImageType sample_type;
static InfoDialog *color_picker_info = NULL;
static GtkWidget *color_area = NULL;
static gchar red_buf [MAX_INFO_BUF];
static gchar green_buf [MAX_INFO_BUF];
static gchar blue_buf [MAX_INFO_BUF];
static gchar alpha_buf [MAX_INFO_BUF];
static gchar index_buf [MAX_INFO_BUF];
static gchar gray_buf [MAX_INFO_BUF];
static gchar hex_buf [MAX_INFO_BUF];
/* local function prototypes */
static void color_picker_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void color_picker_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void color_picker_motion (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp);
static void color_picker_cursor_update (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp);
static void color_picker_control (Tool *tool,
ToolAction action,
GDisplay *gdisp);
static void color_picker_info_window_close_callback (GtkWidget *widget,
gpointer data);
static void color_picker_info_update (Tool *tool,
gboolean valid);
static gboolean pick_color_do (GimpImage *gimage,
GimpDrawable *drawable,
gint x,
gint y,
gboolean sample_merged,
gboolean sample_average,
gdouble average_radius,
gboolean update_active,
gint final);
/* functions */
static void
color_picker_options_reset (void)
{
ColorPickerOptions *options = color_picker_options;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
options->sample_merged_d);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_average_w),
options->sample_average_d);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->average_radius_w),
options->average_radius_d);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->update_active_w),
options->update_active_d);
}
static ColorPickerOptions *
color_picker_options_new (void)
{
ColorPickerOptions *options;
GtkWidget *vbox;
GtkWidget *abox;
GtkWidget *table;
GtkWidget *label;
GtkWidget *scale;
/* the new color picker tool options structure */
options = g_new (ColorPickerOptions, 1);
tool_options_init ((ToolOptions *) options,
_("Color Picker"),
color_picker_options_reset);
options->sample_merged = options->sample_merged_d = FALSE;
options->sample_average = options->sample_average_d = FALSE;
options->average_radius = options->average_radius_d = 1.0;
options->update_active = options->update_active_d = TRUE;
/* the main vbox */
vbox = options->tool_options.main_vbox;
/* the sample merged toggle button */
options->sample_merged_w =
gtk_check_button_new_with_label (_("Sample Merged"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
options->sample_merged_d);
gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled",
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&options->sample_merged);
gtk_widget_show (options->sample_merged_w);
/* the sample average options */
table = gtk_table_new (2, 2, FALSE);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
options->sample_average_w =
gtk_check_button_new_with_label (_("Sample Average"));
gtk_table_attach (GTK_TABLE (table), options->sample_average_w, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_average_w),
options->sample_average_d);
gtk_signal_connect (GTK_OBJECT (options->sample_average_w), "toggled",
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&options->sample_average);
gtk_widget_show (options->sample_average_w);
label = gtk_label_new (_("Radius:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (label);
/* the feather radius scale */
abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 0, 2,
GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (abox);
options->average_radius_w =
gtk_adjustment_new (options->average_radius_d, 1.0, 15.0, 2.0, 2.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->average_radius_w));
gtk_scale_set_digits (GTK_SCALE (scale), 0);
gtk_container_add (GTK_CONTAINER (abox), scale);
gtk_widget_set_sensitive (scale, options->sample_average_d);
gtk_object_set_data (GTK_OBJECT (options->sample_average_w), "set_sensitive",
scale);
gtk_widget_set_sensitive (label, options->sample_average_d);
gtk_object_set_data (GTK_OBJECT (scale), "set_sensitive",
label);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (options->average_radius_w), "value_changed",
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
&options->average_radius);
gtk_widget_show (scale);
gtk_widget_show (table);
/* the update active color toggle button */
options->update_active_w =
gtk_check_button_new_with_label (_("Update Active Color"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->update_active_w),
options->update_active_d);
gtk_box_pack_start (GTK_BOX (vbox), options->update_active_w, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (options->update_active_w), "toggled",
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&options->update_active);
gtk_widget_show (options->update_active_w);
return options;
}
static void
color_picker_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
ColorPickerTool *cp_tool;
gint x, y;
cp_tool = (ColorPickerTool *) tool->private;
/* Make the tool active and set it's gdisplay & drawable */
tool->gdisp = gdisp;
tool->drawable = gimp_image_active_drawable (gdisp->gimage);
tool->state = ACTIVE;
/* create the info dialog if it doesn't exist */
if (! color_picker_info)
{
GtkWidget *hbox;
GtkWidget *frame;
GimpRGB color;
color_picker_info = info_dialog_new (_("Color Picker"),
tools_help_func, NULL);
/* if the gdisplay is for a color image, the dialog must have RGB */
switch (gimp_drawable_type (tool->drawable))
{
case RGB_GIMAGE: case RGBA_GIMAGE:
info_dialog_add_label (color_picker_info, _("Red:"), red_buf);
info_dialog_add_label (color_picker_info, _("Green:"), green_buf);
info_dialog_add_label (color_picker_info, _("Blue:"), blue_buf);
info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf);
info_dialog_add_label (color_picker_info, _("Hex Triplet:"), hex_buf);
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
info_dialog_add_label (color_picker_info, _("Index:"), index_buf);
info_dialog_add_label (color_picker_info, _("Red:"), red_buf);
info_dialog_add_label (color_picker_info, _("Green:"), green_buf);
info_dialog_add_label (color_picker_info, _("Blue:"), blue_buf);
info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf);
info_dialog_add_label (color_picker_info, _("Hex Triplet"), hex_buf);
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
info_dialog_add_label (color_picker_info, _("Intensity:"), gray_buf);
info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf);
info_dialog_add_label (color_picker_info, _("Hex Triplet:"), hex_buf);
break;
default :
break;
}
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (color_picker_info->vbox), hbox,
FALSE, FALSE, 0);
gtk_widget_show (hbox);
gtk_widget_reparent (color_picker_info->info_table, hbox);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
color_area =
gimp_color_area_new (&color,
gimp_drawable_has_alpha (tool->drawable) ?
GIMP_COLOR_AREA_LARGE_CHECKS :
GIMP_COLOR_AREA_FLAT,
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
gtk_widget_set_usize (color_area, 48, 64);
gtk_drag_dest_unset (color_area);
gtk_container_add (GTK_CONTAINER (frame), color_area);
gtk_widget_show (color_area);
gtk_widget_show (frame);
/* create the action area */
gimp_dialog_create_action_area
(GTK_DIALOG (color_picker_info->shell),
_("Close"), color_picker_info_window_close_callback,
color_picker_info, NULL, NULL, TRUE, FALSE,
NULL);
}
/* Keep the coordinates of the target */
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
&cp_tool->centerx, &cp_tool->centery, FALSE, 1);
gdk_pointer_grab (gdisp->canvas->window, FALSE,
(GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK),
NULL, NULL, bevent->time);
/* First, transform the coordinates to gimp image space */
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y,
FALSE, FALSE);
/* if the shift key is down, create a new color.
* otherwise, modify the current color.
*/
if (bevent->state & GDK_SHIFT_MASK)
{
color_picker_info_update
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
color_picker_options->sample_merged,
color_picker_options->sample_average,
color_picker_options->average_radius,
color_picker_options->update_active,
COLOR_NEW));
update_type = COLOR_UPDATE_NEW;
}
else
{
color_picker_info_update
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
color_picker_options->sample_merged,
color_picker_options->sample_average,
color_picker_options->average_radius,
color_picker_options->update_active,
COLOR_UPDATE));
update_type = COLOR_UPDATE;
}
/* Start drawing the colorpicker tool */
draw_core_start (cp_tool->core, gdisp->canvas->window, tool);
}
static void
color_picker_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
ColorPickerTool *cp_tool;
gint x, y;
gdk_pointer_ungrab (bevent->time);
gdk_flush ();
cp_tool = (ColorPickerTool *) tool->private;
/* First, transform the coordinates to gimp image space */
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y,
FALSE, FALSE);
color_picker_info_update
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
color_picker_options->sample_merged,
color_picker_options->sample_average,
color_picker_options->average_radius,
color_picker_options->update_active,
update_type));
draw_core_stop (cp_tool->core, tool);
tool->state = INACTIVE;
}
static void
color_picker_motion (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
ColorPickerTool *cp_tool;
gint x, y;
cp_tool = (ColorPickerTool *) tool->private;
/* undraw the current tool */
draw_core_pause (cp_tool->core, tool);
/* First, transform the coordinates to gimp image space */
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
FALSE, FALSE);
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
&cp_tool->centerx, &cp_tool->centery,
FALSE, TRUE);
color_picker_info_update
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
color_picker_options->sample_merged,
color_picker_options->sample_average,
color_picker_options->average_radius,
color_picker_options->update_active,
update_type));
/* redraw the current tool */
draw_core_resume (cp_tool->core, tool);
}
static void
color_picker_cursor_update (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
gint x, y;
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
FALSE, FALSE);
/* We used to use the following code here:
*
* if (gimp_image_pick_correlate_layer (gdisp->gimage, x, y)) { ... }
*/
if (gdisp->gimage &&
x > 0 && x < gdisp->gimage->width &&
y > 0 && y < gdisp->gimage->height)
{
gdisplay_install_tool_cursor (gdisp, GIMP_COLOR_PICKER_CURSOR,
COLOR_PICKER,
CURSOR_MODIFIER_NONE,
FALSE);
}
else
{
gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
COLOR_PICKER,
CURSOR_MODIFIER_NONE,
FALSE);
}
}
static void
color_picker_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
ColorPickerTool *cp_tool;
cp_tool = (ColorPickerTool *) tool->private;
switch (action)
{
case PAUSE :
draw_core_pause (cp_tool->core, tool);
break;
case RESUME :
draw_core_resume (cp_tool->core, tool);
break;
case HALT :
draw_core_stop (cp_tool->core, tool);
info_dialog_popdown (color_picker_info);
break;
default:
break;
}
}
typedef guchar * (*GetColorFunc) (GimpObject *object,
gint x,
gint y);
static gboolean
pick_color_do (GimpImage *gimage,
GimpDrawable *drawable,
gint x,
gint y,
gboolean sample_merged,
gboolean sample_average,
gdouble average_radius,
gboolean update_active,
gint final)
{
guchar *color;
gint offx, offy;
gint has_alpha;
gint is_indexed;
GetColorFunc get_color_func;
GimpObject *get_color_obj;
if (!drawable && !sample_merged)
return FALSE;
if (!sample_merged)
{
gimp_drawable_offsets (drawable, &offx, &offy);
x -= offx;
y -= offy;
sample_type = gimp_drawable_type (drawable);
is_indexed = gimp_drawable_is_indexed (drawable);
get_color_func = (GetColorFunc) gimp_drawable_get_color_at;
get_color_obj = GIMP_OBJECT (drawable);
}
else
{
sample_type = gimp_image_composite_type (gimage);
is_indexed = FALSE;
get_color_func = (GetColorFunc) gimp_image_get_color_at;
get_color_obj = GIMP_OBJECT (gimage);
}
has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (sample_type);
if (!(color = (* get_color_func) (get_color_obj, x, y)))
return FALSE;
if (sample_average)
{
gint i, j;
gint count = 0;
gint color_avg[4] = { 0, 0, 0, 0 };
guchar *tmp_color;
gint radius = (gint) average_radius;
for (i = x - radius; i <= x + radius; i++)
for (j = y - radius; j <= y + radius; j++)
if ((tmp_color = (* get_color_func) (get_color_obj, i, j)))
{
count++;
color_avg[RED_PIX] += tmp_color[RED_PIX];
color_avg[GREEN_PIX] += tmp_color[GREEN_PIX];
color_avg[BLUE_PIX] += tmp_color[BLUE_PIX];
if (has_alpha)
color_avg[ALPHA_PIX] += tmp_color[ALPHA_PIX];
g_free (tmp_color);
}
color[RED_PIX] = (guchar) (color_avg[RED_PIX] / count);
color[GREEN_PIX] = (guchar) (color_avg[GREEN_PIX] / count);
color[BLUE_PIX] = (guchar) (color_avg[BLUE_PIX] / count);
if (has_alpha)
color[ALPHA_PIX] = (guchar) (color_avg[ALPHA_PIX] / count);
is_indexed = FALSE;
}
col_value[RED_PIX] = color[RED_PIX];
col_value[GREEN_PIX] = color[GREEN_PIX];
col_value[BLUE_PIX] = color[BLUE_PIX];
if (has_alpha)
col_value[ALPHA_PIX] = color[ALPHA_PIX];
if (is_indexed)
col_value[4] = color[4];
if (update_active)
palette_set_active_color (col_value [RED_PIX],
col_value [GREEN_PIX],
col_value [BLUE_PIX],
final);
g_free (color);
return TRUE;
}
gboolean
pick_color (GimpImage *gimage,
GimpDrawable *drawable,
gint x,
gint y,
gboolean sample_merged,
gboolean sample_average,
gdouble average_radius,
gint final)
{
return pick_color_do (gimage, drawable,
x, y,
sample_merged,
sample_average,
average_radius,
TRUE,
final);
}
static void
colorpicker_draw (Tool *tool)
{
ColorPickerTool *cp_tool;
gint tx, ty;
gint radiusx, radiusy;
gint cx, cy;
if (! color_picker_options->sample_average)
return;
cp_tool = (ColorPickerTool *) tool->private;
gdisplay_transform_coords (tool->gdisp, cp_tool->centerx, cp_tool->centery,
&tx, &ty, TRUE);
radiusx = SCALEX (tool->gdisp, color_picker_options->average_radius);
radiusy = SCALEY (tool->gdisp, color_picker_options->average_radius);
cx = SCALEX (tool->gdisp, 1);
cy = SCALEY (tool->gdisp, 1);
/* Draw the circle around the collecting area */
gdk_draw_rectangle (cp_tool->core->win, cp_tool->core->gc, 0,
tx - radiusx,
ty - radiusy,
2 * radiusx + cx, 2 * radiusy + cy);
if (radiusx > 1 && radiusy > 1)
{
gdk_draw_rectangle (cp_tool->core->win, cp_tool->core->gc, 0,
tx - radiusx + 2,
ty - radiusy + 2,
2 * radiusx + cx - 4, 2 * radiusy + cy - 4);
}
}
static void
color_picker_info_update (Tool *tool,
gboolean valid)
{
if (!valid)
{
if (GTK_WIDGET_IS_SENSITIVE (color_area))
gtk_widget_set_sensitive (color_area, FALSE);
g_snprintf (red_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (green_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (blue_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (index_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (gray_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (hex_buf, MAX_INFO_BUF, _("N/A"));
}
else
{
GimpRGB color;
guchar r = 0;
guchar g = 0;
guchar b = 0;
guchar a = 0;
if (! GTK_WIDGET_IS_SENSITIVE (color_area))
gtk_widget_set_sensitive (color_area, TRUE);
switch (sample_type)
{
case RGB_GIMAGE: case RGBA_GIMAGE:
g_snprintf (index_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (red_buf, MAX_INFO_BUF, "%d", col_value [RED_PIX]);
g_snprintf (green_buf, MAX_INFO_BUF, "%d", col_value [GREEN_PIX]);
g_snprintf (blue_buf, MAX_INFO_BUF, "%d", col_value [BLUE_PIX]);
if (sample_type == RGBA_GIMAGE)
g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]);
else
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x",
col_value [RED_PIX],
col_value [GREEN_PIX],
col_value [BLUE_PIX]);
r = col_value [RED_PIX];
g = col_value [GREEN_PIX];
b = col_value [BLUE_PIX];
if (sample_type == RGBA_GIMAGE)
a = col_value [ALPHA_PIX];
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
g_snprintf (index_buf, MAX_INFO_BUF, "%d", col_value [4]);
g_snprintf (red_buf, MAX_INFO_BUF, "%d", col_value [RED_PIX]);
g_snprintf (green_buf, MAX_INFO_BUF, "%d", col_value [GREEN_PIX]);
g_snprintf (blue_buf, MAX_INFO_BUF, "%d", col_value [BLUE_PIX]);
if (sample_type == INDEXEDA_GIMAGE)
g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]);
else
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x",
col_value [RED_PIX],
col_value [GREEN_PIX],
col_value [BLUE_PIX]);
r = col_value [RED_PIX];
g = col_value [GREEN_PIX];
b = col_value [BLUE_PIX];
if (sample_type == INDEXEDA_GIMAGE)
a = col_value [ALPHA_PIX];
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
g_snprintf (gray_buf, MAX_INFO_BUF, "%d", col_value [GRAY_PIX]);
if (sample_type == GRAYA_GIMAGE)
g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]);
else
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x",
col_value [GRAY_PIX],
col_value [GRAY_PIX],
col_value [GRAY_PIX]);
r = col_value [GRAY_PIX];
g = col_value [GRAY_PIX];
b = col_value [GRAY_PIX];
if (sample_type == GRAYA_GIMAGE)
a = col_value [ALPHA_PIX];
break;
}
gimp_rgba_set_uchar (&color, r, g, b, a);
gimp_color_area_set_color (GIMP_COLOR_AREA (color_area), &color);
}
info_dialog_update (color_picker_info);
info_dialog_popup (color_picker_info);
}
static void
color_picker_info_window_close_callback (GtkWidget *widget,
gpointer client_data)
{
info_dialog_popdown ((InfoDialog *) client_data);
}
Tool *
tools_new_color_picker ()
{
Tool * tool;
ColorPickerTool * private;
/* The tool options */
if (! color_picker_options)
{
color_picker_options = color_picker_options_new ();
tools_register (COLOR_PICKER, (ToolOptions *) color_picker_options);
}
tool = tools_new_tool (COLOR_PICKER);
private = g_new0 (ColorPickerTool, 1);
private->core = draw_core_new (colorpicker_draw);
tool->preserve = FALSE; /* Don't preserve on drawable change */
tool->private = (void *) private;
tool->button_press_func = color_picker_button_press;
tool->button_release_func = color_picker_button_release;
tool->motion_func = color_picker_motion;
tool->cursor_update_func = color_picker_cursor_update;
tool->control_func = color_picker_control;
return tool;
}
void
tools_free_color_picker (Tool *tool)
{
ColorPickerTool * cp_tool;
cp_tool = (ColorPickerTool *) tool->private;
if (tool->state == ACTIVE)
draw_core_stop (cp_tool->core, tool);
draw_core_free (cp_tool->core);
if (color_picker_info)
{
info_dialog_free (color_picker_info);
color_picker_info = NULL;
color_area = NULL;
}
g_free (cp_tool);
}

View File

@ -1,39 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_PICKER_H__
#define __COLOR_PICKER_H__
extern gint col_value[5];
gboolean pick_color (GimpImage *gimage,
GimpDrawable *drawable,
gint x,
gint y,
gboolean sample_merged,
gboolean sample_average,
double average_radius,
gint final);
Tool * tools_new_color_picker (void);
void tools_free_color_picker (Tool *tool);
#endif /* __COLOR_PICKER_H__ */

View File

@ -68,13 +68,14 @@
#include "scale.h"
#include "selection.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
#ifdef DISPLAY_FILTERS
#include "gdisplay_color_ui.h"
#endif /* DISPLAY_FILTERS */
#include "tools/tools.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -28,8 +28,9 @@
#include "gdisplay.h"
#include "gimpcontext.h"
#include "gimprc.h"
#include "paint_options.h"
#include "tools.h"
#include "tools/paint_options.h"
#include "tools/tools.h"
static GimpContext * global_tool_context;

View File

@ -94,30 +94,31 @@
#include "apptypes.h"
#include "appenv.h"
#include "brightness_contrast.h"
#include "color_balance.h"
#include "convert.h"
#include "cursorutil.h"
#include "curves.h"
#include "drawable.h"
#include "floating_sel.h"
#include "fsdither.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "hue_saturation.h"
#include "layer.h"
#include "levels.h"
#include "undo.h"
#include "palette.h"
#include "gimppalette.h"
#include "palette_select.h"
#include "pixel_region.h"
#include "posterize.h"
#include "threshold.h"
#include "tile_manager.h"
#include "tile_manager_pvt.h" /* ick ick ick. */
#include "tools/brightness_contrast.h"
#include "tools/color_balance.h"
#include "tools/curves.h"
#include "tools/hue_saturation.h"
#include "tools/levels.h"
#include "tools/posterize.h"
#include "tools/threshold.h"
#include "libgimp/gimpcolorspace.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -1,696 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "apptypes.h"
#include "appenv.h"
#include "drawable.h"
#include "convolve.h"
#include "gdisplay.h"
#include "gimpbrush.h"
#include "gimpcontext.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "paint_options.h"
#include "pixel_region.h"
#include "selection.h"
#include "temp_buf.h"
#include "tools.h"
#include "gimage.h"
#include "libgimp/gimpintl.h"
#define FIELD_COLS 4
#define MIN_BLUR 64 /* (8/9 original pixel) */
#define MAX_BLUR 0.25 /* (1/33 original pixel) */
#define MIN_SHARPEN -512
#define MAX_SHARPEN -64
/* defaults */
#define DEFAULT_CONVOLVE_RATE 50.0
#define DEFAULT_CONVOLVE_TYPE BLUR_CONVOLVE
/* Different clip relationships between a blur-blob and edges:
see convolve_motion */
typedef enum
{
CONVOLVE_NCLIP, /* Left or top edge */
CONVOLVE_NOT_CLIPPED, /* No edges */
CONVOLVE_PCLIP /* Right or bottom edge */
} ConvolveClipType;
/* the convolve structures */
typedef struct _ConvolveOptions ConvolveOptions;
struct _ConvolveOptions
{
PaintOptions paint_options;
ConvolveType type;
ConvolveType type_d;
GtkWidget *type_w[2];
gdouble rate;
gdouble rate_d;
GtkObject *rate_w;
};
/* forward function declarations */
static void calculate_matrix (ConvolveType type,
gdouble rate);
static void integer_matrix (gfloat *source,
gint *dest,
gint size);
static void copy_matrix (gfloat *src,
gfloat *dest,
gint size);
static gint sum_matrix (gint *matrix,
gint size);
static gpointer convolve_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state);
static void convolve_motion (PaintCore *paint_core,
GimpDrawable *drawable,
PaintPressureOptions *pressure_options,
ConvolveType type,
gdouble rate);
/* the convolve tool options */
static ConvolveOptions * convolve_options = NULL;
/* local variables */
static gint matrix [25];
static gint matrix_size;
static gint matrix_divisor;
static ConvolveType non_gui_type;
static gdouble non_gui_rate;
static gfloat custom_matrix [25] =
{
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
};
static gfloat blur_matrix [25] =
{
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 1, MIN_BLUR, 1, 0,
0, 1, 1, 1, 0,
0, 0 ,0, 0, 0,
};
static gfloat sharpen_matrix [25] =
{
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 1, MIN_SHARPEN, 1, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
};
/* functions */
static void
convolve_options_reset (void)
{
ConvolveOptions *options = convolve_options;
paint_options_reset ((PaintOptions *) options);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w), options->rate_d);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
}
static ConvolveOptions *
convolve_options_new (void)
{
ConvolveOptions *options;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *scale;
GtkWidget *frame;
/* the new convolve tool options structure */
options = g_new (ConvolveOptions, 1);
paint_options_init ((PaintOptions *) options,
CONVOLVE,
convolve_options_reset);
options->type = options->type_d = DEFAULT_CONVOLVE_TYPE;
options->rate = options->rate_d = DEFAULT_CONVOLVE_RATE;
/* the main vbox */
vbox = ((ToolOptions *) options)->main_vbox;
/* the rate scale */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Rate:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
options->rate_w =
gtk_adjustment_new (options->rate_d, 0.0, 100.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w));
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed",
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
&options->rate);
gtk_widget_show (scale);
gtk_widget_show (hbox);
frame = gimp_radio_group_new2 (TRUE, _("Convolve Type"),
gimp_radio_button_update,
&options->type, (gpointer) options->type,
_("Blur"), (gpointer) BLUR_CONVOLVE,
&options->type_w[0],
_("Sharpen"), (gpointer) SHARPEN_CONVOLVE,
&options->type_w[1],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
return options;
}
static gpointer
convolve_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
switch (state)
{
case MOTION_PAINT:
convolve_motion (paint_core, drawable,
convolve_options->paint_options.pressure_options,
convolve_options->type, convolve_options->rate);
break;
default:
break;
}
return NULL;
}
static void
convolve_modifier_key_func (Tool *tool,
GdkEventKey *kevent,
GDisplay *gdisp)
{
switch (kevent->keyval)
{
case GDK_Alt_L:
case GDK_Alt_R:
break;
case GDK_Shift_L:
case GDK_Shift_R:
if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */
{
switch (convolve_options->type)
{
case BLUR_CONVOLVE:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (convolve_options->type_w[SHARPEN_CONVOLVE]),
TRUE);
break;
case SHARPEN_CONVOLVE:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (convolve_options->type_w[BLUR_CONVOLVE]),
TRUE);
break;
default:
break;
}
}
break;
case GDK_Control_L:
case GDK_Control_R:
if ( !(kevent->state & GDK_SHIFT_MASK) ) /* shift enables line draw mode */
{
switch (convolve_options->type)
{
case BLUR_CONVOLVE:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (convolve_options->type_w[SHARPEN_CONVOLVE]),
TRUE);
break;
case SHARPEN_CONVOLVE:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (convolve_options->type_w[BLUR_CONVOLVE]),
TRUE);
break;
default:
break;
}
}
break;
}
tool->toggled = (convolve_options->type == SHARPEN_CONVOLVE);
}
static void
convolve_cursor_update_func (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
tool->toggled = (convolve_options->type == SHARPEN_CONVOLVE);
paint_core_cursor_update (tool, mevent, gdisp);
}
Tool *
tools_new_convolve (void)
{
Tool *tool;
PaintCore *private;
/* The tool options */
if (! convolve_options)
{
convolve_options = convolve_options_new ();
tools_register (CONVOLVE, (ToolOptions *) convolve_options);
/* press all default buttons */
convolve_options_reset ();
}
tool = paint_core_new (CONVOLVE);
tool->modifier_key_func = convolve_modifier_key_func;
tool->cursor_update_func = convolve_cursor_update_func;
private = (PaintCore *) tool->private;
private->paint_func = convolve_paint_func;
return tool;
}
void
tools_free_convolve (Tool *tool)
{
paint_core_free (tool);
}
static void
convolve_motion (PaintCore *paint_core,
GimpDrawable *drawable,
PaintPressureOptions *pressure_options,
ConvolveType type,
double rate)
{
TempBuf *area;
guchar *temp_data;
PixelRegion srcPR;
PixelRegion destPR;
gdouble scale;
ConvolveClipType area_hclip = CONVOLVE_NOT_CLIPPED;
ConvolveClipType area_vclip = CONVOLVE_NOT_CLIPPED;
gint marginx = 0;
gint marginy = 0;
if (! gimp_drawable_gimage (drawable))
return;
/* If the image type is indexed, don't convolve */
if (gimp_drawable_is_indexed (drawable))
return;
/* If the brush is smaller than the convolution matrix, don't convolve */
if ((paint_core->brush->mask->width < matrix_size) ||
(paint_core->brush->mask->height < matrix_size))
return;
if (pressure_options->size)
scale = paint_core->curpressure;
else
scale = 1.0;
/* Get image region around current brush (mask bbox + 1 pixel) */
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
return;
/* configure the source pixel region */
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
area->x, area->y, area->width, area->height, FALSE);
/* Configure the destination pixel region - a paint_core TempBuf */
destPR.bytes = area->bytes;
destPR.tiles = NULL;
destPR.x = 0;
destPR.y = 0;
destPR.w = area->width;
destPR.h = area->height;
destPR.rowstride = area->width * destPR.bytes;
destPR.data = temp_buf_data (area);
if (pressure_options->rate)
rate = rate * 2.0 * paint_core->curpressure;
calculate_matrix (type, rate);
/* Image region near edges? If so, paint area will be clipped */
/* with respect to brush mask + 1 pixel border (# 19285) */
if((marginx = (gint)paint_core->curx - paint_core->brush->mask->width/2 - 1) != area->x)
area_hclip = CONVOLVE_NCLIP;
else
if((marginx = area->width - paint_core->brush->mask->width - 2) != 0)
area_hclip = CONVOLVE_PCLIP;
if((marginy = (gint)paint_core->cury - paint_core->brush->mask->height/2 - 1) != area->y)
area_vclip = CONVOLVE_NCLIP;
else
if((marginy = area->height - paint_core->brush->mask->height - 2) != 0)
area_vclip = CONVOLVE_PCLIP;
/* Has the TempBuf been clipped by a canvas edge or two ? */
if((area_hclip == CONVOLVE_NOT_CLIPPED) && (area_vclip == CONVOLVE_NOT_CLIPPED))
{
/* No clipping... */
/* Standard case: copy src to temp. convolve temp to dest. */
/* Brush defines pipe size and no edge adjustments are needed. */
/* If the source has no alpha, then add alpha pixels */
/* Because paint_core.c is alpha-only code. See below. */
PixelRegion tempPR;
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = area->width;
tempPR.h = area->height;
tempPR.tiles = NULL;
if (! gimp_drawable_has_alpha (drawable))
{
/* note: this particular approach needlessly convolves the totally-
opaque alpha channel. A faster approach would be to keep
tempPR the same number of bytes as srcPR, and extend the
paint_core_replace_canvas API to handle non-alpha images. */
tempPR.bytes = srcPR.bytes + 1;
tempPR.rowstride = tempPR.bytes * tempPR.w;
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
tempPR.data = temp_data;
add_alpha_region (&srcPR, &tempPR);
}
else
{
tempPR.bytes = srcPR.bytes;
tempPR.rowstride = tempPR.bytes * tempPR.w;
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
tempPR.data = temp_data;
copy_region (&srcPR, &tempPR);
}
/* Convolve the region */
tempPR.x = 0;
tempPR.y = 0;
tempPR.w = area->width;
tempPR.h = area->height;
tempPR.data = temp_data;
convolve_region (&tempPR, &destPR, matrix, matrix_size,
matrix_divisor, NORMAL_CONVOL);
/* Free the allocated temp space */
g_free (temp_data);
}
else
{
/* TempBuf clipping has occured on at least one edge... */
/* Edge case: expand area under brush margin px on near edge(s), convolve */
/* expanded buffers. copy src -> ovrsz1 convolve ovrsz1 -> ovrsz2 */
/* copy-with-crop ovrsz2 -> dest */
PixelRegion ovrsz1PR;
PixelRegion ovrsz2PR;
guchar *ovrsz1_data = NULL;
guchar *ovrsz2_data = NULL;
guchar *fillcolor = gimp_drawable_get_color_at (drawable,
CLAMP ((gint) paint_core->curx, 0, gimp_drawable_width (drawable) - 1),
CLAMP ((gint) paint_core->cury, 0, gimp_drawable_height (drawable) - 1));
marginx *= (marginx < 0) ? -1 : 0;
marginy *= (marginy < 0) ? -1 : 0;
ovrsz2PR.x = 0;
ovrsz2PR.y = 0;
ovrsz2PR.w = area->width + marginx;
ovrsz2PR.h = area->height + marginy;
ovrsz2PR.bytes = (gimp_drawable_has_alpha (drawable))? srcPR.bytes : srcPR.bytes + 1;
ovrsz2PR.offx = 0;
ovrsz2PR.offy = 0;
ovrsz2PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w;
ovrsz2PR.tiles = NULL;
ovrsz2_data = g_malloc (ovrsz2PR.h * ovrsz2PR.rowstride);
ovrsz2PR.data = ovrsz2_data;
ovrsz1PR.x = 0;
ovrsz1PR.y = 0;
ovrsz1PR.w = area->width + marginx;
ovrsz1PR.h = area->height + marginy;
ovrsz1PR.bytes = (gimp_drawable_has_alpha (drawable))? srcPR.bytes : srcPR.bytes + 1;
ovrsz1PR.offx = 0;
ovrsz1PR.offy = 0;
ovrsz1PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w;
ovrsz1PR.tiles = NULL;
ovrsz1_data = g_malloc (ovrsz1PR.h * ovrsz1PR.rowstride);
ovrsz1PR.data = ovrsz1_data;
color_region (&ovrsz1PR, (const guchar *)fillcolor);
ovrsz1PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0;
ovrsz1PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0;
ovrsz1PR.w = area->width;
ovrsz1PR.h = area->height;
ovrsz1PR.data = ovrsz1_data + (ovrsz1PR.rowstride * ovrsz1PR.y) + (ovrsz1PR.bytes * ovrsz1PR.x);
if (! gimp_drawable_has_alpha (drawable))
add_alpha_region (&srcPR, &ovrsz1PR);
else
copy_region (&srcPR, &ovrsz1PR);
/* Convolve the region */
ovrsz1PR.x = 0;
ovrsz1PR.y = 0;
ovrsz1PR.w = area->width + marginx;
ovrsz1PR.h = area->height + marginy;
ovrsz1PR.data = ovrsz1_data;
convolve_region (&ovrsz1PR, &ovrsz2PR, matrix, matrix_size,
matrix_divisor, NORMAL_CONVOL);
/* Crop and copy to destination */
ovrsz2PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0;
ovrsz2PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0;
ovrsz2PR.w = area->width;
ovrsz2PR.h = area->height;
ovrsz2PR.data = ovrsz2_data + (ovrsz2PR.rowstride * ovrsz2PR.y) + (ovrsz2PR.bytes * ovrsz2PR.x);
copy_region (&ovrsz2PR, &destPR);
g_free(ovrsz1_data);
g_free(ovrsz2_data);
g_free(fillcolor);
}
/* paste the newly painted canvas to the gimage which is being worked on */
paint_core_replace_canvas (paint_core, drawable, OPAQUE_OPACITY,
(int) (gimp_context_get_opacity (NULL) * 255),
pressure_options->pressure ? PRESSURE : SOFT,
scale, INCREMENTAL);
}
static void
calculate_matrix (ConvolveType type,
double rate)
{
float percent;
/* find percent of tool pressure */
percent = MIN (rate / 100.0, 1.0);
/* get the appropriate convolution matrix and size and divisor */
switch (type)
{
case BLUR_CONVOLVE:
matrix_size = 5;
blur_matrix [12] = MIN_BLUR + percent * (MAX_BLUR - MIN_BLUR);
copy_matrix (blur_matrix, custom_matrix, matrix_size);
break;
case SHARPEN_CONVOLVE:
matrix_size = 5;
sharpen_matrix [12] = MIN_SHARPEN + percent * (MAX_SHARPEN - MIN_SHARPEN);
copy_matrix (sharpen_matrix, custom_matrix, matrix_size);
break;
case CUSTOM_CONVOLVE:
matrix_size = 5;
break;
}
integer_matrix (custom_matrix, matrix, matrix_size);
matrix_divisor = sum_matrix (matrix, matrix_size);
if (!matrix_divisor)
matrix_divisor = 1;
}
static void
integer_matrix (gfloat *source,
gint *dest,
gint size)
{
gint i;
#define PRECISION 10000
for (i = 0; i < size*size; i++)
*dest++ = (gint) (*source ++ * PRECISION);
}
static void
copy_matrix (gfloat *src,
gfloat *dest,
gint size)
{
gint i;
for (i = 0; i < size*size; i++)
*dest++ = *src++;
}
static int
sum_matrix (gint *matrix,
gint size)
{
gint sum = 0;
size *= size;
while (size --)
sum += *matrix++;
return sum;
}
static gpointer
convolve_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
convolve_motion (paint_core, drawable, &non_gui_pressure_options,
non_gui_type, non_gui_rate);
return NULL;
}
gboolean
convolve_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array)
{
gdouble rate = DEFAULT_CONVOLVE_RATE;
ConvolveType type = DEFAULT_CONVOLVE_TYPE;
ConvolveOptions *options = convolve_options;
if (options)
{
rate = options->rate;
type = options->type;
}
return convolve_non_gui (drawable, rate, type, num_strokes, stroke_array);
}
gboolean
convolve_non_gui (GimpDrawable *drawable,
double rate,
ConvolveType type,
gint num_strokes,
gdouble *stroke_array)
{
gint i;
if (paint_core_init (&non_gui_paint_core, drawable,
stroke_array[0], stroke_array[1]))
{
/* Set the paint core's paint func */
non_gui_paint_core.paint_func = convolve_non_gui_paint_func;
non_gui_type = type;
non_gui_rate = rate;
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
convolve_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
for (i = 1; i < num_strokes; i++)
{
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
paint_core_interpolate (&non_gui_paint_core, drawable);
non_gui_paint_core.lastx = non_gui_paint_core.curx;
non_gui_paint_core.lasty = non_gui_paint_core.cury;
}
/* Finish the painting */
paint_core_finish (&non_gui_paint_core, drawable, -1);
/* Cleanup */
paint_core_cleanup ();
return TRUE;
}
return FALSE;
}

View File

@ -1,44 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CONVOLVE_H__
#define __CONVOLVE_H__
typedef enum
{
BLUR_CONVOLVE,
SHARPEN_CONVOLVE,
CUSTOM_CONVOLVE
} ConvolveType;
gboolean convolve_non_gui (GimpDrawable *drawable,
gdouble rate,
ConvolveType type,
gint num_strokes,
gdouble *stroke_array);
gboolean convolve_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array);
Tool * tools_new_convolve (void);
void tools_free_convolve (Tool *tool);
#endif /* __CONVOLVE_H__ */

View File

@ -38,9 +38,10 @@
#include "paint_funcs.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "tools/tools.h"
#include "libgimp/gimpintl.h"
#include "tile_manager_pvt.h"

View File

@ -50,9 +50,11 @@
#include "gimprc.h"
#include "patterns.h"
#include "pattern_header.h"
#include "paint_core.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpintl.h"

View File

@ -50,9 +50,11 @@
#include "gimprc.h"
#include "patterns.h"
#include "pattern_header.h"
#include "paint_core.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpintl.h"

View File

@ -33,11 +33,13 @@
#include "appenv.h"
#include "gimpbrushgenerated.h"
#include "paint_core.h"
#include "gimprc.h"
#include "gimpbrush.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"

View File

@ -33,11 +33,13 @@
#include "appenv.h"
#include "gimpbrushgenerated.h"
#include "paint_core.h"
#include "gimprc.h"
#include "gimpbrush.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"

View File

@ -33,11 +33,13 @@
#include "appenv.h"
#include "gimpbrushgenerated.h"
#include "paint_core.h"
#include "gimprc.h"
#include "gimpbrush.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"

View File

@ -48,9 +48,11 @@
#include "patterns.h"
#include "gimpbrush.h"
#include "gimpbrushpipe.h"
#include "paint_core.h"
#include "gimprc.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpparasiteio.h"

View File

@ -48,9 +48,11 @@
#include "patterns.h"
#include "gimpbrush.h"
#include "gimpbrushpipe.h"
#include "paint_core.h"
#include "gimprc.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpparasiteio.h"

View File

@ -38,9 +38,10 @@
#include "paint_funcs.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "tools/tools.h"
#include "libgimp/gimpintl.h"
#include "tile_manager_pvt.h"

View File

@ -94,30 +94,31 @@
#include "apptypes.h"
#include "appenv.h"
#include "brightness_contrast.h"
#include "color_balance.h"
#include "convert.h"
#include "cursorutil.h"
#include "curves.h"
#include "drawable.h"
#include "floating_sel.h"
#include "fsdither.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "hue_saturation.h"
#include "layer.h"
#include "levels.h"
#include "undo.h"
#include "palette.h"
#include "gimppalette.h"
#include "palette_select.h"
#include "pixel_region.h"
#include "posterize.h"
#include "threshold.h"
#include "tile_manager.h"
#include "tile_manager_pvt.h" /* ick ick ick. */
#include "tools/brightness_contrast.h"
#include "tools/color_balance.h"
#include "tools/curves.h"
#include "tools/hue_saturation.h"
#include "tools/levels.h"
#include "tools/posterize.h"
#include "tools/threshold.h"
#include "libgimp/gimpcolorspace.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -31,14 +31,16 @@
#include "gimage_mask.h"
#include "gimprc.h"
#include "layer.h"
#include "paint_core.h"
#include "paint_funcs.h"
#include "paint_options.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tile_manager_pvt.h"
#include "undo.h"
#include "tools/paint_core.h"
#include "tools/paint_options.h"
#include "tools/tools.h"
#include "pdb/procedural_db.h"
#include "libgimp/gimpintl.h"

View File

@ -26,7 +26,6 @@
#include "apptypes.h"
#include "appenv.h"
#include "by_color_select.h"
#include "channel.h"
#include "draw_core.h"
#include "drawable.h"
@ -38,7 +37,6 @@
#include "gimpparasite.h"
#include "gimprc.h"
#include "layer.h"
#include "paint_core.h"
#include "paint_funcs.h"
#include "parasitelist.h"
#include "path_transform.h"
@ -46,10 +44,13 @@
#include "tile_manager.h"
#include "tile_manager_pvt.h"
#include "tile.h"
#include "tools.h"
#include "transform_core.h"
#include "undo.h"
#include "tools/by_color_select.h"
#include "tools/paint_core.h"
#include "tools/tools.h"
#include "tools/transform_core.h"
#include "libgimp/gimpparasite.h"
#include "libgimp/gimpintl.h"

View File

@ -51,7 +51,6 @@
#include "scale.h"
#include "scroll.h"
#include "selection.h"
#include "tools.h"
#include "undo.h"
@ -59,7 +58,8 @@
#include "gdisplay_color.h"
#endif /* DISPLAY_FILTERS */
#include "bezier_selectP.h"
#include "tools/bezier_selectP.h"
#include "tools/tools.h"
#include "libgimp/gimpmath.h"

1598
app/crop.c

File diff suppressed because it is too large Load Diff

View File

@ -1,43 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CROP_H__
#define __CROP_H__
typedef enum
{
CROP_CROP,
RESIZE_CROP
} CropType;
void crop_draw (Tool *tool);
void crop_image (GimpImage *gimage,
gint x1,
gint y1,
gint x2,
gint y2,
gboolean layer_only,
gboolean crop_layers);
Tool * tools_new_crop (void);
void tools_free_crop (Tool *tool);
#endif /* __CROP_H__ */

View File

@ -26,7 +26,8 @@
#include "cursorutil.h"
#include "dialog_handler.h"
#include "gdisplay.h" /* for gdisplay_*_override_cursor() */
#include "tools.h"
#include "tools/tools.h"
#include "cursors/mouse.xbm"
#include "cursors/mouse_mask.xbm"

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CURVES_H__
#define __CURVES_H__
#define SMOOTH 0
#define GFREE 1
typedef struct _CurvesDialog CurvesDialog;
struct _CurvesDialog
{
GtkWidget *shell;
GtkWidget *channel_menu;
GtkWidget *xrange;
GtkWidget *yrange;
GtkWidget *graph;
GdkPixmap *pixmap;
GtkWidget *curve_type_menu;
GimpDrawable *drawable;
ImageMap image_map;
gint color;
gint channel;
gboolean preview;
gint grab_point;
gint last;
gint leftmost;
gint rightmost;
gint curve_type[5];
gint points[5][17][2];
guchar curve[5][256];
gint col_value[5];
gint cursor_ind_height;
gint cursor_ind_width;
gint cursor_ind_ascent;
GimpLut *lut;
};
Tool * tools_new_curves (void);
void tools_free_curves (Tool *tool);
void curves_dialog_hide (void);
void curves_initialize (GDisplay *gdisp);
void curves_free (void);
gfloat curves_lut_func (CurvesDialog *cd,
gint nchannels,
gint channel,
gfloat value);
void curves_calculate_curve (CurvesDialog *cd);
#endif /* __CURVES_H__ */

View File

@ -39,7 +39,8 @@
#include "gradient_header.h"
#include "patterns.h"
#include "session.h"
#include "tools.h"
#include "tools/tools.h"
#include "libgimp/gimpenv.h"
#include "libgimp/gimpcolorarea.h"

View File

@ -34,7 +34,8 @@
#include "info_dialog.h"
#include "info_window.h"
#include "scroll.h"
#include "tools.h"
#include "tools/tools.h"
#include "pdb/procedural_db.h"

View File

@ -26,7 +26,6 @@
#include "apptypes.h"
#include "appenv.h"
#include "bucket_fill.h"
#include "cursorutil.h"
#include "devices.h"
#include "dialog_handler.h"
@ -39,7 +38,6 @@
#include "info_window.h"
#include "layer.h"
#include "layer_select.h"
#include "move.h"
#include "paint_funcs.h"
#include "patterns.h"
#include "pixel_region.h"
@ -48,9 +46,12 @@
#include "selection.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "tools/bucket_fill.h"
#include "tools/move.h"
#include "tools/tools.h"
#include "libgimp/gimpintl.h"

View File

@ -26,7 +26,6 @@
#include "apptypes.h"
#include "appenv.h"
#include "bucket_fill.h"
#include "cursorutil.h"
#include "devices.h"
#include "dialog_handler.h"
@ -39,7 +38,6 @@
#include "info_window.h"
#include "layer.h"
#include "layer_select.h"
#include "move.h"
#include "paint_funcs.h"
#include "patterns.h"
#include "pixel_region.h"
@ -48,9 +46,12 @@
#include "selection.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "tools/bucket_fill.h"
#include "tools/move.h"
#include "tools/tools.h"
#include "libgimp/gimpintl.h"

View File

@ -31,7 +31,8 @@
#include "gimprc.h"
#include "nav_window.h"
#include "scale.h"
#include "tools.h"
#include "tools/tools.h"
void

View File

@ -30,7 +30,8 @@
#include "scale.h"
#include "scroll.h"
#include "nav_window.h"
#include "tools.h"
#include "tools/tools.h"
/* This is the delay before dithering begins

View File

@ -51,7 +51,6 @@
#include "scale.h"
#include "scroll.h"
#include "selection.h"
#include "tools.h"
#include "undo.h"
@ -59,7 +58,8 @@
#include "gdisplay_color.h"
#endif /* DISPLAY_FILTERS */
#include "bezier_selectP.h"
#include "tools/bezier_selectP.h"
#include "tools/tools.h"
#include "libgimp/gimpmath.h"

View File

@ -26,7 +26,6 @@
#include "apptypes.h"
#include "appenv.h"
#include "bucket_fill.h"
#include "cursorutil.h"
#include "devices.h"
#include "dialog_handler.h"
@ -39,7 +38,6 @@
#include "info_window.h"
#include "layer.h"
#include "layer_select.h"
#include "move.h"
#include "paint_funcs.h"
#include "patterns.h"
#include "pixel_region.h"
@ -48,9 +46,12 @@
#include "selection.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "tools/bucket_fill.h"
#include "tools/move.h"
#include "tools/tools.h"
#include "libgimp/gimpintl.h"

View File

@ -54,7 +54,8 @@
#include "session.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tools.h"
#include "tools/tools.h"
#include "pixmaps.h"
#include "pixmaps/qmasksel.xpm"

View File

@ -31,7 +31,8 @@
#include "gimprc.h"
#include "nav_window.h"
#include "scale.h"
#include "tools.h"
#include "tools/tools.h"
void

View File

@ -30,7 +30,8 @@
#include "scale.h"
#include "scroll.h"
#include "nav_window.h"
#include "tools.h"
#include "tools/tools.h"
/* This is the delay before dithering begins

View File

@ -54,7 +54,8 @@
#include "session.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tools.h"
#include "tools/tools.h"
#include "pixmaps.h"
#include "pixmaps/qmasksel.xpm"

View File

@ -1,667 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "apptypes.h"
#include "appenv.h"
#include "drawable.h"
#include "dodgeburn.h"
#include "gdisplay.h"
#include "gimplut.h"
#include "gimpcontext.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "paint_options.h"
#include "pixel_region.h"
#include "selection.h"
#include "temp_buf.h"
#include "tools.h"
#include "gimage.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"
/* Default values */
#define DODGEBURN_DEFAULT_TYPE DODGE
#define DODGEBURN_DEFAULT_EXPOSURE 50.0
#define DODGEBURN_DEFAULT_MODE DODGEBURN_HIGHLIGHTS
/* the dodgeburn structures */
typedef struct _DodgeBurnOptions DodgeBurnOptions;
struct _DodgeBurnOptions
{
PaintOptions paint_options;
DodgeBurnType type;
DodgeBurnType type_d;
GtkWidget *type_w[2];
DodgeBurnMode mode; /*highlights, midtones, shadows*/
DodgeBurnMode mode_d;
GtkWidget *mode_w[3];
gdouble exposure;
gdouble exposure_d;
GtkObject *exposure_w;
GimpLut *lut;
};
static gpointer dodgeburn_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state);
static void dodgeburn_make_luts (PaintCore *paint_cure,
gdouble db_exposure,
DodgeBurnType type,
DodgeBurnMode mode,
GimpLut *lut,
GimpDrawable *drawable);
static gfloat dodgeburn_highlights_lut_func (gpointer user_data,
gint nchannels,
gint channel,
gfloat value);
static gfloat dodgeburn_midtones_lut_func (gpointer user_data,
gint nchannels,
gint channel,
gfloat value);
static gfloat dodgeburn_shadows_lut_func (gpointer user_data,
gint nchannels,
gint channel,
gfloat value);
static void dodgeburn_motion (PaintCore *paint_core,
PaintPressureOptions *pressure_options,
gdouble dodgeburn_exposure,
GimpLut *lut,
GimpDrawable *drawable);
static void dodgeburn_init (PaintCore *paint_cure,
GimpDrawable *drawable);
static void dodgeburn_finish (PaintCore *paint_core,
GimpDrawable *drawable);
/* the dodgeburn tool options */
static DodgeBurnOptions * dodgeburn_options = NULL;
/* Non gui function */
static gdouble non_gui_exposure;
static GimpLut *non_gui_lut;
/* functions */
static void
dodgeburn_options_reset (void)
{
DodgeBurnOptions *options = dodgeburn_options;
paint_options_reset ((PaintOptions *) options);
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->exposure_w),
options->exposure_d);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->mode_w[options->mode_d]), TRUE);
}
static DodgeBurnOptions *
dodgeburn_options_new (void)
{
DodgeBurnOptions *options;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *scale;
GtkWidget *frame;
/* the new dodgeburn tool options structure */
options = g_new (DodgeBurnOptions, 1);
paint_options_init ((PaintOptions *) options,
DODGEBURN,
dodgeburn_options_reset);
options->type = options->type_d = DODGEBURN_DEFAULT_TYPE;
options->exposure = options->exposure_d = DODGEBURN_DEFAULT_EXPOSURE;
options->mode = options->mode_d = DODGEBURN_DEFAULT_MODE;
/* the main vbox */
vbox = ((ToolOptions *) options)->main_vbox;
/* the exposure scale */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Exposure:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
options->exposure_w =
gtk_adjustment_new (options->exposure_d, 0.0, 100.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->exposure_w));
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (options->exposure_w), "value_changed",
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
&options->exposure);
gtk_widget_show (scale);
gtk_widget_show (hbox);
/* the type (dodge or burn) */
frame = gimp_radio_group_new2 (TRUE, _("Type"),
gimp_radio_button_update,
&options->type, (gpointer) options->type,
_("Dodge"), (gpointer) DODGE,
&options->type_w[0],
_("Burn"), (gpointer) BURN,
&options->type_w[1],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
/* mode (highlights, midtones, or shadows) */
frame =
gimp_radio_group_new2 (TRUE, _("Mode"),
gimp_radio_button_update,
&options->mode, (gpointer) options->mode,
_("Highlights"), (gpointer) DODGEBURN_HIGHLIGHTS,
&options->mode_w[0],
_("Midtones"), (gpointer) DODGEBURN_MIDTONES,
&options->mode_w[1],
_("Shadows"), (gpointer) DODGEBURN_SHADOWS,
&options->mode_w[2],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
return options;
}
static gpointer
dodgeburn_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
switch (state)
{
case INIT_PAINT:
dodgeburn_init (paint_core, drawable);
break;
case MOTION_PAINT:
dodgeburn_motion (paint_core,
dodgeburn_options->paint_options.pressure_options,
dodgeburn_options->exposure, dodgeburn_options->lut, drawable);
break;
case FINISH_PAINT:
dodgeburn_finish (paint_core, drawable);
break;
default:
break;
}
return NULL;
}
static void
dodgeburn_finish (PaintCore *paint_core,
GimpDrawable *drawable)
{
/* Here we destroy the luts to do the painting with.*/
if (dodgeburn_options->lut)
{
gimp_lut_free (dodgeburn_options->lut);
dodgeburn_options->lut = NULL;
}
}
static void
dodgeburn_init (PaintCore *paint_core,
GimpDrawable *drawable)
{
/* Here we create the luts to do the painting with.*/
dodgeburn_options->lut = gimp_lut_new ();
dodgeburn_make_luts (paint_core,
dodgeburn_options->exposure,
dodgeburn_options->type,
dodgeburn_options->mode,
dodgeburn_options->lut,
drawable);
}
static void
dodgeburn_make_luts (PaintCore *paint_core,
gdouble db_exposure,
DodgeBurnType type,
DodgeBurnMode mode,
GimpLut *lut,
GimpDrawable *drawable)
{
GimpLutFunc lut_func;
gint nchannels = gimp_drawable_bytes (drawable);
static gfloat exposure;
exposure = db_exposure / 100.0;
/* make the exposure negative if burn for luts*/
if (type == BURN)
exposure = -exposure;
switch (mode)
{
case DODGEBURN_HIGHLIGHTS:
lut_func = dodgeburn_highlights_lut_func;
break;
case DODGEBURN_MIDTONES:
lut_func = dodgeburn_midtones_lut_func;
break;
case DODGEBURN_SHADOWS:
lut_func = dodgeburn_shadows_lut_func;
break;
default:
lut_func = NULL;
break;
}
gimp_lut_setup_exact (lut,
lut_func, (gpointer) &exposure,
nchannels);
}
static void
dodgeburn_modifier_key_func (Tool *tool,
GdkEventKey *kevent,
GDisplay *gdisp)
{
switch (kevent->keyval)
{
case GDK_Alt_L:
case GDK_Alt_R:
break;
case GDK_Shift_L:
case GDK_Shift_R:
if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */
{
switch (dodgeburn_options->type)
{
case BURN:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[DODGE]), TRUE);
break;
case DODGE:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[BURN]), TRUE);
break;
default:
break;
}
}
break;
case GDK_Control_L:
case GDK_Control_R:
if (! (kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */
{
switch (dodgeburn_options->type)
{
case BURN:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[DODGE]), TRUE);
break;
case DODGE:
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[BURN]), TRUE);
break;
default:
break;
}
}
break;
}
tool->toggled = (dodgeburn_options->type == BURN);
}
static void
dodgeburn_cursor_update_func (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
tool->toggled = (dodgeburn_options->type == BURN);
paint_core_cursor_update (tool, mevent, gdisp);
}
Tool *
tools_new_dodgeburn (void)
{
Tool *tool;
PaintCore *private;
/* The tool options */
if (! dodgeburn_options)
{
dodgeburn_options = dodgeburn_options_new ();
tools_register (DODGEBURN, (ToolOptions *) dodgeburn_options);
/* press all default buttons */
dodgeburn_options_reset ();
}
tool = paint_core_new (DODGEBURN);
tool->modifier_key_func = dodgeburn_modifier_key_func;
tool->cursor_update_func = dodgeburn_cursor_update_func;
private = (PaintCore *) tool->private;
private->paint_func = dodgeburn_paint_func;
private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH;
return tool;
}
void
tools_free_dodgeburn (Tool *tool)
{
/* delete any luts here */
paint_core_free (tool);
}
static void
dodgeburn_motion (PaintCore *paint_core,
PaintPressureOptions *pressure_options,
double dodgeburn_exposure,
GimpLut *lut,
GimpDrawable *drawable)
{
GImage *gimage;
TempBuf * area;
TempBuf * orig;
PixelRegion srcPR, destPR, tempPR;
guchar *temp_data;
gint opacity;
gdouble scale;
if (! (gimage = gimp_drawable_gimage (drawable)))
return;
/* If the image type is indexed, don't dodgeburn */
if ((gimp_drawable_type (drawable) == INDEXED_GIMAGE) ||
(gimp_drawable_type (drawable) == INDEXEDA_GIMAGE))
return;
if (pressure_options->size)
scale = paint_core->curpressure;
else
scale = 1.0;
/* Get a region which can be used to paint to */
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
return;
/* Constant painting --get a copy of the orig drawable (with
no paint from this stroke yet) */
{
gint x1, y1, x2, y2;
x1 = CLAMP (area->x, 0, gimp_drawable_width (drawable));
y1 = CLAMP (area->y, 0, gimp_drawable_height (drawable));
x2 = CLAMP (area->x + area->width, 0, gimp_drawable_width (drawable));
y2 = CLAMP (area->y + area->height, 0, gimp_drawable_height (drawable));
if (!(x2 - x1) || !(y2 - y1))
return;
/* get the original untouched image */
orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2);
srcPR.bytes = orig->bytes;
srcPR.x = 0;
srcPR.y = 0;
srcPR.w = x2 - x1;
srcPR.h = y2 - y1;
srcPR.rowstride = srcPR.bytes * orig->width;
srcPR.data = temp_buf_data (orig);
}
/* tempPR will hold the dodgeburned region*/
tempPR.bytes = srcPR.bytes;
tempPR.x = srcPR.x;
tempPR.y = srcPR.y;
tempPR.w = srcPR.w;
tempPR.h = srcPR.h;
tempPR.rowstride = tempPR.bytes * tempPR.w;
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
tempPR.data = temp_data;
/* DodgeBurn the region */
gimp_lut_process (lut, &srcPR, &tempPR);
/* The dest is the paint area we got above (= canvas_buf) */
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = area->width;
destPR.h = area->height;
destPR.rowstride = area->width * destPR.bytes;
destPR.data = temp_buf_data (area);
/* Now add an alpha to the dodgeburned region
and put this in area = canvas_buf */
if (! gimp_drawable_has_alpha (drawable))
add_alpha_region (&tempPR, &destPR);
else
copy_region (&tempPR, &destPR);
opacity = 255 * gimp_context_get_opacity (NULL);
if (pressure_options->opacity)
opacity = opacity * 2.0 * paint_core->curpressure;
/* Replace the newly dodgedburned area (canvas_buf) to the gimage*/
paint_core_replace_canvas (paint_core, drawable,
MIN (opacity, 255),
OPAQUE_OPACITY,
pressure_options->pressure ? PRESSURE : SOFT,
scale, CONSTANT);
g_free (temp_data);
}
static gpointer
dodgeburn_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
dodgeburn_motion (paint_core, &non_gui_pressure_options,
non_gui_exposure, non_gui_lut, drawable);
return NULL;
}
gboolean
dodgeburn_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array)
{
gdouble exposure = DODGEBURN_DEFAULT_TYPE;
DodgeBurnType type = DODGEBURN_DEFAULT_TYPE;
DodgeBurnMode mode = DODGEBURN_DEFAULT_MODE;
DodgeBurnOptions *options = dodgeburn_options;
if (options)
{
exposure = dodgeburn_options->exposure;
type = dodgeburn_options->type;
mode = dodgeburn_options->mode;
}
return dodgeburn_non_gui (drawable, exposure, type, mode,
num_strokes, stroke_array);
}
gboolean
dodgeburn_non_gui (GimpDrawable *drawable,
gdouble exposure,
DodgeBurnType type,
DodgeBurnMode mode,
gint num_strokes,
gdouble *stroke_array)
{
gint i;
if (paint_core_init (&non_gui_paint_core, drawable,
stroke_array[0], stroke_array[1]))
{
/* Set the paint core's paint func */
non_gui_paint_core.paint_func = dodgeburn_non_gui_paint_func;
non_gui_exposure = exposure;
non_gui_lut = gimp_lut_new();
dodgeburn_make_luts (&non_gui_paint_core,
exposure,
type,
mode,
non_gui_lut,
drawable);
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
dodgeburn_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
for (i = 1; i < num_strokes; i++)
{
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
paint_core_interpolate (&non_gui_paint_core, drawable);
non_gui_paint_core.lastx = non_gui_paint_core.curx;
non_gui_paint_core.lasty = non_gui_paint_core.cury;
}
/* Finish the painting */
paint_core_finish (&non_gui_paint_core, drawable, -1);
/* Cleanup */
paint_core_cleanup ();
gimp_lut_free (non_gui_lut);
return TRUE;
}
else
return FALSE;
}
static gfloat
dodgeburn_highlights_lut_func (gpointer user_data,
gint nchannels,
gint channel,
gfloat value)
{
gfloat *exposure_ptr = (gfloat *) user_data;
gfloat exposure = *exposure_ptr;
gfloat factor = 1.0 + exposure * (.333333);
if ((nchannels == 2 && channel == 1) ||
(nchannels == 4 && channel == 3))
return value;
return factor * value;
}
static gfloat
dodgeburn_midtones_lut_func (gpointer user_data,
gint nchannels,
gint channel,
gfloat value)
{
gfloat *exposure_ptr = (gfloat *) user_data;
gfloat exposure = *exposure_ptr;
gfloat factor;
if ((nchannels == 2 && channel == 1) ||
(nchannels == 4 && channel == 3))
return value;
if (exposure < 0)
factor = 1.0 - exposure * (.333333);
else
factor = 1/(1.0 + exposure);
return pow (value, factor);
}
static gfloat
dodgeburn_shadows_lut_func (gpointer user_data,
gint nchannels,
gint channel,
gfloat value)
{
gfloat *exposure_ptr = (gfloat *) user_data;
gfloat exposure = *exposure_ptr;
gfloat new_value;
gfloat factor;
if ( (nchannels == 2 && channel == 1) ||
(nchannels == 4 && channel == 3))
return value;
if (exposure >= 0)
{
factor = 0.333333 * exposure;
new_value = factor + value - factor * value;
}
else /* exposure < 0 */
{
factor = -0.333333 * exposure;
if (value < factor)
new_value = 0;
else /*factor <= value <=1*/
new_value = (value - factor)/(1 - factor);
}
return new_value;
}

View File

@ -1,51 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __DODGEBURN_H__
#define __DODGEBURN_H__
typedef enum
{
DODGE,
BURN
} DodgeBurnType;
typedef enum
{
DODGEBURN_HIGHLIGHTS,
DODGEBURN_MIDTONES,
DODGEBURN_SHADOWS
} DodgeBurnMode;
gboolean dodgeburn_non_gui (GimpDrawable *drawable,
gdouble exposure,
DodgeBurnType type,
DodgeBurnMode mode,
gint num_strokes,
gdouble *stroke_array);
gboolean dodgeburn_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array);
Tool * tools_new_dodgeburn (void);
void tools_free_dodgeburn (Tool *tool);
#endif /* __DODGEBURN_H__ */

View File

@ -31,7 +31,6 @@
#include "cursorutil.h"
#include "draw_core.h"
#include "drawable.h"
#include "tools.h"
#include "edit_selection.h"
#include "floating_sel.h"
#include "gimpimage.h"
@ -43,6 +42,8 @@
#include "selection.h"
#include "undo.h"
#include "tools/tools.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"

View File

@ -1,165 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "channel.h"
#include "draw_core.h"
#include "edit_selection.h"
#include "ellipse_select.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "gimpimage.h"
#include "rect_select.h"
#include "rect_selectP.h"
#include "selection_options.h"
#include "tools.h"
#include "tool_options.h"
/* the ellipse selection tool options */
SelectionOptions * ellipse_options = NULL;
/*************************************/
/* Ellipsoidal selection apparatus */
void
ellipse_select (GimpImage *gimage,
gint x,
gint y,
gint w,
gint h,
SelectOps op,
gboolean antialias,
gboolean feather,
gdouble feather_radius)
{
Channel *new_mask;
/* if applicable, replace the current selection */
if (op == SELECTION_REPLACE)
gimage_mask_clear (gimage);
else
gimage_mask_undo (gimage);
/* if feathering for rect, make a new mask with the
* rectangle and feather that with the old mask
*/
if (feather)
{
new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
channel_combine_ellipse (new_mask, CHANNEL_OP_ADD, x, y, w, h, antialias);
channel_feather (new_mask, gimp_image_get_mask (gimage),
feather_radius,
feather_radius,
op, 0, 0);
channel_delete (new_mask);
}
else if (op == SELECTION_INTERSECT)
{
new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
channel_combine_ellipse (new_mask, CHANNEL_OP_ADD, x, y, w, h, antialias);
channel_combine_mask (gimp_image_get_mask (gimage), new_mask, op, 0, 0);
channel_delete (new_mask);
}
else
channel_combine_ellipse (gimp_image_get_mask (gimage), op,
x, y, w, h, antialias);
}
void
ellipse_select_draw (Tool *tool)
{
EllipseSelect *ellipse_sel;
gint x1, y1;
gint x2, y2;
ellipse_sel = (EllipseSelect *) tool->private;
x1 = MIN (ellipse_sel->x, ellipse_sel->x + ellipse_sel->w);
y1 = MIN (ellipse_sel->y, ellipse_sel->y + ellipse_sel->h);
x2 = MAX (ellipse_sel->x, ellipse_sel->x + ellipse_sel->w);
y2 = MAX (ellipse_sel->y, ellipse_sel->y + ellipse_sel->h);
gdisplay_transform_coords (tool->gdisp, x1, y1, &x1, &y1, 0);
gdisplay_transform_coords (tool->gdisp, x2, y2, &x2, &y2, 0);
gdk_draw_arc (ellipse_sel->core->win,
ellipse_sel->core->gc, 0,
x1, y1, (x2 - x1), (y2 - y1), 0, 23040);
}
static void
ellipse_select_options_reset (void)
{
selection_options_reset (ellipse_options);
}
Tool *
tools_new_ellipse_select (void)
{
Tool *tool;
EllipseSelect *private;
/* The tool options */
if (!ellipse_options)
{
ellipse_options =
selection_options_new (ELLIPSE_SELECT, ellipse_select_options_reset);
tools_register (ELLIPSE_SELECT, (ToolOptions *) ellipse_options);
}
tool = tools_new_tool (ELLIPSE_SELECT);
private = g_new0 (EllipseSelect, 1);
private->core = draw_core_new (ellipse_select_draw);
/* Make the selection static, not blinking */
private->x = private->y = 0;
private->w = private->h = 0;
tool->private = (void *) private;
tool->button_press_func = rect_select_button_press;
tool->button_release_func = rect_select_button_release;
tool->motion_func = rect_select_motion;
tool->modifier_key_func = rect_select_modifier_update;
tool->cursor_update_func = rect_select_cursor_update;
tool->oper_update_func = rect_select_oper_update;
tool->control_func = rect_select_control;
return tool;
}
void
tools_free_ellipse_select (Tool *tool)
{
EllipseSelect *ellipse_sel;
ellipse_sel = (EllipseSelect *) tool->private;
draw_core_free (ellipse_sel->core);
g_free (ellipse_sel);
}

View File

@ -1,38 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ELLIPSE_SELECT_H__
#define __ELLIPSE_SELECT_H__
void ellipse_select (GimpImage *gimage,
gint x,
gint y,
gint w,
gint h,
SelectOps op,
gboolean antialias,
gboolean feather,
gdouble feather_radius);
void ellipse_select_draw (Tool *tool);
Tool * tools_new_ellipse_select (void);
void tools_free_ellipse_select (Tool *tool);
#endif /* __ELLIPSE_SELECT_H__ */

View File

@ -1,364 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "apptypes.h"
#include "appenv.h"
#include "cursorutil.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "gimpcontext.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "paint_options.h"
#include "eraser.h"
#include "selection.h"
#include "temp_buf.h"
#include "tools.h"
#include "libgimp/gimpintl.h"
/* Defaults */
#define ERASER_DEFAULT_HARD FALSE
#define ERASER_DEFAULT_INCREMENTAL FALSE
#define ERASER_DEFAULT_ANTI_ERASE FALSE
/* the eraser structures */
typedef struct _EraserOptions EraserOptions;
struct _EraserOptions
{
PaintOptions paint_options;
gboolean hard;
gboolean hard_d;
GtkWidget *hard_w;
gboolean anti_erase;
gboolean anti_erase_d;
GtkWidget *anti_erase_w;
};
/* forward function declarations */
static gpointer eraser_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state);
static void eraser_motion (PaintCore *paint_core,
GimpDrawable *drawable,
PaintPressureOptions *pressure_options,
gboolean hard,
gboolean incremental,
gboolean anti_erase);
/* the eraser tool options */
static EraserOptions *eraser_options = NULL;
/* local variables */
static gboolean non_gui_hard;
static gboolean non_gui_incremental;
static gboolean non_gui_anti_erase;
/* functions */
static void
eraser_options_reset (void)
{
EraserOptions *options = eraser_options;
paint_options_reset ((PaintOptions *) options);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w),
options->hard_d);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w),
options->anti_erase_d);
}
static EraserOptions *
eraser_options_new (void)
{
EraserOptions *options;
GtkWidget *vbox;
/* the new eraser tool options structure */
options = g_new (EraserOptions, 1);
paint_options_init ((PaintOptions *) options,
ERASER,
eraser_options_reset);
options->hard = options->hard_d = ERASER_DEFAULT_HARD;
options->anti_erase = options->anti_erase_d = ERASER_DEFAULT_ANTI_ERASE;
/* the main vbox */
vbox = ((ToolOptions *) options)->main_vbox;
/* the hard toggle */
options->hard_w = gtk_check_button_new_with_label (_("Hard Edge"));
gtk_box_pack_start (GTK_BOX (vbox), options->hard_w, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (options->hard_w), "toggled",
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&options->hard);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w),
options->hard_d);
gtk_widget_show (options->hard_w);
/* the anti_erase toggle */
options->anti_erase_w = gtk_check_button_new_with_label (_("Anti Erase"));
gtk_box_pack_start (GTK_BOX (vbox), options->anti_erase_w, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (options->anti_erase_w), "toggled",
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&options->anti_erase);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w),
options->anti_erase_d);
gtk_widget_show (options->anti_erase_w);
return options;
}
static void
eraser_modifier_key_func (Tool *tool,
GdkEventKey *kevent,
GDisplay *gdisp)
{
switch (kevent->keyval)
{
case GDK_Alt_L:
case GDK_Alt_R:
break;
case GDK_Shift_L:
case GDK_Shift_R:
if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w),
! eraser_options->anti_erase);
break;
case GDK_Control_L:
case GDK_Control_R:
if (!(kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w),
! eraser_options->anti_erase);
break;
}
tool->toggled = eraser_options->anti_erase;
}
static gpointer
eraser_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
switch (state)
{
case INIT_PAINT:
break;
case MOTION_PAINT:
eraser_motion (paint_core,
drawable,
eraser_options->paint_options.pressure_options,
eraser_options->hard,
eraser_options->paint_options.incremental,
eraser_options->anti_erase);
break;
case FINISH_PAINT:
break;
default:
break;
}
return NULL;
}
Tool *
tools_new_eraser (void)
{
Tool *tool;
PaintCore *private;
/* The tool options */
if (! eraser_options)
{
eraser_options = eraser_options_new ();
tools_register (ERASER, (ToolOptions *) eraser_options);
}
tool = paint_core_new (ERASER);
private = (PaintCore *) tool->private;
private->paint_func = eraser_paint_func;
private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH;
tool->modifier_key_func = eraser_modifier_key_func;
return tool;
}
void
tools_free_eraser (Tool *tool)
{
paint_core_free (tool);
}
static void
eraser_motion (PaintCore *paint_core,
GimpDrawable *drawable,
PaintPressureOptions *pressure_options,
gboolean hard,
gboolean incremental,
gboolean anti_erase)
{
GImage *gimage;
gint opacity;
TempBuf *area;
guchar col[MAX_CHANNELS];
gdouble scale;
if (! (gimage = gimp_drawable_gimage (drawable)))
return;
gimp_image_get_background (gimage, drawable, col);
if (pressure_options->size)
scale = paint_core->curpressure;
else
scale = 1.0;
/* Get a region which can be used to paint to */
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
return;
/* set the alpha channel */
col[area->bytes - 1] = OPAQUE_OPACITY;
/* color the pixels */
color_pixels (temp_buf_data (area), col,
area->width * area->height, area->bytes);
opacity = 255 * gimp_context_get_opacity (NULL);
if (pressure_options->opacity)
opacity = opacity * 2.0 * paint_core->curpressure;
/* paste the newly painted canvas to the gimage which is being worked on */
paint_core_paste_canvas (paint_core, drawable,
MIN (opacity, 255),
(int) (gimp_context_get_opacity (NULL) * 255),
anti_erase ? ANTI_ERASE_MODE : ERASE_MODE,
hard ? HARD : (pressure_options->pressure ? PRESSURE : SOFT),
scale,
incremental ? INCREMENTAL : CONSTANT);
}
static gpointer
eraser_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
PaintState state)
{
eraser_motion (paint_core, drawable,
&non_gui_pressure_options,
non_gui_hard, non_gui_incremental, non_gui_anti_erase);
return NULL;
}
gboolean
eraser_non_gui_default (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array)
{
gboolean hardness = ERASER_DEFAULT_HARD;
gboolean method = ERASER_DEFAULT_INCREMENTAL;
gboolean anti_erase = ERASER_DEFAULT_ANTI_ERASE;
EraserOptions *options = eraser_options;
if (options)
{
hardness = options->hard;
method = options->paint_options.incremental;
anti_erase = options->anti_erase;
}
return eraser_non_gui (drawable, num_strokes, stroke_array,
hardness, method, anti_erase);
}
gboolean
eraser_non_gui (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array,
gint hardness,
gint method,
gboolean anti_erase)
{
gint i;
if (paint_core_init (&non_gui_paint_core, drawable,
stroke_array[0], stroke_array[1]))
{
non_gui_hard = hardness;
non_gui_incremental = method;
non_gui_anti_erase = anti_erase;
/* Set the paint core's paint func */
non_gui_paint_core.paint_func = eraser_non_gui_paint_func;
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
eraser_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
for (i = 1; i < num_strokes; i++)
{
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
paint_core_interpolate (&non_gui_paint_core, drawable);
non_gui_paint_core.lastx = non_gui_paint_core.curx;
non_gui_paint_core.lasty = non_gui_paint_core.cury;
}
/* Finish the painting */
paint_core_finish (&non_gui_paint_core, drawable, -1);
/* Cleanup */
paint_core_cleanup ();
return TRUE;
}
return FALSE;
}

View File

@ -1,37 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ERASER_H__
#define __ERASER_H__
gboolean eraser_non_gui (GimpDrawable *drawable,
gint num_strokes,
gdouble *stroke_array,
gint hardness,
gint method,
gboolean anti_erase);
gboolean eraser_non_gui_default (GimpDrawable *paint_core,
gint num_strokes,
gdouble *stroke_array);
Tool * tools_new_eraser (void);
void tools_free_eraser (Tool *tool);
#endif /* __ERASER_H__ */

View File

@ -1,324 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "apptypes.h"
#include "appenv.h"
#include "cursorutil.h"
#include "drawable.h"
#include "flip_tool.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "paint_funcs.h"
#include "path_transform.h"
#include "pixel_region.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "tile_manager_pvt.h"
#include "tools.h"
#include "tool_options.h"
#include "transform_core.h"
#include "libgimp/gimpintl.h"
#define FLIP_INFO 0
/* the flip structures */
typedef struct _FlipOptions FlipOptions;
struct _FlipOptions
{
ToolOptions tool_options;
InternalOrientationType type;
InternalOrientationType type_d;
GtkWidget *type_w[2];
};
/* local function prototypes */
static TileManager * flip_tool_transform (Tool *tool,
GDisplay *gdisp,
TransformState state);
/* private variables */
static FlipOptions *flip_options = NULL;
/* functions */
/* FIXME: Lame - 1 hacks abound since the code assumes certain values for
* the ORIENTATION_FOO constants.
*/
static void
flip_options_reset (void)
{
FlipOptions *options = flip_options;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d - 1]), TRUE);
}
static FlipOptions *
flip_options_new (void)
{
FlipOptions *options;
GtkWidget *vbox;
GtkWidget *frame;
/* the new flip tool options structure */
options = g_new (FlipOptions, 1);
tool_options_init ((ToolOptions *) options,
_("Flip Tool"),
flip_options_reset);
options->type = options->type_d = ORIENTATION_HORIZONTAL;
/* the main vbox */
vbox = options->tool_options.main_vbox;
/* tool toggle */
frame =
gimp_radio_group_new2 (TRUE, _("Tool Toggle"),
gimp_radio_button_update,
&options->type, (gpointer) options->type,
_("Horizontal"), (gpointer) ORIENTATION_HORIZONTAL,
&options->type_w[0],
_("Vertical"), (gpointer) ORIENTATION_VERTICAL,
&options->type_w[1],
NULL);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
return options;
}
static void
flip_modifier_key_func (Tool *tool,
GdkEventKey *kevent,
GDisplay *gdisp)
{
switch (kevent->keyval)
{
case GDK_Alt_L: case GDK_Alt_R:
break;
case GDK_Shift_L: case GDK_Shift_R:
break;
case GDK_Control_L: case GDK_Control_R:
if (flip_options->type == ORIENTATION_HORIZONTAL)
{
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_VERTICAL - 1]), TRUE);
}
else
{
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_HORIZONTAL - 1]), TRUE);
}
break;
}
}
static TileManager *
flip_tool_transform (Tool *tool,
GDisplay *gdisp,
TransformState state)
{
TransformCore *transform_core;
transform_core = (TransformCore *) tool->private;
switch (state)
{
case TRANSFORM_INIT:
transform_info = NULL;
break;
case TRANSFORM_MOTION:
break;
case TRANSFORM_RECALC:
break;
case TRANSFORM_FINISH:
/* transform_core->trans_info[FLIP] *= -1.0;*/
return flip_tool_flip (gdisp->gimage,
gimp_image_active_drawable (gdisp->gimage),
transform_core->original,
(int) transform_core->trans_info[FLIP_INFO],
flip_options->type);
break;
}
return NULL;
}
static void
flip_cursor_update (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
GimpDrawable *drawable;
GdkCursorType ctype = GIMP_BAD_CURSOR;
if ((drawable = gimp_image_active_drawable (gdisp->gimage)))
{
gint x, y;
gint off_x, off_y;
gimp_drawable_offsets (drawable, &off_x, &off_y);
gdisplay_untransform_coords (gdisp,
(double) mevent->x, (double) mevent->y,
&x, &y, TRUE, FALSE);
if (x >= off_x && y >= off_y &&
x < (off_x + gimp_drawable_width (drawable)) &&
y < (off_y + gimp_drawable_height (drawable)))
{
/* Is there a selected region? If so, is cursor inside? */
if (gimage_mask_is_empty (gdisp->gimage) ||
gimage_mask_value (gdisp->gimage, x, y))
{
if (flip_options->type == ORIENTATION_HORIZONTAL)
ctype = GDK_SB_H_DOUBLE_ARROW;
else
ctype = GDK_SB_V_DOUBLE_ARROW;
}
}
}
gdisplay_install_tool_cursor (gdisp, ctype,
FLIP,
CURSOR_MODIFIER_NONE,
ctype == GDK_SB_V_DOUBLE_ARROW);
}
Tool *
tools_new_flip (void)
{
Tool *tool;
TransformCore *private;
/* The tool options */
if (! flip_options)
{
flip_options = flip_options_new ();
tools_register (FLIP, (ToolOptions *) flip_options);
}
tool = transform_core_new (FLIP, FALSE);
private = tool->private;
private->trans_func = flip_tool_transform;
private->trans_info[FLIP_INFO] = -1.0;
tool->modifier_key_func = flip_modifier_key_func;
tool->cursor_update_func = flip_cursor_update;
return tool;
}
void
tools_free_flip_tool (Tool *tool)
{
transform_core_free (tool);
}
TileManager *
flip_tool_flip (GimpImage *gimage,
GimpDrawable *drawable,
TileManager *orig,
gint flip,
InternalOrientationType type)
{
TileManager *new;
PixelRegion srcPR, destPR;
gint orig_width;
gint orig_height;
gint orig_bpp;
gint i;
if (! orig)
return NULL;
orig_width = tile_manager_level_width (orig);
orig_height = tile_manager_level_height (orig);
orig_bpp = tile_manager_level_bpp (orig);
if (flip > 0)
{
new = tile_manager_new (orig_width, orig_height, orig_bpp);
pixel_region_init (&srcPR, orig,
0, 0, orig_width, orig_height, FALSE);
pixel_region_init (&destPR, new,
0, 0, orig_width, orig_height, TRUE);
copy_region (&srcPR, &destPR);
new->x = orig->x;
new->y = orig->y;
}
else
{
new = tile_manager_new (orig_width, orig_height, orig_bpp);
new->x = orig->x;
new->y = orig->y;
if (type == ORIENTATION_HORIZONTAL)
for (i = 0; i < orig->width; i++)
{
pixel_region_init (&srcPR, orig, i, 0, 1, orig_height, FALSE);
pixel_region_init (&destPR, new,
(orig_width - i - 1), 0, 1, orig_height, TRUE);
copy_region (&srcPR, &destPR);
}
else
for (i = 0; i < orig->height; i++)
{
pixel_region_init (&srcPR, orig, 0, i, orig_width, 1, FALSE);
pixel_region_init (&destPR, new,
0, (orig_height - i - 1), orig_width, 1, TRUE);
copy_region (&srcPR, &destPR);
}
/* flip locked paths */
/* Note that the undo structures etc are setup before we enter this
* function.
*/
if (type == ORIENTATION_HORIZONTAL)
path_transform_flip_horz (gimage);
else
path_transform_flip_vert (gimage);
}
return new;
}

View File

@ -1,33 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __FLIP_TOOL_H__
#define __FLIP_TOOL_H__
TileManager * flip_tool_flip (GimpImage *gimage,
GimpDrawable *drawable,
TileManager *orig,
gint flip,
InternalOrientationType type);
Tool * tools_new_flip (void);
void tools_free_flip_tool (Tool *tool);
#endif /* __FLIP_TOOL_H__ */

View File

@ -1,391 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "channel.h"
#include "draw_core.h"
#include "edit_selection.h"
#include "errors.h"
#include "floating_sel.h"
#include "free_select.h"
#include "gimage_mask.h"
#include "gimpimage.h"
#include "gdisplay.h"
#include "rect_select.h"
#include "selection_options.h"
#include "scan_convert.h"
#include "tools.h"
#include "tool_options.h"
#include "libgimp/gimpmath.h"
#define DEFAULT_MAX_INC 1024
#define SUPERSAMPLE 3
#define SUPERSAMPLE2 9
/* the free selection structures */
typedef struct _FreeSelect FreeSelect;
struct _FreeSelect
{
DrawCore *core; /* Core select object */
SelectOps op; /* selection operation (ADD, SUB, etc) */
gint current_x; /* these values are updated on every motion event */
gint current_y; /* (enables immediate cursor updating on modifier
* key events). */
gint num_pts; /* Number of points in the polygon */
};
/* local function prototypes */
static void free_select_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void free_select_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void free_select_motion (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp);
/* the free selection tool options */
static SelectionOptions * free_options = NULL;
/* The global array of XPoints for drawing the polygon... */
static GdkPoint *global_pts = NULL;
static gint max_segs = 0;
/* functions */
static gint
add_point (gint num_pts,
gint x,
gint y)
{
if (num_pts >= max_segs)
{
max_segs += DEFAULT_MAX_INC;
global_pts = (GdkPoint *) g_realloc ((void *) global_pts, sizeof (GdkPoint) * max_segs);
if (!global_pts)
gimp_fatal_error ("add_point(): Unable to reallocate points array in free_select.");
}
global_pts[num_pts].x = x;
global_pts[num_pts].y = y;
return 1;
}
static Channel *
scan_convert (GimpImage *gimage,
gint num_pts,
ScanConvertPoint *pts,
gint width,
gint height,
gboolean antialias)
{
Channel *mask;
ScanConverter *sc;
sc = scan_converter_new (width, height, antialias ? SUPERSAMPLE : 1);
scan_converter_add_points (sc, num_pts, pts);
mask = scan_converter_to_channel (sc, gimage);
scan_converter_free (sc);
return mask;
}
/*************************************/
/* Polygonal selection apparatus */
void
free_select (GImage *gimage,
gint num_pts,
ScanConvertPoint *pts,
SelectOps op,
gboolean antialias,
gboolean feather,
gdouble feather_radius)
{
Channel *mask;
/* if applicable, replace the current selection */
/* or insure that a floating selection is anchored down... */
if (op == SELECTION_REPLACE)
gimage_mask_clear (gimage);
else
gimage_mask_undo (gimage);
mask = scan_convert (gimage, num_pts, pts,
gimage->width, gimage->height, antialias);
if (mask)
{
if (feather)
channel_feather (mask, gimp_image_get_mask (gimage),
feather_radius,
feather_radius,
op, 0, 0);
else
channel_combine_mask (gimp_image_get_mask (gimage),
mask, op, 0, 0);
channel_delete (mask);
}
}
static void
free_select_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
FreeSelect *free_sel;
free_sel = (FreeSelect *) tool->private;
gdk_pointer_grab (gdisp->canvas->window, FALSE,
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK,
NULL, NULL, bevent->time);
tool->state = ACTIVE;
tool->gdisp = gdisp;
switch (free_sel->op)
{
case SELECTION_MOVE_MASK:
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE);
return;
case SELECTION_MOVE:
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
return;
default:
break;
}
add_point (0, bevent->x, bevent->y);
free_sel->num_pts = 1;
draw_core_start (free_sel->core,
gdisp->canvas->window,
tool);
}
static void
free_select_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
FreeSelect *free_sel;
ScanConvertPoint *pts;
gint i;
free_sel = (FreeSelect *) tool->private;
gdk_pointer_ungrab (bevent->time);
gdk_flush ();
draw_core_stop (free_sel->core, tool);
tool->state = INACTIVE;
/* First take care of the case where the user "cancels" the action */
if (! (bevent->state & GDK_BUTTON3_MASK))
{
if (free_sel->op == SELECTION_ANCHOR)
{
/* If there is a floating selection, anchor it */
if (gimp_image_floating_sel (gdisp->gimage))
floating_sel_anchor (gimp_image_floating_sel (gdisp->gimage));
/* Otherwise, clear the selection mask */
else
gimage_mask_clear (gdisp->gimage);
gdisplays_flush ();
return;
}
pts = g_new (ScanConvertPoint, free_sel->num_pts);
for (i = 0; i < free_sel->num_pts; i++)
{
gdisplay_untransform_coords_f (gdisp, global_pts[i].x, global_pts[i].y,
&pts[i].x, &pts[i].y, FALSE);
}
free_select (gdisp->gimage, free_sel->num_pts, pts, free_sel->op,
free_options->antialias, free_options->feather,
free_options->feather_radius);
g_free (pts);
gdisplays_flush ();
}
}
static void
free_select_motion (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
FreeSelect *free_sel;
free_sel = (FreeSelect *) tool->private;
/* needed for immediate cursor update on modifier event */
free_sel->current_x = mevent->x;
free_sel->current_y = mevent->y;
if (tool->state != ACTIVE)
return;
if (free_sel->op == SELECTION_ANCHOR)
{
free_sel->op = SELECTION_REPLACE;
rect_select_cursor_update (tool, mevent, gdisp);
}
if (add_point (free_sel->num_pts, mevent->x, mevent->y))
{
gdk_draw_line (free_sel->core->win, free_sel->core->gc,
global_pts[free_sel->num_pts - 1].x,
global_pts[free_sel->num_pts - 1].y,
global_pts[free_sel->num_pts].x,
global_pts[free_sel->num_pts].y);
free_sel->num_pts ++;
}
}
static void
free_select_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
FreeSelect *free_sel;
free_sel = (FreeSelect *) tool->private;
switch (action)
{
case PAUSE:
draw_core_pause (free_sel->core, tool);
break;
case RESUME:
draw_core_resume (free_sel->core, tool);
break;
case HALT:
draw_core_stop (free_sel->core, tool);
break;
default:
break;
}
}
void
free_select_draw (Tool *tool)
{
FreeSelect *free_sel;
gint i;
free_sel = (FreeSelect *) tool->private;
for (i = 1; i < free_sel->num_pts; i++)
gdk_draw_line (free_sel->core->win, free_sel->core->gc,
global_pts[i - 1].x, global_pts[i - 1].y,
global_pts[i].x, global_pts[i].y);
}
static void
free_select_options_reset (void)
{
selection_options_reset (free_options);
}
Tool *
tools_new_free_select (void)
{
Tool *tool;
FreeSelect *private;
/* The tool options */
if (!free_options)
{
free_options =
selection_options_new (FREE_SELECT, free_select_options_reset);
tools_register (FREE_SELECT, (ToolOptions *) free_options);
}
tool = tools_new_tool (FREE_SELECT);
private = g_new0 (FreeSelect, 1);
private->core = draw_core_new (free_select_draw);
private->num_pts = 0;
private->op = SELECTION_REPLACE;
tool->scroll_lock = TRUE; /* Do not allow scrolling */
tool->private = (void *) private;
tool->button_press_func = free_select_button_press;
tool->button_release_func = free_select_button_release;
tool->motion_func = free_select_motion;
tool->modifier_key_func = rect_select_modifier_update;
tool->cursor_update_func = rect_select_cursor_update;
tool->oper_update_func = rect_select_oper_update;
tool->control_func = free_select_control;
return tool;
}
void
tools_free_free_select (Tool *tool)
{
FreeSelect *free_sel;
free_sel = (FreeSelect *) tool->private;
draw_core_free (free_sel->core);
g_free (free_sel);
}

View File

@ -1,38 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __FREE_SELECT_H__
#define __FREE_SELECT_H__
/* free select functions */
void free_select (GimpImage *gimage,
gint num_pts,
ScanConvertPoint *pts,
SelectOps op,
gboolean antialias,
gboolean feather,
gdouble feather_radius);
void free_select_draw (Tool *tool);
Tool * tools_new_free_select (void);
void tools_free_free_select (Tool *tool);
#endif /* __FREE_SELECT_H__ */

View File

@ -1,688 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "boundary.h"
#include "channel.h"
#include "cursorutil.h"
#include "draw_core.h"
#include "drawable.h"
#include "edit_selection.h"
#include "fuzzy_select.h"
#include "gimage_mask.h"
#include "gimpimage.h"
#include "gimprc.h"
#include "gimpui.h"
#include "gdisplay.h"
#include "pixel_region.h"
#include "rect_select.h"
#include "selection_options.h"
#include "tile_manager.h"
#include "tile.h"
#include "tools.h"
#include "tool_options.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"
/* the fuzzy selection structures */
typedef struct _FuzzySelect FuzzySelect;
struct _FuzzySelect
{
DrawCore *core; /* Core select object */
gint op; /* selection operation (ADD, SUB, etc) */
gint current_x; /* these values are updated on every motion event */
gint current_y; /* (enables immediate cursor updating on modifier
* key events). */
gint x, y; /* Point from which to execute seed fill */
gint first_x; /* */
gint first_y; /* variables to keep track of sensitivity */
gdouble first_threshold; /* initial value of threshold slider */
};
/* fuzzy select action functions */
static void fuzzy_select_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void fuzzy_select_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp);
static void fuzzy_select_motion (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp);
static void fuzzy_select_control (Tool *tool,
ToolAction tool_action,
GDisplay *gdisp);
static void fuzzy_select_draw (Tool *tool);
static GdkSegment * fuzzy_select_calculate (Tool *tool,
GDisplay *gdisp,
gint *nsegs);
/* the fuzzy selection tool options */
static SelectionOptions *fuzzy_options = NULL;
/* XSegments which make up the fuzzy selection boundary */
static GdkSegment *segs = NULL;
static gint num_segs = 0;
Channel * fuzzy_mask = NULL;
/*************************************/
/* Fuzzy selection apparatus */
static gint
is_pixel_sufficiently_different (guchar *col1,
guchar *col2,
gboolean antialias,
gint threshold,
gint bytes,
gboolean has_alpha)
{
gint diff;
gint max;
gint b;
gint alpha;
max = 0;
alpha = (has_alpha) ? bytes - 1 : bytes;
/* if there is an alpha channel, never select transparent regions */
if (has_alpha && col2[alpha] == 0)
return 0;
for (b = 0; b < bytes; b++)
{
diff = col1[b] - col2[b];
diff = abs (diff);
if (diff > max)
max = diff;
}
if (antialias)
{
float aa;
aa = 1.5 - ((float) max / threshold);
if (aa <= 0)
return 0;
else if (aa < 0.5)
return (unsigned char) (aa * 512);
else
return 255;
}
else
{
if (max > threshold)
return 0;
else
return 255;
}
}
static void
ref_tiles (TileManager *src,
TileManager *mask,
Tile **s_tile,
Tile **m_tile,
gint x,
gint y,
guchar **s,
guchar **m)
{
if (*s_tile != NULL)
tile_release (*s_tile, FALSE);
if (*m_tile != NULL)
tile_release (*m_tile, TRUE);
*s_tile = tile_manager_get_tile (src, x, y, TRUE, FALSE);
*m_tile = tile_manager_get_tile (mask, x, y, TRUE, TRUE);
*s = tile_data_pointer (*s_tile, x % TILE_WIDTH, y % TILE_HEIGHT);
*m = tile_data_pointer (*m_tile, x % TILE_WIDTH, y % TILE_HEIGHT);
}
static int
find_contiguous_segment (guchar *col,
PixelRegion *src,
PixelRegion *mask,
gint width,
gint bytes,
gboolean has_alpha,
gboolean antialias,
gint threshold,
gint initial,
gint *start,
gint *end)
{
guchar *s;
guchar *m;
guchar diff;
Tile *s_tile = NULL;
Tile *m_tile = NULL;
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, src->x, src->y, &s, &m);
/* check the starting pixel */
if (! (diff = is_pixel_sufficiently_different (col, s, antialias,
threshold, bytes, has_alpha)))
{
tile_release (s_tile, FALSE);
tile_release (m_tile, TRUE);
return FALSE;
}
*m-- = diff;
s -= bytes;
*start = initial - 1;
while (*start >= 0 && diff)
{
if (! ((*start + 1) % TILE_WIDTH))
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *start, src->y, &s, &m);
diff = is_pixel_sufficiently_different (col, s, antialias,
threshold, bytes, has_alpha);
if ((*m-- = diff))
{
s -= bytes;
(*start)--;
}
}
diff = 1;
*end = initial + 1;
if (*end % TILE_WIDTH && *end < width)
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *end, src->y, &s, &m);
while (*end < width && diff)
{
if (! (*end % TILE_WIDTH))
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *end, src->y, &s, &m);
diff = is_pixel_sufficiently_different (col, s, antialias,
threshold, bytes, has_alpha);
if ((*m++ = diff))
{
s += bytes;
(*end)++;
}
}
tile_release (s_tile, FALSE);
tile_release (m_tile, TRUE);
return TRUE;
}
static void
find_contiguous_region_helper (PixelRegion *mask,
PixelRegion *src,
gboolean has_alpha,
gboolean antialias,
gint threshold,
gboolean indexed,
gint x,
gint y,
guchar *col)
{
gint start, end, i;
gint val;
gint bytes;
Tile *tile;
if (threshold == 0) threshold = 1;
if (x < 0 || x >= src->w) return;
if (y < 0 || y >= src->h) return;
tile = tile_manager_get_tile (mask->tiles, x, y, TRUE, FALSE);
val = *(guchar *)(tile_data_pointer (tile,
x % TILE_WIDTH, y % TILE_HEIGHT));
tile_release (tile, FALSE);
if (val != 0)
return;
src->x = x;
src->y = y;
bytes = src->bytes;
if(indexed)
{
bytes = has_alpha ? 4 : 3;
}
if (! find_contiguous_segment (col, src, mask, src->w,
src->bytes, has_alpha,
antialias, threshold, x, &start, &end))
return;
for (i = start + 1; i < end; i++)
{
find_contiguous_region_helper (mask, src, has_alpha, antialias,
threshold, indexed, i, y - 1, col);
find_contiguous_region_helper (mask, src, has_alpha, antialias,
threshold, indexed, i, y + 1, col);
}
}
Channel *
find_contiguous_region (GImage *gimage,
GimpDrawable *drawable,
gboolean antialias,
gint threshold,
gint x,
gint y,
gboolean sample_merged)
{
PixelRegion srcPR, maskPR;
Channel *mask;
guchar *start;
gboolean has_alpha;
gboolean indexed;
gint type;
gint bytes;
Tile *tile;
if (sample_merged)
{
pixel_region_init (&srcPR, gimp_image_composite (gimage), 0, 0,
gimage->width, gimage->height, FALSE);
type = gimp_image_composite_type (gimage);
has_alpha = (type == RGBA_GIMAGE ||
type == GRAYA_GIMAGE ||
type == INDEXEDA_GIMAGE);
}
else
{
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
0, 0,
gimp_drawable_width (drawable),
gimp_drawable_height (drawable),
FALSE);
has_alpha = gimp_drawable_has_alpha (drawable);
}
indexed = gimp_drawable_is_indexed (drawable);
bytes = gimp_drawable_bytes (drawable);
if (indexed)
{
bytes = has_alpha ? 4 : 3;
}
mask = channel_new_mask (gimage, srcPR.w, srcPR.h);
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE(mask)),
0, 0,
gimp_drawable_width (GIMP_DRAWABLE(mask)),
gimp_drawable_height (GIMP_DRAWABLE(mask)),
TRUE);
tile = tile_manager_get_tile (srcPR.tiles, x, y, TRUE, FALSE);
if (tile)
{
start = tile_data_pointer (tile, x%TILE_WIDTH, y%TILE_HEIGHT);
find_contiguous_region_helper (&maskPR, &srcPR, has_alpha, antialias,
threshold, bytes, x, y, start);
tile_release (tile, FALSE);
}
return mask;
}
void
fuzzy_select (GImage *gimage,
GimpDrawable *drawable,
gint op,
gboolean feather,
gdouble feather_radius)
{
gint off_x, off_y;
/* if applicable, replace the current selection */
if (op == CHANNEL_OP_REPLACE)
gimage_mask_clear (gimage);
else
gimage_mask_undo (gimage);
if (drawable) /* NULL if sample_merged is active */
gimp_drawable_offsets (drawable, &off_x, &off_y);
else
off_x = off_y = 0;
if (feather)
channel_feather (fuzzy_mask, gimp_image_get_mask (gimage),
feather_radius,
feather_radius,
op, off_x, off_y);
else
channel_combine_mask (gimp_image_get_mask (gimage),
fuzzy_mask, op, off_x, off_y);
/* free the fuzzy region struct */
channel_delete (fuzzy_mask);
fuzzy_mask = NULL;
}
/* fuzzy select action functions */
static void
fuzzy_select_button_press (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
FuzzySelect *fuzzy_sel;
fuzzy_sel = (FuzzySelect *) tool->private;
fuzzy_sel->x = bevent->x;
fuzzy_sel->y = bevent->y;
fuzzy_sel->first_x = fuzzy_sel->x;
fuzzy_sel->first_y = fuzzy_sel->y;
fuzzy_sel->first_threshold = fuzzy_options->threshold;
gdk_pointer_grab (gdisp->canvas->window, FALSE,
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK,
NULL, NULL, bevent->time);
tool->state = ACTIVE;
tool->gdisp = gdisp;
if (fuzzy_sel->op == SELECTION_MOVE_MASK)
{
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE);
return;
}
else if (fuzzy_sel->op == SELECTION_MOVE)
{
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
return;
}
/* calculate the region boundary */
segs = fuzzy_select_calculate (tool, gdisp, &num_segs);
draw_core_start (fuzzy_sel->core,
gdisp->canvas->window,
tool);
}
static void
fuzzy_select_button_release (Tool *tool,
GdkEventButton *bevent,
GDisplay *gdisp)
{
FuzzySelect *fuzzy_sel;
GimpDrawable *drawable;
fuzzy_sel = (FuzzySelect *) tool->private;
gdk_pointer_ungrab (bevent->time);
gdk_flush ();
draw_core_stop (fuzzy_sel->core, tool);
tool->state = INACTIVE;
/* First take care of the case where the user "cancels" the action */
if (! (bevent->state & GDK_BUTTON3_MASK))
{
drawable = (fuzzy_options->sample_merged ?
NULL : gimp_image_active_drawable (gdisp->gimage));
fuzzy_select (gdisp->gimage, drawable, fuzzy_sel->op,
fuzzy_options->feather,
fuzzy_options->feather_radius);
gdisplays_flush ();
}
/* If the segment array is allocated, free it */
if (segs)
g_free (segs);
segs = NULL;
}
static void
fuzzy_select_motion (Tool *tool,
GdkEventMotion *mevent,
GDisplay *gdisp)
{
FuzzySelect *fuzzy_sel;
GdkSegment *new_segs;
gint num_new_segs;
gint diff_x, diff_y;
gdouble diff;
static guint last_time = 0;
fuzzy_sel = (FuzzySelect *) tool->private;
/* needed for immediate cursor update on modifier event */
fuzzy_sel->current_x = mevent->x;
fuzzy_sel->current_y = mevent->y;
if (tool->state != ACTIVE)
return;
/* don't let the events come in too fast, ignore below a delay of 100 ms */
if (ABS (mevent->time - last_time) < 100)
return;
last_time = mevent->time;
diff_x = mevent->x - fuzzy_sel->first_x;
diff_y = mevent->y - fuzzy_sel->first_y;
diff = ((ABS (diff_x) > ABS (diff_y)) ? diff_x : diff_y) / 2.0;
gtk_adjustment_set_value (GTK_ADJUSTMENT (fuzzy_options->threshold_w),
fuzzy_sel->first_threshold + diff);
/* calculate the new fuzzy boundary */
new_segs = fuzzy_select_calculate (tool, gdisp, &num_new_segs);
/* stop the current boundary */
draw_core_pause (fuzzy_sel->core, tool);
/* make sure the XSegment array is freed before we assign the new one */
if (segs)
g_free (segs);
segs = new_segs;
num_segs = num_new_segs;
/* start the new boundary */
draw_core_resume (fuzzy_sel->core, tool);
}
static GdkSegment *
fuzzy_select_calculate (Tool *tool,
GDisplay *gdisp,
gint *nsegs)
{
PixelRegion maskPR;
FuzzySelect *fuzzy_sel;
Channel *new;
GdkSegment *segs;
BoundSeg *bsegs;
GimpDrawable *drawable;
gint i;
gint x, y;
gboolean use_offsets;
fuzzy_sel = (FuzzySelect *) tool->private;
drawable = gimp_image_active_drawable (gdisp->gimage);
gimp_add_busy_cursors ();
use_offsets = fuzzy_options->sample_merged ? FALSE : TRUE;
gdisplay_untransform_coords (gdisp, fuzzy_sel->x,
fuzzy_sel->y, &x, &y, FALSE, use_offsets);
new = find_contiguous_region (gdisp->gimage, drawable,
fuzzy_options->antialias,
fuzzy_options->threshold, x, y,
fuzzy_options->sample_merged);
if (fuzzy_mask)
gtk_object_unref (GTK_OBJECT (fuzzy_mask));
fuzzy_mask = new;
gtk_object_ref (GTK_OBJECT (fuzzy_mask));
gtk_object_sink (GTK_OBJECT (fuzzy_mask));
/* calculate and allocate a new XSegment array which represents the boundary
* of the color-contiguous region
*/
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (fuzzy_mask)),
0, 0,
gimp_drawable_width (GIMP_DRAWABLE (fuzzy_mask)),
gimp_drawable_height (GIMP_DRAWABLE (fuzzy_mask)),
FALSE);
bsegs = find_mask_boundary (&maskPR, nsegs, WithinBounds,
0, 0,
gimp_drawable_width (GIMP_DRAWABLE (fuzzy_mask)),
gimp_drawable_height (GIMP_DRAWABLE (fuzzy_mask)));
segs = g_new (GdkSegment, *nsegs);
for (i = 0; i < *nsegs; i++)
{
gdisplay_transform_coords (gdisp, bsegs[i].x1, bsegs[i].y1, &x, &y, use_offsets);
segs[i].x1 = x; segs[i].y1 = y;
gdisplay_transform_coords (gdisp, bsegs[i].x2, bsegs[i].y2, &x, &y, use_offsets);
segs[i].x2 = x; segs[i].y2 = y;
}
/* free boundary segments */
g_free (bsegs);
gimp_remove_busy_cursors (NULL);
return segs;
}
static void
fuzzy_select_draw (Tool *tool)
{
FuzzySelect *fuzzy_sel;
fuzzy_sel = (FuzzySelect *) tool->private;
if (segs)
gdk_draw_segments (fuzzy_sel->core->win, fuzzy_sel->core->gc, segs, num_segs);
}
static void
fuzzy_select_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
FuzzySelect *fuzzy_sel;
fuzzy_sel = (FuzzySelect *) tool->private;
switch (action)
{
case PAUSE :
draw_core_pause (fuzzy_sel->core, tool);
break;
case RESUME :
draw_core_resume (fuzzy_sel->core, tool);
break;
case HALT :
draw_core_stop (fuzzy_sel->core, tool);
break;
default:
break;
}
}
static void
fuzzy_select_options_reset (void)
{
selection_options_reset (fuzzy_options);
}
Tool *
tools_new_fuzzy_select (void)
{
Tool *tool;
FuzzySelect *private;
/* The tool options */
if (! fuzzy_options)
{
fuzzy_options = selection_options_new (FUZZY_SELECT,
fuzzy_select_options_reset);
tools_register (FUZZY_SELECT, (ToolOptions *) fuzzy_options);
}
tool = tools_new_tool (FUZZY_SELECT);
private = g_new0 (FuzzySelect, 1);
private->core = draw_core_new (fuzzy_select_draw);
tool->scroll_lock = TRUE; /* Disallow scrolling */
tool->private = (void *) private;
tool->button_press_func = fuzzy_select_button_press;
tool->button_release_func = fuzzy_select_button_release;
tool->motion_func = fuzzy_select_motion;
tool->modifier_key_func = rect_select_modifier_update;
tool->cursor_update_func = rect_select_cursor_update;
tool->oper_update_func = rect_select_oper_update;
tool->control_func = fuzzy_select_control;
return tool;
}
void
tools_free_fuzzy_select (Tool *tool)
{
FuzzySelect *fuzzy_sel;
fuzzy_sel = (FuzzySelect *) tool->private;
draw_core_free (fuzzy_sel->core);
g_free (fuzzy_sel);
}

View File

@ -1,43 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __FUZZY_SELECT_H__
#define __FUZZY_SELECT_H__
Channel * find_contiguous_region (GimpImage *gimage,
GimpDrawable *drawable,
gboolean antialias,
gint threshold,
gint x,
gint y,
gboolean sample_merged);
void fuzzy_select (GimpImage *gimage,
GimpDrawable *drawable,
gint op,
gboolean feather,
gdouble feather_radius);
Tool * tools_new_fuzzy_select (void);
void tools_free_fuzzy_select (Tool *tool);
extern Channel *fuzzy_mask;
#endif /* __FUZZY_SELECT_H__ */

View File

@ -51,7 +51,6 @@
#include "scale.h"
#include "scroll.h"
#include "selection.h"
#include "tools.h"
#include "undo.h"
@ -59,7 +58,8 @@
#include "gdisplay_color.h"
#endif /* DISPLAY_FILTERS */
#include "bezier_selectP.h"
#include "tools/bezier_selectP.h"
#include "tools/tools.h"
#include "libgimp/gimpmath.h"

View File

@ -34,9 +34,10 @@
#include "gdisplay.h"
#include "paint_funcs.h"
#include "palette_import.h"
#include "tools.h"
#include "undo.h"
#include "tools/tools.h"
/* gimage.c: Junk (ugly dependencies) from gimpimage.c on its way
* to proper places. That is, the handlers should be moved to

View File

@ -31,14 +31,16 @@
#include "gimage_mask.h"
#include "gimprc.h"
#include "layer.h"
#include "paint_core.h"
#include "paint_funcs.h"
#include "paint_options.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tile_manager_pvt.h"
#include "undo.h"
#include "tools/paint_core.h"
#include "tools/paint_options.h"
#include "tools/tools.h"
#include "pdb/procedural_db.h"
#include "libgimp/gimpintl.h"

View File

@ -50,9 +50,11 @@
#include "gimprc.h"
#include "patterns.h"
#include "pattern_header.h"
#include "paint_core.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpintl.h"

View File

@ -33,11 +33,13 @@
#include "appenv.h"
#include "gimpbrushgenerated.h"
#include "paint_core.h"
#include "gimprc.h"
#include "gimpbrush.h"
#include "temp_buf.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"

View File

@ -48,9 +48,11 @@
#include "patterns.h"
#include "gimpbrush.h"
#include "gimpbrushpipe.h"
#include "paint_core.h"
#include "gimprc.h"
/* this needs to go away */
#include "tools/paint_core.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpparasiteio.h"

View File

@ -38,7 +38,8 @@
#include "layer.h"
#include "patterns.h"
#include "temp_buf.h"
#include "tools.h"
#include "tools/tools.h"
#include "libgimp/gimplimits.h"
#include "libgimp/gimpcolorarea.h"

View File

@ -94,30 +94,31 @@
#include "apptypes.h"
#include "appenv.h"
#include "brightness_contrast.h"
#include "color_balance.h"
#include "convert.h"
#include "cursorutil.h"
#include "curves.h"
#include "drawable.h"
#include "floating_sel.h"
#include "fsdither.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "hue_saturation.h"
#include "layer.h"
#include "levels.h"
#include "undo.h"
#include "palette.h"
#include "gimppalette.h"
#include "palette_select.h"
#include "pixel_region.h"
#include "posterize.h"
#include "threshold.h"
#include "tile_manager.h"
#include "tile_manager_pvt.h" /* ick ick ick. */
#include "tools/brightness_contrast.h"
#include "tools/color_balance.h"
#include "tools/curves.h"
#include "tools/hue_saturation.h"
#include "tools/levels.h"
#include "tools/posterize.h"
#include "tools/threshold.h"
#include "libgimp/gimpcolorspace.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -50,7 +50,8 @@
#include "plug_in.h"
#include "gimage.h"
#include "session.h"
#include "tools.h"
#include "tools/tools.h"
#include "libgimp/gimpenv.h"
#include "libgimp/gimputils.h"

View File

@ -38,9 +38,10 @@
#include "paint_funcs.h"
#include "pixel_region.h"
#include "tile_manager.h"
#include "tools.h"
#include "undo.h"
#include "tools/tools.h"
#include "libgimp/gimpintl.h"
#include "tile_manager_pvt.h"

View File

@ -37,10 +37,11 @@
#include "gimplist.h"
#include "gimprc.h"
#include "gimpui.h"
#include "paint_options.h"
#include "session.h"
#include "temp_buf.h"
#include "tools/paint_options.h"
#include "pdb/procedural_db.h"
#include "libgimp/gimphelpui.h"

View File

@ -68,13 +68,14 @@
#include "scale.h"
#include "selection.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
#ifdef DISPLAY_FILTERS
#include "gdisplay_color_ui.h"
#endif /* DISPLAY_FILTERS */
#include "tools/tools.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -39,7 +39,8 @@
#include "gradient_header.h"
#include "patterns.h"
#include "session.h"
#include "tools.h"
#include "tools/tools.h"
#include "libgimp/gimpenv.h"
#include "libgimp/gimpcolorarea.h"

View File

@ -68,13 +68,14 @@
#include "scale.h"
#include "selection.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
#ifdef DISPLAY_FILTERS
#include "gdisplay_color_ui.h"
#endif /* DISPLAY_FILTERS */
#include "tools/tools.h"
#include "libgimp/gimphelpui.h"
#include "libgimp/gimpmath.h"

View File

@ -34,7 +34,8 @@
#include "info_dialog.h"
#include "info_window.h"
#include "scroll.h"
#include "tools.h"
#include "tools/tools.h"
#include "pdb/procedural_db.h"

View File

@ -39,7 +39,8 @@
#include "gradient_header.h"
#include "patterns.h"
#include "session.h"
#include "tools.h"
#include "tools/tools.h"
#include "libgimp/gimpenv.h"
#include "libgimp/gimpcolorarea.h"

View File

@ -31,6 +31,7 @@
#include "commands.h"
#include "dialog_handler.h"
#include "fileops.h"
#include "gdisplay.h"
#include "gimphelp.h"
#include "gimprc.h"
#include "gimpui.h"
@ -41,8 +42,8 @@
#include "paint_funcs.h"
#include "preferences_dialog.h"
#include "scale.h"
#include "tools.h"
#include "gdisplay.h"
#include "tools/tools.h"
#include "libgimp/gimpenv.h"

View File

@ -45,8 +45,6 @@
#include "lc_dialogP.h"
#include "menus.h"
#include "ops_buttons.h"
#include "bezier_select.h"
#include "bezier_selectP.h"
#include "path.h"
#include "pathP.h"
#include "path_transform.h"
@ -55,6 +53,9 @@
#include "plug_in.h"
#include "undo.h"
#include "tools/bezier_select.h"
#include "tools/bezier_selectP.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"

View File

@ -1,470 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "drawable.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimphistogram.h"
#include "gimpui.h"
#include "histogram_tool.h"
#include "histogramwidget.h"
#include "pixel_region.h"
#include "tool_options.h"
#include "tools.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"
#define TEXT_WIDTH 45
#define GRADIENT_HEIGHT 15
/* the histogram structures */
typedef struct _HistogramTool HistogramTool;
struct _HistogramTool
{
gint x, y; /* coords for last mouse click */
};
/* histogram_tool action functions */
static void histogram_tool_control (Tool *tool,
ToolAction tool_action,
GDisplay *gdisp);
static HistogramToolDialog * histogram_tool_dialog_new (void);
static void histogram_tool_close_callback (GtkWidget *widget,
gpointer data);
static void histogram_tool_channel_callback (GtkWidget *widget,
gpointer data);
static void histogram_tool_gradient_draw (GtkWidget *gdisp,
gint channel);
static void histogram_tool_dialog_update (HistogramToolDialog *htd,
gint start,
gint end);
/* the histogram tool options */
static ToolOptions * histogram_tool_options = NULL;
/* the histogram tool dialog */
static HistogramToolDialog * histogram_tool_dialog = NULL;
/* histogram_tool machinery */
void
histogram_tool_histogram_range (HistogramWidget *widget,
gint start,
gint end,
gpointer data)
{
HistogramToolDialog *htd;
gdouble pixels;
gdouble count;
htd = (HistogramToolDialog *) data;
if (htd == NULL || htd->hist == NULL ||
gimp_histogram_nchannels (htd->hist) <= 0)
return;
pixels = gimp_histogram_get_count (htd->hist, 0, 255);
count = gimp_histogram_get_count (htd->hist, start, end);
htd->mean = gimp_histogram_get_mean (htd->hist, htd->channel,
start, end);
htd->std_dev = gimp_histogram_get_std_dev (htd->hist, htd->channel,
start, end);
htd->median = gimp_histogram_get_median (htd->hist, htd->channel,
start, end);
htd->pixels = pixels;
htd->count = count;
htd->percentile = count / pixels;
if (htd->shell)
histogram_tool_dialog_update (htd, start, end);
}
static void
histogram_tool_dialog_update (HistogramToolDialog *htd,
gint start,
gint end)
{
gchar text[12];
/* mean */
g_snprintf (text, sizeof (text), "%3.1f", htd->mean);
gtk_label_set_text (GTK_LABEL (htd->info_labels[0]), text);
/* std dev */
g_snprintf (text, sizeof (text), "%3.1f", htd->std_dev);
gtk_label_set_text (GTK_LABEL (htd->info_labels[1]), text);
/* median */
g_snprintf (text, sizeof (text), "%3.1f", htd->median);
gtk_label_set_text (GTK_LABEL (htd->info_labels[2]), text);
/* pixels */
g_snprintf (text, sizeof (text), "%8.1f", htd->pixels);
gtk_label_set_text (GTK_LABEL (htd->info_labels[3]), text);
/* intensity */
if (start == end)
g_snprintf (text, sizeof (text), "%d", start);
else
g_snprintf (text, sizeof (text), "%d..%d", start, end);
gtk_label_set_text (GTK_LABEL (htd->info_labels[4]), text);
/* count */
g_snprintf (text, sizeof (text), "%8.1f", htd->count);
gtk_label_set_text (GTK_LABEL (htd->info_labels[5]), text);
/* percentile */
g_snprintf (text, sizeof (text), "%2.2f", htd->percentile * 100);
gtk_label_set_text (GTK_LABEL (htd->info_labels[6]), text);
}
/* histogram_tool action functions */
static void
histogram_tool_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
switch (action)
{
case PAUSE:
break;
case RESUME:
break;
case HALT:
if (histogram_tool_dialog)
histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog);
break;
default:
break;
}
}
Tool *
tools_new_histogram_tool (void)
{
Tool *tool;
HistogramTool *private;
/* The tool options */
if (! histogram_tool_options)
{
histogram_tool_options = tool_options_new (_("Histogram"));
tools_register (HISTOGRAM, histogram_tool_options);
}
tool = tools_new_tool (HISTOGRAM);
private = g_new0 (HistogramTool, 1);
tool->scroll_lock = TRUE; /* Disallow scrolling */
tool->preserve = FALSE; /* Don't preserve on drawable change */
tool->private = (void *) private;
tool->control_func = histogram_tool_control;
return tool;
}
void
tools_free_histogram_tool (Tool *tool)
{
HistogramTool * hist;
hist = (HistogramTool *) tool->private;
/* Close the histogram dialog */
if (histogram_tool_dialog)
histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog);
g_free (hist);
}
void
histogram_tool_initialize (GDisplay *gdisp)
{
PixelRegion PR;
if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage)))
{
g_message (_("Histogram does not operate on indexed drawables."));
return;
}
/* The histogram_tool dialog */
if (!histogram_tool_dialog)
histogram_tool_dialog = histogram_tool_dialog_new ();
else if (!GTK_WIDGET_VISIBLE (histogram_tool_dialog->shell))
gtk_widget_show (histogram_tool_dialog->shell);
histogram_tool_dialog->drawable = gimp_image_active_drawable (gdisp->gimage);
histogram_tool_dialog->color = gimp_drawable_is_rgb (histogram_tool_dialog->drawable);
/* hide or show the channel menu based on image type */
if (histogram_tool_dialog->color)
gtk_widget_show (histogram_tool_dialog->channel_menu);
else
gtk_widget_hide (histogram_tool_dialog->channel_menu);
/* calculate the histogram */
pixel_region_init (&PR, gimp_drawable_data (histogram_tool_dialog->drawable),
0, 0,
gimp_drawable_width (histogram_tool_dialog->drawable),
gimp_drawable_height (histogram_tool_dialog->drawable),
FALSE);
gimp_histogram_calculate (histogram_tool_dialog->hist, &PR, NULL);
histogram_widget_update (histogram_tool_dialog->histogram,
histogram_tool_dialog->hist);
histogram_widget_range (histogram_tool_dialog->histogram, 0, 255);
}
/***************************/
/* Histogram Tool dialog */
/***************************/
static HistogramToolDialog *
histogram_tool_dialog_new (void)
{
HistogramToolDialog *htd;
GtkWidget *main_vbox;
GtkWidget *hbox;
GtkWidget *vbox;
GtkWidget *grad_hbox;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *label;
GtkWidget *option_menu;
gint i;
gint x, y;
static gchar * histogram_info_names[] =
{
N_("Mean:"),
N_("Std Dev:"),
N_("Median:"),
N_("Pixels:"),
N_("Intensity:"),
N_("Count:"),
N_("Percentile:")
};
htd = g_new (HistogramToolDialog, 1);
htd->channel = GIMP_HISTOGRAM_VALUE;
htd->hist = gimp_histogram_new ();
/* The shell and main vbox */
htd->shell = gimp_dialog_new (_("Histogram"), "histogram",
tools_help_func,
tool_info[HISTOGRAM].private_tip,
GTK_WIN_POS_NONE,
FALSE, TRUE, FALSE,
_("Close"), histogram_tool_close_callback,
htd, NULL, NULL, TRUE, TRUE,
NULL);
main_vbox = gtk_vbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (htd->shell)->vbox), main_vbox);
hbox = gtk_hbox_new (TRUE, 0);
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
vbox = gtk_vbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
/* The option menu for selecting channels */
htd->channel_menu = gtk_hbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (vbox), htd->channel_menu, FALSE, FALSE, 0);
label = gtk_label_new (_("Information on Channel:"));
gtk_box_pack_start (GTK_BOX (htd->channel_menu), label, FALSE, FALSE, 0);
gtk_widget_show (label);
option_menu = gimp_option_menu_new2
(FALSE, histogram_tool_channel_callback,
htd, (gpointer) htd->channel,
_("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, NULL,
_("Red"), (gpointer) GIMP_HISTOGRAM_RED, NULL,
_("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, NULL,
_("Blue"), (gpointer) GIMP_HISTOGRAM_BLUE, NULL,
NULL);
gtk_box_pack_start (GTK_BOX (htd->channel_menu), option_menu, FALSE, FALSE, 0);
gtk_widget_show (option_menu);
gtk_widget_show (htd->channel_menu);
/* The histogram tool histogram */
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
htd->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT);
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->histogram));
gtk_signal_connect (GTK_OBJECT (htd->histogram), "range_changed",
GTK_SIGNAL_FUNC (histogram_tool_histogram_range),
htd);
gtk_widget_show (GTK_WIDGET (htd->histogram));
gtk_widget_show (frame);
/* The gradient below the histogram */
grad_hbox = gtk_hbox_new (TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), grad_hbox, FALSE, FALSE, 0);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_box_pack_start (GTK_BOX (grad_hbox), frame, FALSE, FALSE, 0);
htd->gradient = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (htd->gradient),
HISTOGRAM_WIDTH, GRADIENT_HEIGHT);
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->gradient));
gtk_widget_show (htd->gradient);
gtk_widget_show (frame);
gtk_widget_show (grad_hbox);
histogram_tool_gradient_draw (htd->gradient, GIMP_HISTOGRAM_VALUE);
gtk_widget_show (vbox);
gtk_widget_show (hbox);
/* The table containing histogram information */
table = gtk_table_new (4, 4, TRUE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
/* the labels for histogram information */
for (i = 0; i < 7; i++)
{
y = (i % 4);
x = (i / 4) * 2;
label = gtk_label_new (gettext(histogram_info_names[i]));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, x, x + 1, y, y + 1,
GTK_FILL, GTK_FILL, 2, 2);
gtk_widget_show (label);
htd->info_labels[i] = gtk_label_new ("0");
gtk_misc_set_alignment (GTK_MISC (htd->info_labels[i]), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), htd->info_labels[i],
x + 1, x + 2, y, y + 1,
GTK_FILL, GTK_FILL, 2, 2);
gtk_widget_show (htd->info_labels[i]);
}
gtk_widget_show (table);
gtk_widget_show (main_vbox);
gtk_widget_show (htd->shell);
return htd;
}
static void
histogram_tool_close_callback (GtkWidget *widget,
gpointer data)
{
HistogramToolDialog *htd;
htd = (HistogramToolDialog *) data;
gimp_dialog_hide (htd->shell);
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
histogram_tool_channel_callback (GtkWidget *widget,
gpointer data)
{
HistogramToolDialog *htd;
htd = (HistogramToolDialog *) data;
gimp_menu_item_update (widget, &htd->channel);
histogram_widget_channel (htd->histogram, htd->channel);
histogram_tool_gradient_draw (htd->gradient, htd->channel);
}
static void
histogram_tool_gradient_draw (GtkWidget *gradient,
gint channel)
{
guchar buf[HISTOGRAM_WIDTH * 3];
guchar r, g, b;
gint i;
r = g = b = 0;
switch (channel)
{
case GIMP_HISTOGRAM_VALUE:
case GIMP_HISTOGRAM_ALPHA: r = g = b = 1;
break;
case GIMP_HISTOGRAM_RED: r = 1;
break;
case GIMP_HISTOGRAM_GREEN: g = 1;
break;
case GIMP_HISTOGRAM_BLUE: b = 1;
break;
default:
g_warning ("unknown channel type, can't happen\n");
break;
}
for (i = 0; i < HISTOGRAM_WIDTH; i++)
{
buf[3*i+0] = i*r;
buf[3*i+1] = i*g;
buf[3*i+2] = i*b;
}
for (i = 0; i < GRADIENT_HEIGHT; i++)
gtk_preview_draw_row (GTK_PREVIEW (gradient),
buf, 0, i, HISTOGRAM_WIDTH);
gtk_widget_queue_draw (gradient);
}

View File

@ -1,64 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __HISTOGRAM_TOOL_H__
#define __HISTOGRAM_TOOL_H__
#define HISTOGRAM_WIDTH 256
#define HISTOGRAM_HEIGHT 150
typedef struct _HistogramToolDialog HistogramToolDialog;
struct _HistogramToolDialog
{
GtkWidget *shell;
GtkWidget *info_labels[7];
GtkWidget *channel_menu;
HistogramWidget *histogram;
GimpHistogram *hist;
GtkWidget *gradient;
gdouble mean;
gdouble std_dev;
gdouble median;
gdouble pixels;
gdouble count;
gdouble percentile;
GimpDrawable *drawable;
ImageMap image_map;
gint channel;
gint color;
};
/* histogram_tool functions */
Tool * tools_new_histogram_tool (void);
void tools_free_histogram_tool (Tool *tool);
void histogram_tool_initialize (GDisplay *gdisp);
void histogram_tool_free (void);
void histogram_tool_histogram_range (HistogramWidget *hw,
gint start,
gint end,
gpointer data);
#endif /* __HISTOGRAM_TOOL_H__ */

View File

@ -1,854 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "apptypes.h"
#include "appenv.h"
#include "drawable.h"
#include "gimage_mask.h"
#include "gdisplay.h"
#include "gimpimage.h"
#include "gimpui.h"
#include "hue_saturation.h"
#include "image_map.h"
#include "pixel_region.h"
#include "tools.h"
#include "tool_options.h"
#include "libgimp/gimpcolorspace.h"
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"
#define HUE_PARTITION_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK
#define SLIDER_WIDTH 200
#define DA_WIDTH 40
#define DA_HEIGHT 20
#define HUE_PARTITION 0x0
#define HUE_SLIDER 0x1
#define LIGHTNESS_SLIDER 0x2
#define SATURATION_SLIDER 0x4
#define DRAW 0x40
#define ALL 0xFF
/* the hue-saturation structures */
typedef struct _HueSaturation HueSaturation;
struct _HueSaturation
{
gint x, y; /* coords for last mouse click */
};
/* hue saturation action functions */
static void hue_saturation_control (Tool *tool,
ToolAction tool_action,
GDisplay *gdisp);
static HueSaturationDialog * hue_saturation_dialog_new (void);
static void hue_saturation_update (HueSaturationDialog *hsd,
gint);
static void hue_saturation_preview (HueSaturationDialog *hsd);
static void hue_saturation_reset_callback (GtkWidget *,
gpointer);
static void hue_saturation_ok_callback (GtkWidget *,
gpointer);
static void hue_saturation_cancel_callback (GtkWidget *,
gpointer);
static void hue_saturation_partition_callback (GtkWidget *,
gpointer);
static void hue_saturation_preview_update (GtkWidget *,
gpointer);
static void hue_saturation_hue_adjustment_update (GtkAdjustment *,
gpointer);
static void hue_saturation_lightness_adjustment_update (GtkAdjustment *,
gpointer);
static void hue_saturation_saturation_adjustment_update (GtkAdjustment *,
gpointer);
static gint hue_saturation_hue_partition_events (GtkWidget *,
GdkEvent *,
HueSaturationDialog *hsd);
/* the hue-saturation tool options */
static ToolOptions *hue_saturation_options = NULL;
/* the hue-saturation tool dialog */
static HueSaturationDialog *hue_saturation_dialog = NULL;
/* Local variables */
static gint hue_transfer[6][256];
static gint lightness_transfer[6][256];
static gint saturation_transfer[6][256];
static gint default_colors[6][3] =
{
{ 255, 0, 0 },
{ 255, 255, 0 },
{ 0, 255, 0 },
{ 0, 255, 255 },
{ 0, 0, 255 },
{ 255, 0, 255 }
};
/* hue saturation machinery */
void
hue_saturation_calculate_transfers (HueSaturationDialog *hsd)
{
gint value;
gint hue;
gint i;
/* Calculate transfers */
for (hue = 0; hue < 6; hue++)
for (i = 0; i < 256; i++)
{
value = (hsd->hue[0] + hsd->hue[hue + 1]) * 255.0 / 360.0;
if ((i + value) < 0)
hue_transfer[hue][i] = 255 + (i + value);
else if ((i + value) > 255)
hue_transfer[hue][i] = i + value - 255;
else
hue_transfer[hue][i] = i + value;
/* Lightness */
value = (hsd->lightness[0] + hsd->lightness[hue + 1]) * 127.0 / 100.0;
value = CLAMP (value, -255, 255);
if (value < 0)
lightness_transfer[hue][i] = (unsigned char) ((i * (255 + value)) / 255);
else
lightness_transfer[hue][i] = (unsigned char) (i + ((255 - i) * value) / 255);
/* Saturation */
value = (hsd->saturation[0] + hsd->saturation[hue + 1]) * 255.0 / 100.0;
value = CLAMP (value, -255, 255);
/* This change affects the way saturation is computed. With the
old code (different code for value < 0), increasing the
saturation affected muted colors very much, and bright colors
less. With the new code, it affects muted colors and bright
colors more or less evenly. For enhancing the color in photos,
the new behavior is exactly what you want. It's hard for me
to imagine a case in which the old behavior is better.
*/
saturation_transfer[hue][i] = CLAMP ((i * (255 + value)) / 255, 0, 255);
}
}
void
hue_saturation (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
{
HueSaturationDialog *hsd;
unsigned char *src, *s;
unsigned char *dest, *d;
int alpha;
int w, h;
int r, g, b;
int hue;
hsd = (HueSaturationDialog *) user_data;
/* Set the transfer arrays (for speed) */
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
alpha = (srcPR->bytes == 4) ? TRUE : FALSE;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
r = s[RED_PIX];
g = s[GREEN_PIX];
b = s[BLUE_PIX];
gimp_rgb_to_hls_int (&r, &g, &b);
if (r < 43)
hue = 0;
else if (r < 85)
hue = 1;
else if (r < 128)
hue = 2;
else if (r < 171)
hue = 3;
else if (r < 213)
hue = 4;
else
hue = 5;
r = hue_transfer[hue][r];
g = lightness_transfer[hue][g];
b = saturation_transfer[hue][b];
gimp_hls_to_rgb_int (&r, &g, &b);
d[RED_PIX] = r;
d[GREEN_PIX] = g;
d[BLUE_PIX] = b;
if (alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
/* hue saturation action functions */
static void
hue_saturation_control (Tool *tool,
ToolAction action,
GDisplay *gdisp)
{
switch (action)
{
case PAUSE:
break;
case RESUME:
break;
case HALT:
hue_saturation_dialog_hide ();
break;
default:
break;
}
}
Tool *
tools_new_hue_saturation (void)
{
Tool * tool;
HueSaturation * private;
/* The tool options */
if (!hue_saturation_options)
{
hue_saturation_options = tool_options_new (_("Hue-Saturation"));
tools_register (HUE_SATURATION, hue_saturation_options);
}
tool = tools_new_tool (HUE_SATURATION);
private = g_new0 (HueSaturation, 1);
tool->scroll_lock = TRUE; /* Disallow scrolling */
tool->preserve = FALSE; /* Don't preserve on drawable change */
tool->private = (void *) private;
tool->control_func = hue_saturation_control;
return tool;
}
void
hue_saturation_dialog_hide (void)
{
if (hue_saturation_dialog)
hue_saturation_cancel_callback (NULL, (gpointer) hue_saturation_dialog);
}
void
tools_free_hue_saturation (Tool *tool)
{
HueSaturation * color_bal;
color_bal = (HueSaturation *) tool->private;
/* Close the hue saturation dialog */
hue_saturation_dialog_hide ();
g_free (color_bal);
}
void
hue_saturation_initialize (GDisplay *gdisp)
{
gint i;
if (! gimp_drawable_is_rgb (gimp_image_active_drawable (gdisp->gimage)))
{
g_message (_("Hue-Saturation operates only on RGB color drawables."));
return;
}
/* The "hue-saturation" dialog */
if (!hue_saturation_dialog)
hue_saturation_dialog = hue_saturation_dialog_new ();
else
if (!GTK_WIDGET_VISIBLE (hue_saturation_dialog->shell))
gtk_widget_show (hue_saturation_dialog->shell);
for (i = 0; i < 7; i++)
{
hue_saturation_dialog->hue[i] = 0.0;
hue_saturation_dialog->lightness[i] = 0.0;
hue_saturation_dialog->saturation[i] = 0.0;
}
hue_saturation_dialog->drawable = gimp_image_active_drawable (gdisp->gimage);
hue_saturation_dialog->image_map =
image_map_create (gdisp, hue_saturation_dialog->drawable);
hue_saturation_update (hue_saturation_dialog, ALL);
}
void
hue_saturation_free (void)
{
if (hue_saturation_dialog)
{
if (hue_saturation_dialog->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (hue_saturation_dialog->image_map);
active_tool->preserve = FALSE;
hue_saturation_dialog->image_map = NULL;
}
gtk_widget_destroy (hue_saturation_dialog->shell);
}
}
/***************************/
/* Hue-Saturation dialog */
/***************************/
static HueSaturationDialog *
hue_saturation_dialog_new (void)
{
HueSaturationDialog *hsd;
GtkWidget *main_vbox;
GtkWidget *main_hbox;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *table;
GtkWidget *label;
GtkWidget *slider;
GtkWidget *abox;
GtkWidget *spinbutton;
GtkWidget *toggle;
GtkWidget *radio_button;
GtkWidget *frame;
GtkObject *data;
GSList *group = NULL;
gint i;
gchar *hue_partition_names[] =
{
N_("Master"),
N_("R"),
N_("Y"),
N_("G"),
N_("C"),
N_("B"),
N_("M")
};
hsd = g_new (HueSaturationDialog, 1);
hsd->hue_partition = ALL_HUES;
hsd->preview = TRUE;
/* The shell and main vbox */
hsd->shell = gimp_dialog_new (_("Hue-Saturation"), "hue_saturation",
tools_help_func, NULL,
GTK_WIN_POS_NONE,
FALSE, TRUE, FALSE,
_("OK"), hue_saturation_ok_callback,
hsd, NULL, NULL, TRUE, FALSE,
_("Reset"), hue_saturation_reset_callback,
hsd, NULL, NULL, FALSE, FALSE,
_("Cancel"), hue_saturation_cancel_callback,
hsd, NULL, NULL, FALSE, TRUE,
NULL);
main_vbox = gtk_vbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (hsd->shell)->vbox), main_vbox);
/* The main hbox containing hue partitions and sliders */
main_hbox = gtk_hbox_new (FALSE, 12);
gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, FALSE, FALSE, 0);
/* The table containing hue partitions */
table = gtk_table_new (7, 2, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (main_hbox), table, FALSE, FALSE, 0);
/* the radio buttons for hue partitions */
for (i = 0; i < 7; i++)
{
radio_button = gtk_radio_button_new_with_label (group, gettext (hue_partition_names[i]));
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
gtk_object_set_data (GTK_OBJECT (radio_button), "hue_partition",
(gpointer) i);
if (!i)
{
gtk_table_attach (GTK_TABLE (table), radio_button, 0, 2, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
}
else
{
gtk_table_attach (GTK_TABLE (table), radio_button, 0, 1, i, i + 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_table_attach (GTK_TABLE (table), frame, 1, 2, i, i + 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
hsd->hue_partition_da[i - 1] = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (hsd->hue_partition_da[i - 1]),
DA_WIDTH, DA_HEIGHT);
gtk_widget_set_events (hsd->hue_partition_da[i - 1],
HUE_PARTITION_MASK);
gtk_signal_connect (GTK_OBJECT (hsd->hue_partition_da[i - 1]), "event",
GTK_SIGNAL_FUNC (hue_saturation_hue_partition_events),
hsd);
gtk_container_add (GTK_CONTAINER (frame), hsd->hue_partition_da[i - 1]);
gtk_widget_show (hsd->hue_partition_da[i - 1]);
gtk_widget_show (frame);
}
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
GTK_SIGNAL_FUNC (hue_saturation_partition_callback),
hsd);
gtk_widget_show (radio_button);
}
gtk_widget_show (table);
/* The vbox for the table and preview toggle */
vbox = gtk_vbox_new (FALSE, 4);
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
label = gtk_label_new (_("Hue / Lightness / Saturation Adjustments"));
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
/* The table containing sliders */
table = gtk_table_new (3, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
/* Create the hue scale widget */
label = gtk_label_new (_("Hue:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
data = gtk_adjustment_new (0, -180, 180.0, 1.0, 1.0, 0.0);
hsd->hue_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (hsd->hue_data);
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 0, 1,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
abox = gtk_vbox_new (FALSE, 0);
spinbutton = gtk_spin_button_new (hsd->hue_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 74, -1);
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (hsd->hue_data), "value_changed",
GTK_SIGNAL_FUNC (hue_saturation_hue_adjustment_update),
hsd);
gtk_widget_show (label);
gtk_widget_show (slider);
gtk_widget_show (spinbutton);
gtk_widget_show (abox);
/* Create the lightness scale widget */
label = gtk_label_new (_("Lightness:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 1.0, 0.0);
hsd->lightness_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (hsd->lightness_data);
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 1, 2,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
abox = gtk_vbox_new (FALSE, 0);
spinbutton = gtk_spin_button_new (hsd->lightness_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (hsd->lightness_data), "value_changed",
GTK_SIGNAL_FUNC (hue_saturation_lightness_adjustment_update),
hsd);
gtk_widget_show (label);
gtk_widget_show (slider);
gtk_widget_show (spinbutton);
gtk_widget_show (abox);
/* Create the saturation scale widget */
label = gtk_label_new (_("Saturation:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 1.0, 0.0);
hsd->saturation_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (hsd->saturation_data);
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 2, 3,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
abox = gtk_vbox_new (FALSE, 0);
spinbutton = gtk_spin_button_new (hsd->saturation_data, 1.0, 0);
gtk_widget_set_usize (spinbutton, 75, -1);
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (hsd->saturation_data), "value_changed",
GTK_SIGNAL_FUNC (hue_saturation_saturation_adjustment_update),
hsd);
gtk_widget_show (label);
gtk_widget_show (slider);
gtk_widget_show (spinbutton);
gtk_widget_show (abox);
gtk_widget_show (table);
/* Horizontal box for preview toggle button */
hbox = gtk_hbox_new (FALSE, 4);
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
/* The preview toggle */
toggle = gtk_check_button_new_with_label (_("Preview"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), hsd->preview);
gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
GTK_SIGNAL_FUNC (hue_saturation_preview_update),
hsd);
gtk_widget_show (toggle);
gtk_widget_show (hbox);
gtk_widget_show (vbox);
gtk_widget_show (main_hbox);
gtk_widget_show (main_vbox);
gtk_widget_show (hsd->shell);
return hsd;
}
static void
hue_saturation_update (HueSaturationDialog *hsd,
gint update)
{
gint i, j, b;
gint rgb[3];
guchar buf[DA_WIDTH * 3];
if (update & HUE_SLIDER)
{
gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->hue_data),
hsd->hue[hsd->hue_partition]);
}
if (update & LIGHTNESS_SLIDER)
{
gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->lightness_data),
hsd->lightness[hsd->hue_partition]);
}
if (update & SATURATION_SLIDER)
{
gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->saturation_data),
hsd->saturation[hsd->hue_partition]);
}
hue_saturation_calculate_transfers (hsd);
for (i = 0; i < 6; i++)
{
rgb[RED_PIX] = default_colors[i][RED_PIX];
rgb[GREEN_PIX] = default_colors[i][GREEN_PIX];
rgb[BLUE_PIX] = default_colors[i][BLUE_PIX];
gimp_rgb_to_hls_int (rgb, rgb + 1, rgb + 2);
rgb[RED_PIX] = hue_transfer[i][rgb[RED_PIX]];
rgb[GREEN_PIX] = lightness_transfer[i][rgb[GREEN_PIX]];
rgb[BLUE_PIX] = saturation_transfer[i][rgb[BLUE_PIX]];
gimp_hls_to_rgb_int (rgb, rgb + 1, rgb + 2);
for (j = 0; j < DA_WIDTH; j++)
for (b = 0; b < 3; b++)
buf[j * 3 + b] = (guchar) rgb[b];
for (j = 0; j < DA_HEIGHT; j++)
gtk_preview_draw_row (GTK_PREVIEW (hsd->hue_partition_da[i]),
buf, 0, j, DA_WIDTH);
if (update & DRAW)
gtk_widget_draw (hsd->hue_partition_da[i], NULL);
}
}
static void
hue_saturation_preview (HueSaturationDialog *hsd)
{
if (!hsd->image_map)
{
g_warning ("hue_saturation_preview(): No image map");
return;
}
active_tool->preserve = TRUE;
image_map_apply (hsd->image_map, hue_saturation, (void *) hsd);
active_tool->preserve = FALSE;
}
static void
hue_saturation_reset_callback (GtkWidget *widget,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
hsd->hue[hsd->hue_partition] = 0.0;
hsd->lightness[hsd->hue_partition] = 0.0;
hsd->saturation[hsd->hue_partition] = 0.0;
hue_saturation_update (hsd, ALL);
if (hsd->preview)
hue_saturation_preview (hsd);
}
static void
hue_saturation_ok_callback (GtkWidget *widget,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
gimp_dialog_hide (hsd->shell);
active_tool->preserve = TRUE;
if (!hsd->preview)
image_map_apply (hsd->image_map, hue_saturation, (gpointer) hsd);
if (hsd->image_map)
image_map_commit (hsd->image_map);
active_tool->preserve = FALSE;
hsd->image_map = NULL;
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
hue_saturation_cancel_callback (GtkWidget *widget,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
gimp_dialog_hide (hsd->shell);
if (hsd->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (hsd->image_map);
active_tool->preserve = FALSE;
gdisplays_flush ();
hsd->image_map = NULL;
}
active_tool->gdisp = NULL;
active_tool->drawable = NULL;
}
static void
hue_saturation_partition_callback (GtkWidget *widget,
gpointer data)
{
HueSaturationDialog *hsd;
HueRange partition;
hsd = (HueSaturationDialog *) data;
partition = (HueRange) gtk_object_get_data (GTK_OBJECT (widget),
"hue_partition");
hsd->hue_partition = partition;
hue_saturation_update (hsd, ALL);
}
static void
hue_saturation_preview_update (GtkWidget *widget,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
{
hsd->preview = TRUE;
hue_saturation_preview (hsd);
}
else
{
hsd->preview = FALSE;
if (hsd->image_map)
{
active_tool->preserve = TRUE;
image_map_clear (hsd->image_map);
active_tool->preserve = FALSE;
gdisplays_flush ();
}
}
}
static void
hue_saturation_hue_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
if (hsd->hue[hsd->hue_partition] != adjustment->value)
{
hsd->hue[hsd->hue_partition] = adjustment->value;
hue_saturation_update (hsd, DRAW);
if (hsd->preview)
hue_saturation_preview (hsd);
}
}
static void
hue_saturation_lightness_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
if (hsd->lightness[hsd->hue_partition] != adjustment->value)
{
hsd->lightness[hsd->hue_partition] = adjustment->value;
hue_saturation_update (hsd, DRAW);
if (hsd->preview)
hue_saturation_preview (hsd);
}
}
static void
hue_saturation_saturation_adjustment_update (GtkAdjustment *adjustment,
gpointer data)
{
HueSaturationDialog *hsd;
hsd = (HueSaturationDialog *) data;
if (hsd->saturation[hsd->hue_partition] != adjustment->value)
{
hsd->saturation[hsd->hue_partition] = adjustment->value;
hue_saturation_update (hsd, DRAW);
if (hsd->preview)
hue_saturation_preview (hsd);
}
}
static gint
hue_saturation_hue_partition_events (GtkWidget *widget,
GdkEvent *event,
HueSaturationDialog *hsd)
{
switch (event->type)
{
case GDK_EXPOSE:
hue_saturation_update (hsd, HUE_PARTITION);
break;
default:
break;
}
return FALSE;
}

View File

@ -1,71 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __HUE_SATURATION_H__
#define __HUE_SATURATION_H__
typedef enum
{
ALL_HUES,
RED_HUES,
YELLOW_HUES,
GREEN_HUES,
CYAN_HUES,
BLUE_HUES,
MAGENTA_HUES
} HueRange;
typedef struct _HueSaturationDialog HueSaturationDialog;
struct _HueSaturationDialog
{
GtkWidget *shell;
GtkWidget *hue_partition_da[6];
GtkAdjustment *hue_data;
GtkAdjustment *lightness_data;
GtkAdjustment *saturation_data;
GimpDrawable *drawable;
ImageMap image_map;
gdouble hue[7];
gdouble lightness[7];
gdouble saturation[7];
HueRange hue_partition;
gboolean preview;
};
Tool * tools_new_hue_saturation (void);
void tools_free_hue_saturation (Tool *tool);
void hue_saturation_initialize (GDisplay *gdisp);
void hue_saturation_free (void);
void hue_saturation_dialog_hide (void);
void hue_saturation (PixelRegion *srcPR,
PixelRegion *destPR,
void *data);
void hue_saturation_calculate_transfers (HueSaturationDialog *hsd);
#endif /* __HUE_SATURATION_H__ */

View File

@ -34,7 +34,8 @@
#include "info_dialog.h"
#include "info_window.h"
#include "scroll.h"
#include "tools.h"
#include "tools/tools.h"
#include "pdb/procedural_db.h"

Some files were not shown because too many files have changed in this diff Show More