From 80a8d5a75f936d7b7a6ee48fba71c812f261d13b Mon Sep 17 00:00:00 2001 From: Nate Summers Date: Tue, 27 Feb 2001 05:21:12 +0000 Subject: [PATCH] Introduced GimpPaintTool and GimpDrawTool --- ChangeLog | 53 + app/Makefile.am | 2 - app/apptypes.h | 4 +- app/context_manager.c | 1 - app/core/gimpbrush-load.c | 18 +- app/core/gimpbrush.c | 18 +- app/core/gimpbrush.h | 4 +- app/core/gimpbrushgenerated-load.c | 2 +- app/core/gimpbrushgenerated-save.c | 2 +- app/core/gimpbrushgenerated.c | 2 +- app/core/gimpbrushpipe-load.c | 32 +- app/core/gimpbrushpipe.c | 32 +- app/core/gimpcontext.c | 2 + app/core/gimpimage-mask.c | 2 +- .../gimpimage-pick-color.c} | 369 +-- app/core/gimpimage-undo-push.c | 4 +- app/core/gimpprojection.c | 1 - app/core/gimptoolinfo.c | 4 +- app/dialogs/info-window.c | 4 +- app/display/gimpdisplay.c | 1 - app/draw_core.c | 132 - app/draw_core.h | 67 - app/gdisplay.c | 1 - app/gimage_mask.c | 2 +- app/gimpbrush.c | 18 +- app/gimpbrush.h | 4 +- app/gimpbrushgenerated.c | 2 +- app/gimpbrushpipe.c | 32 +- app/gimpcontext.c | 2 + app/gui/info-window.c | 4 +- app/info_window.c | 4 +- .../paintbrush.c => paint/gimppaintbrush.c} | 271 +- app/paint/gimppaintbrush.h | 59 + .../paint_core.c => paint/gimppaintcore.c} | 930 +++---- .../paint_core.h => paint/gimppaintcore.h} | 117 +- app/path_transform.h | 2 +- app/pdb/tools_cmds.c | 8 +- app/tools/Makefile.am | 20 +- app/tools/bezier_selectP.h | 4 +- app/tools/color_picker.h | 70 - app/tools/gimpbrushtool.c | 2225 +++++++++++++++++ app/tools/gimpbrushtool.h | 219 ++ app/tools/gimpcolorpickertool.c | 886 +++++++ app/tools/gimpcolorpickertool.h | 68 + app/tools/gimpdrawtool.c | 192 ++ app/tools/gimpdrawtool.h | 77 + app/tools/gimpmeasuretool.c | 124 +- app/tools/gimpmeasuretool.h | 4 +- app/tools/gimpmovetool.c | 1 - app/tools/gimppaintbrushtool.c | 801 ++++++ app/tools/gimppaintbrushtool.h | 59 + app/tools/gimppaintoptions-gui.c | 2 + app/tools/gimppainttool.c | 2225 +++++++++++++++++ app/tools/gimppainttool.h | 219 ++ ...core_kernels.h => gimppainttool_kernels.h} | 0 app/tools/gimptool.c | 344 ++- app/tools/gimptool.h | 7 - app/tools/gimptoolinfo.c | 4 +- app/tools/measure.c | 124 +- app/tools/measure.h | 4 +- app/tools/move.c | 1 - app/tools/paint_options.c | 2 + app/tools/paintbrush.h | 37 - app/tools/tool.c | 344 ++- app/tools/tool.h | 7 - app/tools/tools.c | 22 +- app/tools/transform_core.h | 2 +- app/undo.c | 4 +- libgimp/Makefile.am | 2 +- tools/pdbgen/Makefile.am | 2 +- 70 files changed, 8597 insertions(+), 1717 deletions(-) rename app/{tools/color_picker.c => core/gimpimage-pick-color.c} (67%) delete mode 100644 app/draw_core.c delete mode 100644 app/draw_core.h rename app/{tools/paintbrush.c => paint/gimppaintbrush.c} (78%) create mode 100644 app/paint/gimppaintbrush.h rename app/{tools/paint_core.c => paint/gimppaintcore.c} (65%) rename app/{tools/paint_core.h => paint/gimppaintcore.h} (66%) delete mode 100644 app/tools/color_picker.h create mode 100644 app/tools/gimpbrushtool.c create mode 100644 app/tools/gimpbrushtool.h create mode 100644 app/tools/gimpcolorpickertool.c create mode 100644 app/tools/gimpcolorpickertool.h create mode 100644 app/tools/gimpdrawtool.c create mode 100644 app/tools/gimpdrawtool.h create mode 100644 app/tools/gimppaintbrushtool.c create mode 100644 app/tools/gimppaintbrushtool.h create mode 100644 app/tools/gimppainttool.c create mode 100644 app/tools/gimppainttool.h rename app/tools/{paint_core_kernels.h => gimppainttool_kernels.h} (100%) delete mode 100644 app/tools/paintbrush.h diff --git a/ChangeLog b/ChangeLog index 0ebc01e37b..f0830468bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,56 @@ +2001-02-26 Nathan Summers +app/tools/gimpdrawtool.c + * app/tools/gimpdrawtool.h + * app/tools/gimppainttool.c + * app/tools/gimppainttool.h + * app/tools/gimppainttool_kernels.h: Created GimpDrawTool and + GimpPaintTool, real classes that replace the old DrawCore and + PaintCore + + * app/Makefile.am + * app/apptypes.h + * app/context_manager.c + * app/gdisplay.c + * app/gimage_mask.c + * app/gimpbrush.c + * app/gimpbrush.h + * app/gimpbrushgenerated.c + * app/gimpbrushpipe.c + * app/gimpcontext.c + * app/info_window.c + * app/path_transform.h + * app/undo.c + * app/pdb/tools_cmds.c + * app/tools/Makefile.am + * app/tools/bezier_selectP.h + * app/tools/gimptoolinfo.c + * app/tools/measure.c + * app/tools/measure.h + * app/tools/move.c + * app/tools/paint_options.c + * app/tools/tool.c + * app/tools/tool.h + * app/tools/tools.c + * app/tools/transform_core.h + * tools/pdbgen/Makefile.am: changed accordingly + + * libgimp/Makefile.am: fixed glitch in build + + * app/tools/gimpcolorpickertool.c + * app/tools/gimpcolorpickertool.h + * app/tools/gimppaintbrushtool.c + * app/tools/gimppaintbrushtool.h:new names + + * app/draw_core.c + * app/draw_core.h + * app/tools/color_picker.c + * app/tools/color_picker.h + * app/tools/paint_core.c + * app/tools/paint_core.h + * app/tools/paint_core_kernels.h + * app/tools/paintbrush.c + * app/tools/paintbrush.h: removed + 2001-02-25 Michael Natterer * app/channel_ops.c diff --git a/app/Makefile.am b/app/Makefile.am index bc1c31b297..c3e59c284f 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -72,8 +72,6 @@ gimp_SOURCES = \ disp_callbacks.h \ docindex.c \ docindex.h \ - draw_core.c \ - draw_core.h \ drawable.c \ drawable.h \ errorconsole.c \ diff --git a/app/apptypes.h b/app/apptypes.h index 5a44f4f693..4ca8c98a37 100644 --- a/app/apptypes.h +++ b/app/apptypes.h @@ -111,7 +111,7 @@ typedef struct _BoundSeg BoundSeg; typedef struct _ColorNotebook ColorNotebook; -typedef struct _DrawCore DrawCore; +typedef struct _GimpDrawTool GimpDrawTool; typedef struct _GDisplay GDisplay; @@ -133,7 +133,7 @@ typedef gpointer ImageMap; typedef struct _InfoDialog InfoDialog; -typedef struct _PaintCore PaintCore; +typedef struct _GimpPaintTool GimpPaintTool; typedef struct _Path Path; typedef struct _PathPoint PathPoint; diff --git a/app/context_manager.c b/app/context_manager.c index 2e24df4501..4fe3c0d8e9 100644 --- a/app/context_manager.c +++ b/app/context_manager.c @@ -46,7 +46,6 @@ #include "gimppattern.h" #include "gimprc.h" - /* * the list of all images */ diff --git a/app/core/gimpbrush-load.c b/app/core/gimpbrush-load.c index d58eb9a2d2..6d1b0e0475 100644 --- a/app/core/gimpbrush-load.c +++ b/app/core/gimpbrush-load.c @@ -51,7 +51,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "brush_scale.h" #include "libgimp/gimpintl.h" @@ -65,8 +65,8 @@ static TempBuf * gimp_brush_get_new_preview (GimpViewable *viewable, gint height); static gchar * gimp_brush_get_extension (GimpData *data); -static GimpBrush * gimp_brush_select_brush (PaintCore *paint_core); -static gboolean gimp_brush_want_null_motion (PaintCore *paint_core); +static GimpBrush * gimp_brush_select_brush (GimpPaintTool *paint_tool); +static gboolean gimp_brush_want_null_motion (GimpPaintTool *paint_tool); static GimpViewableClass *parent_class = NULL; @@ -108,7 +108,7 @@ gimp_brush_class_init (GimpBrushClass *klass) data_class = (GimpDataClass *) klass; parent_class = gtk_type_class (GIMP_TYPE_DATA); - + object_class->destroy = gimp_brush_destroy; viewable_class->get_new_preview = gimp_brush_get_new_preview; @@ -180,7 +180,7 @@ gimp_brush_get_new_preview (GimpViewable *viewable, gdouble ratio_x = (gdouble) brush_width / width; gdouble ratio_y = (gdouble) brush_height / height; - brush_width = (gdouble) brush_width / MAX (ratio_x, ratio_y) + 0.5; + brush_width = (gdouble) brush_width / MAX (ratio_x, ratio_y) + 0.5; brush_height = (gdouble) brush_height / MAX (ratio_x, ratio_y) + 0.5; mask_buf = brush_scale_mask (mask_buf, brush_width, brush_height); @@ -218,7 +218,7 @@ gimp_brush_get_new_preview (GimpViewable *viewable, bg = (255 - *mask); *b++ = bg + (*mask * *pixmap++) / 255; - *b++ = bg + (*mask * *pixmap++) / 255; + *b++ = bg + (*mask * *pixmap++) / 255; *b++ = bg + (*mask * *pixmap++) / 255; mask++; @@ -305,7 +305,7 @@ gimp_brush_load (const gchar *filename) g_return_val_if_fail (filename != NULL, NULL); fd = open (filename, O_RDONLY | _O_BINARY); - if (fd == -1) + if (fd == -1) return NULL; brush = gimp_brush_load_brush (fd, filename); @@ -330,13 +330,13 @@ gimp_brush_load (const gchar *filename) } static GimpBrush * -gimp_brush_select_brush (PaintCore *paint_core) +gimp_brush_select_brush (GimpPaintTool *paint_core) { return paint_core->brush; } static gboolean -gimp_brush_want_null_motion (PaintCore *paint_core) +gimp_brush_want_null_motion (GimpPaintTool *paint_core) { return TRUE; } diff --git a/app/core/gimpbrush.c b/app/core/gimpbrush.c index d58eb9a2d2..6d1b0e0475 100644 --- a/app/core/gimpbrush.c +++ b/app/core/gimpbrush.c @@ -51,7 +51,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "brush_scale.h" #include "libgimp/gimpintl.h" @@ -65,8 +65,8 @@ static TempBuf * gimp_brush_get_new_preview (GimpViewable *viewable, gint height); static gchar * gimp_brush_get_extension (GimpData *data); -static GimpBrush * gimp_brush_select_brush (PaintCore *paint_core); -static gboolean gimp_brush_want_null_motion (PaintCore *paint_core); +static GimpBrush * gimp_brush_select_brush (GimpPaintTool *paint_tool); +static gboolean gimp_brush_want_null_motion (GimpPaintTool *paint_tool); static GimpViewableClass *parent_class = NULL; @@ -108,7 +108,7 @@ gimp_brush_class_init (GimpBrushClass *klass) data_class = (GimpDataClass *) klass; parent_class = gtk_type_class (GIMP_TYPE_DATA); - + object_class->destroy = gimp_brush_destroy; viewable_class->get_new_preview = gimp_brush_get_new_preview; @@ -180,7 +180,7 @@ gimp_brush_get_new_preview (GimpViewable *viewable, gdouble ratio_x = (gdouble) brush_width / width; gdouble ratio_y = (gdouble) brush_height / height; - brush_width = (gdouble) brush_width / MAX (ratio_x, ratio_y) + 0.5; + brush_width = (gdouble) brush_width / MAX (ratio_x, ratio_y) + 0.5; brush_height = (gdouble) brush_height / MAX (ratio_x, ratio_y) + 0.5; mask_buf = brush_scale_mask (mask_buf, brush_width, brush_height); @@ -218,7 +218,7 @@ gimp_brush_get_new_preview (GimpViewable *viewable, bg = (255 - *mask); *b++ = bg + (*mask * *pixmap++) / 255; - *b++ = bg + (*mask * *pixmap++) / 255; + *b++ = bg + (*mask * *pixmap++) / 255; *b++ = bg + (*mask * *pixmap++) / 255; mask++; @@ -305,7 +305,7 @@ gimp_brush_load (const gchar *filename) g_return_val_if_fail (filename != NULL, NULL); fd = open (filename, O_RDONLY | _O_BINARY); - if (fd == -1) + if (fd == -1) return NULL; brush = gimp_brush_load_brush (fd, filename); @@ -330,13 +330,13 @@ gimp_brush_load (const gchar *filename) } static GimpBrush * -gimp_brush_select_brush (PaintCore *paint_core) +gimp_brush_select_brush (GimpPaintTool *paint_core) { return paint_core->brush; } static gboolean -gimp_brush_want_null_motion (PaintCore *paint_core) +gimp_brush_want_null_motion (GimpPaintTool *paint_core) { return TRUE; } diff --git a/app/core/gimpbrush.h b/app/core/gimpbrush.h index 542ed64a43..53cd8e1733 100644 --- a/app/core/gimpbrush.h +++ b/app/core/gimpbrush.h @@ -53,8 +53,8 @@ struct _GimpBrushClass GimpDataClass parent_class; /* FIXME: these are no virtual function pointers but bad hacks: */ - GimpBrush * (* select_brush) (PaintCore *paint_core); - gboolean (* want_null_motion) (PaintCore *paint_core); + GimpBrush * (* select_brush) (GimpPaintTool *paint_tool); + gboolean (* want_null_motion) (GimpPaintTool *paint_tool); }; diff --git a/app/core/gimpbrushgenerated-load.c b/app/core/gimpbrushgenerated-load.c index 0d865a7ca9..9265736f6e 100644 --- a/app/core/gimpbrushgenerated-load.c +++ b/app/core/gimpbrushgenerated-load.c @@ -41,7 +41,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #define OVERSAMPLING 5 diff --git a/app/core/gimpbrushgenerated-save.c b/app/core/gimpbrushgenerated-save.c index 0d865a7ca9..9265736f6e 100644 --- a/app/core/gimpbrushgenerated-save.c +++ b/app/core/gimpbrushgenerated-save.c @@ -41,7 +41,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #define OVERSAMPLING 5 diff --git a/app/core/gimpbrushgenerated.c b/app/core/gimpbrushgenerated.c index 0d865a7ca9..9265736f6e 100644 --- a/app/core/gimpbrushgenerated.c +++ b/app/core/gimpbrushgenerated.c @@ -41,7 +41,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #define OVERSAMPLING 5 diff --git a/app/core/gimpbrushpipe-load.c b/app/core/gimpbrushpipe-load.c index e9d16721bd..e9ff8f2ccb 100644 --- a/app/core/gimpbrushpipe-load.c +++ b/app/core/gimpbrushpipe-load.c @@ -53,15 +53,15 @@ #include "gimprc.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "libgimp/gimpparasiteio.h" #include "libgimp/gimpintl.h" -static GimpBrush * gimp_brush_pipe_select_brush (PaintCore *paint_core); -static gboolean gimp_brush_pipe_want_null_motion (PaintCore *paint_core); +static GimpBrush * gimp_brush_pipe_select_brush (GimpPaintTool *paint_tool); +static gboolean gimp_brush_pipe_want_null_motion (GimpPaintTool *paint_tool); static void gimp_brush_pipe_destroy (GtkObject *object); @@ -69,16 +69,16 @@ static GimpBrushClass *parent_class = NULL; static GimpBrush * -gimp_brush_pipe_select_brush (PaintCore *paint_core) +gimp_brush_pipe_select_brush (GimpPaintTool *paint_tool) { GimpBrushPipe *pipe; gint i, brushix, ix; gdouble angle; - g_return_val_if_fail (paint_core != NULL, NULL); - g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_core->brush), NULL); + g_return_val_if_fail (paint_tool != NULL, NULL); + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_tool->brush), NULL); - pipe = GIMP_BRUSH_PIPE (paint_core->brush); + pipe = GIMP_BRUSH_PIPE (paint_tool->brush); if (pipe->nbrushes == 1) return GIMP_BRUSH (pipe->current); @@ -92,8 +92,8 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) ix = (pipe->index[i] + 1) % pipe->rank[i]; break; case PIPE_SELECT_ANGULAR: - angle = atan2 (paint_core->cury - paint_core->lasty, - paint_core->curx - paint_core->lastx); + angle = atan2 (paint_tool->cury - paint_tool->lasty, + paint_tool->curx - paint_tool->lastx); /* Offset angle to be compatible with PSP tubes */ angle += G_PI_2; /* Map it to the [0..2*G_PI) interval */ @@ -108,13 +108,13 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) ix = rand () % pipe->rank[i]; break; case PIPE_SELECT_PRESSURE: - ix = RINT (paint_core->curpressure * (pipe->rank[i] - 1)); + ix = RINT (paint_tool->curpressure * (pipe->rank[i] - 1)); break; case PIPE_SELECT_TILT_X: - ix = RINT (paint_core->curxtilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; + ix = RINT (paint_tool->curxtilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; break; case PIPE_SELECT_TILT_Y: - ix = RINT (paint_core->curytilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; + ix = RINT (paint_tool->curytilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; break; case PIPE_SELECT_CONSTANT: default: @@ -134,15 +134,15 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) } static gboolean -gimp_brush_pipe_want_null_motion (PaintCore *paint_core) +gimp_brush_pipe_want_null_motion (GimpPaintTool *paint_tool) { GimpBrushPipe *pipe; gint i; - g_return_val_if_fail (paint_core != NULL, TRUE); - g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_core->brush), TRUE); + g_return_val_if_fail (paint_tool != NULL, TRUE); + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_tool->brush), TRUE); - pipe = GIMP_BRUSH_PIPE (paint_core->brush); + pipe = GIMP_BRUSH_PIPE (paint_tool->brush); if (pipe->nbrushes == 1) return TRUE; diff --git a/app/core/gimpbrushpipe.c b/app/core/gimpbrushpipe.c index e9d16721bd..e9ff8f2ccb 100644 --- a/app/core/gimpbrushpipe.c +++ b/app/core/gimpbrushpipe.c @@ -53,15 +53,15 @@ #include "gimprc.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "libgimp/gimpparasiteio.h" #include "libgimp/gimpintl.h" -static GimpBrush * gimp_brush_pipe_select_brush (PaintCore *paint_core); -static gboolean gimp_brush_pipe_want_null_motion (PaintCore *paint_core); +static GimpBrush * gimp_brush_pipe_select_brush (GimpPaintTool *paint_tool); +static gboolean gimp_brush_pipe_want_null_motion (GimpPaintTool *paint_tool); static void gimp_brush_pipe_destroy (GtkObject *object); @@ -69,16 +69,16 @@ static GimpBrushClass *parent_class = NULL; static GimpBrush * -gimp_brush_pipe_select_brush (PaintCore *paint_core) +gimp_brush_pipe_select_brush (GimpPaintTool *paint_tool) { GimpBrushPipe *pipe; gint i, brushix, ix; gdouble angle; - g_return_val_if_fail (paint_core != NULL, NULL); - g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_core->brush), NULL); + g_return_val_if_fail (paint_tool != NULL, NULL); + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_tool->brush), NULL); - pipe = GIMP_BRUSH_PIPE (paint_core->brush); + pipe = GIMP_BRUSH_PIPE (paint_tool->brush); if (pipe->nbrushes == 1) return GIMP_BRUSH (pipe->current); @@ -92,8 +92,8 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) ix = (pipe->index[i] + 1) % pipe->rank[i]; break; case PIPE_SELECT_ANGULAR: - angle = atan2 (paint_core->cury - paint_core->lasty, - paint_core->curx - paint_core->lastx); + angle = atan2 (paint_tool->cury - paint_tool->lasty, + paint_tool->curx - paint_tool->lastx); /* Offset angle to be compatible with PSP tubes */ angle += G_PI_2; /* Map it to the [0..2*G_PI) interval */ @@ -108,13 +108,13 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) ix = rand () % pipe->rank[i]; break; case PIPE_SELECT_PRESSURE: - ix = RINT (paint_core->curpressure * (pipe->rank[i] - 1)); + ix = RINT (paint_tool->curpressure * (pipe->rank[i] - 1)); break; case PIPE_SELECT_TILT_X: - ix = RINT (paint_core->curxtilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; + ix = RINT (paint_tool->curxtilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; break; case PIPE_SELECT_TILT_Y: - ix = RINT (paint_core->curytilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; + ix = RINT (paint_tool->curytilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; break; case PIPE_SELECT_CONSTANT: default: @@ -134,15 +134,15 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) } static gboolean -gimp_brush_pipe_want_null_motion (PaintCore *paint_core) +gimp_brush_pipe_want_null_motion (GimpPaintTool *paint_tool) { GimpBrushPipe *pipe; gint i; - g_return_val_if_fail (paint_core != NULL, TRUE); - g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_core->brush), TRUE); + g_return_val_if_fail (paint_tool != NULL, TRUE); + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_tool->brush), TRUE); - pipe = GIMP_BRUSH_PIPE (paint_core->brush); + pipe = GIMP_BRUSH_PIPE (paint_tool->brush); if (pipe->nbrushes == 1) return TRUE; diff --git a/app/core/gimpcontext.c b/app/core/gimpcontext.c index 2ebee3bd0c..ae267df27d 100644 --- a/app/core/gimpcontext.c +++ b/app/core/gimpcontext.c @@ -1394,6 +1394,8 @@ gimp_context_real_set_tool (GimpContext *context, GTK_SIGNAL_FUNC (gimp_context_tool_dirty), context); + /* FIXME if (tool_info != standard_tool_info) */ + if (tool_info != standard_tool_info) context->tool_name = g_strdup (GIMP_OBJECT (tool_info)->name); } diff --git a/app/core/gimpimage-mask.c b/app/core/gimpimage-mask.c index 2ad07bdc7c..b487cce71f 100644 --- a/app/core/gimpimage-mask.c +++ b/app/core/gimpimage-mask.c @@ -22,7 +22,7 @@ #include "apptypes.h" -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "tools/paint_options.h" #include "tools/tool.h" #include "tools/tool_manager.h" diff --git a/app/tools/color_picker.c b/app/core/gimpimage-pick-color.c similarity index 67% rename from app/tools/color_picker.c rename to app/core/gimpimage-pick-color.c index 4375ac9c30..aceb514238 100644 --- a/app/tools/color_picker.c +++ b/app/core/gimpimage-pick-color.c @@ -24,11 +24,13 @@ #include "libgimpwidgets/gimpwidgets.h" #include "apptypes.h" - #include "appenv.h" -#include "color_picker.h" + +#include "tools/gimpdrawtool.h" +#include "tools/gimpcolorpickertool.h" + #include "cursorutil.h" -#include "draw_core.h" + #include "drawable.h" #include "gdisplay.h" #include "gimpimage.h" @@ -44,26 +46,25 @@ #include "pixmaps2.h" - /* maximum information buffer size */ #define MAX_INFO_BUF 8 /* the color picker structures */ -typedef struct _ColorPickerOptions ColorPickerOptions; +typedef struct _GimpColorPickerToolOptions GimpColorPickerToolOptions; -struct _ColorPickerOptions +struct _GimpColorPickerToolOptions { 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; @@ -76,36 +77,45 @@ struct _ColorPickerOptions /* local function prototypes */ -static void gimp_color_picker_class_init (GimpColorPickerClass *klass); -static void gimp_color_picker_init (GimpColorPicker *color_picker); +static void gimp_color_picker_tool_class_init (GimpColorPickerToolClass *klass); +static void gimp_color_picker_tool_init (GimpColorPickerTool *color_picker_tool); -static void gimp_color_picker_destroy (GtkObject *object); +static void gimp_color_picker_tool_destroy (GtkObject *object); -static void color_picker_button_press (GimpTool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void color_picker_button_release (GimpTool *tool, - GdkEventButton *bevent, - GDisplay *gdisp); -static void color_picker_motion (GimpTool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void color_picker_cursor_update (GimpTool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp); -static void color_picker_control (GimpTool *tool, - ToolAction action, - GDisplay *gdisp); +static void gimp_color_picker_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp); -static void colorpicker_draw (GimpTool *tool); +static void gimp_color_picker_tool_draw (GimpTool *tool); -static ColorPickerOptions * color_picker_options_new (void); -static void color_picker_options_reset (void); -static void color_picker_info_window_close_callback (GtkWidget *widget, - gpointer data); -static void color_picker_info_update (GimpTool *tool, - gboolean valid); + +static GimpColorPickerToolOptions * gimp_color_picker_tool_options_new (void); + +static void gimp_color_picker_tool_options_reset (void); +static void gimp_color_picker_tool_info_window_close_callback (GtkWidget *widget, + gpointer data); +static void gimp_color_picker_tool_info_update (GimpTool *tool, + gboolean valid); + + + static gboolean pick_color_do (GimpImage *gimage, GimpDrawable *drawable, gint x, @@ -118,7 +128,7 @@ static gboolean pick_color_do (GimpImage *gimage, /* the color picker tool options */ -static ColorPickerOptions * color_picker_options = NULL; +static GimpColorPickerToolOptions * gimp_color_picker_tool_options = NULL; /* the color value */ gint col_value[5] = { 0, 0, 0, 0, 0 }; @@ -126,7 +136,7 @@ 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 InfoDialog *gimp_color_picker_tool_info = NULL; static GtkWidget *color_area = NULL; static gchar red_buf [MAX_INFO_BUF]; static gchar green_buf[MAX_INFO_BUF]; @@ -136,14 +146,13 @@ static gchar index_buf[MAX_INFO_BUF]; static gchar gray_buf [MAX_INFO_BUF]; static gchar hex_buf [MAX_INFO_BUF]; - static GimpToolClass *parent_class = NULL; void -gimp_color_picker_register (void) +gimp_color_picker_tool_register (void) { - tool_manager_register_tool (GIMP_TYPE_COLOR_PICKER, + tool_manager_register_tool (GIMP_TYPE_COLOR_PICKER_TOOL, "gimp:color_picker_tool", _("Color Picker"), _("Pick colors from the image"), @@ -153,7 +162,7 @@ gimp_color_picker_register (void) } GtkType -gimp_color_picker_get_type (void) +gimp_color_picker_tool_get_type (void) { static GtkType tool_type = 0; @@ -161,80 +170,80 @@ gimp_color_picker_get_type (void) { GtkTypeInfo tool_info = { - "GimpColorPicker", - sizeof (GimpColorPicker), - sizeof (GimpColorPickerClass), - (GtkClassInitFunc) gimp_color_picker_class_init, - (GtkObjectInitFunc) gimp_color_picker_init, + "GimpColorPickerTool", + sizeof (GimpColorPickerTool), + sizeof (GimpColorPickerToolClass), + (GtkClassInitFunc) gimp_color_picker_tool_class_init, + (GtkObjectInitFunc) gimp_color_picker_tool_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; - - tool_type = gtk_type_unique (GIMP_TYPE_TOOL, &tool_info); + + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); } return tool_type; } static void -gimp_color_picker_class_init (GimpColorPickerClass *klass) +gimp_color_picker_tool_class_init (GimpColorPickerToolClass *klass) { - GtkObjectClass *object_class; - GimpToolClass *tool_class; + GtkObjectClass *object_class; + GimpToolClass *tool_class; + GimpDrawToolClass *draw_class; object_class = (GtkObjectClass *) klass; tool_class = (GimpToolClass *) klass; - parent_class = gtk_type_class (GIMP_TYPE_TOOL); + parent_class = gtk_type_class (GIMP_TYPE_DRAW_TOOL); - object_class->destroy = gimp_color_picker_destroy; + object_class->destroy = gimp_color_picker_tool_destroy; - tool_class->control = color_picker_control; - tool_class->button_press = color_picker_button_press; - tool_class->button_release = color_picker_button_release; - tool_class->motion = color_picker_motion; - tool_class->cursor_update = color_picker_cursor_update; + tool_class->control = gimp_color_picker_tool_control; + tool_class->button_press = gimp_color_picker_tool_button_press; + tool_class->button_release = gimp_color_picker_tool_button_release; + tool_class->motion = gimp_color_picker_tool_motion; + tool_class->cursor_update = gimp_color_picker_tool_cursor_update; + + draw_class->draw = gimp_color_picker_tool_draw; } static void -gimp_color_picker_init (GimpColorPicker *color_picker) +gimp_color_picker_tool_init (GimpColorPickerTool *color_picker_tool) { GimpTool *tool; - tool = GIMP_TOOL (color_picker); + tool = GIMP_TOOL (color_picker_tool); - if (! color_picker_options) + if (! gimp_color_picker_tool_options) { - color_picker_options = color_picker_options_new (); + gimp_color_picker_tool_options = gimp_color_picker_tool_options_new (); - tool_manager_register_tool_options (GIMP_TYPE_COLOR_PICKER, - (ToolOptions *) color_picker_options); + tool_manager_register_tool_options (GIMP_TYPE_COLOR_PICKER_TOOL, + (ToolOptions *) gimp_color_picker_tool_options); } - color_picker->core = draw_core_new (colorpicker_draw); - tool->preserve = FALSE; /* Don't preserve on drawable change */ } static void -gimp_color_picker_destroy (GtkObject *object) +gimp_color_picker_tool_destroy (GtkObject *object) { - GimpColorPicker *color_picker; - GimpTool *tool; + GimpTool *tool; + GimpDrawTool *draw_tool; + + tool = GIMP_TOOL (object); + draw_tool = GIMP_DRAW_TOOL (object); - color_picker = GIMP_COLOR_PICKER (object); - tool = GIMP_TOOL (object); if (tool->state == ACTIVE) - draw_core_stop (color_picker->core, tool); + gimp_draw_tool_stop (draw_tool); - draw_core_free (color_picker->core); - - if (color_picker_info) + if (gimp_color_picker_tool_info) { - info_dialog_free (color_picker_info); - color_picker_info = NULL; + info_dialog_free (gimp_color_picker_tool_info); + gimp_color_picker_tool_info = NULL; color_area = NULL; } @@ -244,9 +253,9 @@ gimp_color_picker_destroy (GtkObject *object) } static void -color_picker_options_reset (void) +gimp_color_picker_tool_options_reset (void) { - ColorPickerOptions *options = color_picker_options; + GimpColorPickerToolOptions *options = gimp_color_picker_tool_options; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w), options->sample_merged_d); @@ -258,10 +267,10 @@ color_picker_options_reset (void) options->update_active_d); } -static ColorPickerOptions * -color_picker_options_new (void) +static GimpColorPickerToolOptions * +gimp_color_picker_tool_options_new (void) { - ColorPickerOptions *options; + GimpColorPickerToolOptions *options; GtkWidget *vbox; GtkWidget *abox; @@ -270,9 +279,9 @@ color_picker_options_new (void) GtkWidget *scale; /* the new color picker tool options structure */ - options = g_new (ColorPickerOptions, 1); + options = g_new (GimpColorPickerToolOptions, 1); tool_options_init ((ToolOptions *) options, - color_picker_options_reset); + gimp_color_picker_tool_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; @@ -354,14 +363,14 @@ color_picker_options_new (void) } static void -color_picker_button_press (GimpTool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) +gimp_color_picker_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) { - GimpColorPicker *cp_tool; - gint x, y; + GimpColorPickerTool *cp_tool; + gint x, y; - cp_tool = GIMP_COLOR_PICKER(tool); + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); /* Make the tool active and set it's gdisplay & drawable */ tool->gdisp = gdisp; @@ -369,39 +378,39 @@ color_picker_button_press (GimpTool *tool, tool->state = ACTIVE; /* create the info dialog if it doesn't exist */ - if (! color_picker_info) + if (! gimp_color_picker_tool_info) { GtkWidget *hbox; GtkWidget *frame; GimpRGB color; - color_picker_info = info_dialog_new (_("Color Picker"), + gimp_color_picker_tool_info = info_dialog_new (_("Color Picker"), tool_manager_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); + info_dialog_add_label (gimp_color_picker_tool_info, _("Red:"), red_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Green:"), green_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Blue:"), blue_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Alpha:"), alpha_buf); + info_dialog_add_label (gimp_color_picker_tool_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); + info_dialog_add_label (gimp_color_picker_tool_info, _("Index:"), index_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Red:"), red_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Green:"), green_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Blue:"), blue_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Alpha:"), alpha_buf); + info_dialog_add_label (gimp_color_picker_tool_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); + info_dialog_add_label (gimp_color_picker_tool_info, _("Intensity:"), gray_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Alpha:"), alpha_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Hex Triplet:"), hex_buf); break; default : @@ -409,22 +418,22 @@ color_picker_button_press (GimpTool *tool, } hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (color_picker_info->vbox), hbox, + gtk_box_pack_start (GTK_BOX (gimp_color_picker_tool_info->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); - gtk_widget_reparent (color_picker_info->info_table, hbox); + gtk_widget_reparent (gimp_color_picker_tool_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 = + color_area = gimp_color_area_new (&color, - gimp_drawable_has_alpha (tool->drawable) ? - GIMP_COLOR_AREA_LARGE_CHECKS : - GIMP_COLOR_AREA_FLAT, + 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); @@ -434,10 +443,10 @@ color_picker_button_press (GimpTool *tool, /* create the action area */ gimp_dialog_create_action_area - (GTK_DIALOG (color_picker_info->shell), + (GTK_DIALOG (gimp_color_picker_tool_info->shell), - _("Close"), color_picker_info_window_close_callback, - color_picker_info, NULL, NULL, TRUE, FALSE, + _("Close"), gimp_color_picker_tool_info_window_close_callback, + gimp_color_picker_tool_info, NULL, NULL, TRUE, FALSE, NULL); } @@ -461,72 +470,72 @@ color_picker_button_press (GimpTool *tool, */ if (bevent->state & GDK_SHIFT_MASK) { - color_picker_info_update + gimp_color_picker_tool_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, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, COLOR_NEW)); update_type = COLOR_UPDATE_NEW; } else { - color_picker_info_update + gimp_color_picker_tool_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, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, COLOR_UPDATE)); update_type = COLOR_UPDATE; } /* Start drawing the colorpicker tool */ - draw_core_start (cp_tool->core, gdisp->canvas->window, tool); + gimp_draw_tool_start (GIMP_DRAW_TOOL(cp_tool), gdisp->canvas->window); } static void -color_picker_button_release (GimpTool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) +gimp_color_picker_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) { - GimpColorPicker *cp_tool; + GimpColorPickerTool *cp_tool; gint x, y; gdk_pointer_ungrab (bevent->time); gdk_flush (); - cp_tool = GIMP_COLOR_PICKER(tool); + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); /* First, transform the coordinates to gimp image space */ gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, FALSE, FALSE); - color_picker_info_update + gimp_color_picker_tool_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, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, update_type)); - draw_core_stop (cp_tool->core, tool); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(cp_tool)); tool->state = INACTIVE; } static void -color_picker_motion (GimpTool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) +gimp_color_picker_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) { - GimpColorPicker *cp_tool; + GimpColorPickerTool *cp_tool; gint x, y; - cp_tool = GIMP_COLOR_PICKER(tool); + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); /* undraw the current tool */ - draw_core_pause (cp_tool->core, tool); + gimp_draw_tool_pause (GIMP_DRAW_TOOL(cp_tool)); /* First, transform the coordinates to gimp image space */ gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, @@ -536,22 +545,22 @@ color_picker_motion (GimpTool *tool, &cp_tool->centerx, &cp_tool->centery, FALSE, TRUE); - color_picker_info_update + gimp_color_picker_tool_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, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, update_type)); /* redraw the current tool */ - draw_core_resume (cp_tool->core, tool); + gimp_draw_tool_resume (GIMP_DRAW_TOOL(cp_tool)); } static void -color_picker_cursor_update (GimpTool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) +gimp_color_picker_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) { gint x, y; @@ -567,42 +576,40 @@ color_picker_cursor_update (GimpTool *tool, x > 0 && x < gdisp->gimage->width && y > 0 && y < gdisp->gimage->height) { - gdisplay_install_tool_cursor (gdisp, - GIMP_COLOR_PICKER_CURSOR, + gdisplay_install_tool_cursor (gdisp, GIMP_COLOR_PICKER_CURSOR, GIMP_COLOR_PICKER_TOOL_CURSOR, GIMP_CURSOR_MODIFIER_NONE); } else { - gdisplay_install_tool_cursor (gdisp, - GIMP_BAD_CURSOR, + gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, GIMP_COLOR_PICKER_TOOL_CURSOR, GIMP_CURSOR_MODIFIER_NONE); } } static void -color_picker_control (GimpTool *tool, - ToolAction action, - GDisplay *gdisp) +gimp_color_picker_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp) { - GimpColorPicker *cp_tool; + GimpDrawTool *dr_tool; - cp_tool = GIMP_COLOR_PICKER(tool); + dr_tool = GIMP_DRAW_TOOL(tool); switch (action) { case PAUSE : - draw_core_pause (cp_tool->core, tool); + gimp_draw_tool_pause (dr_tool); break; case RESUME : - draw_core_resume (cp_tool->core, tool); + gimp_draw_tool_resume (dr_tool); break; case HALT : - draw_core_stop (cp_tool->core, tool); - info_dialog_popdown (color_picker_info); + gimp_draw_tool_stop (dr_tool); + info_dialog_popdown (gimp_color_picker_tool_info); break; default: @@ -634,7 +641,7 @@ pick_color_do (GimpImage *gimage, GimpObject *get_color_obj; - if (!drawable && !sample_merged) + if (!drawable && !sample_merged) return FALSE; if (!sample_merged) @@ -676,7 +683,7 @@ pick_color_do (GimpImage *gimage, 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]; @@ -734,43 +741,45 @@ pick_color (GimpImage *gimage, } static void -colorpicker_draw (GimpTool *tool) +gimp_color_picker_tool_draw (GimpTool *tool) { - GimpColorPicker *cp_tool; + GimpColorPickerTool *cp_tool; + GimpDrawTool *dr_tool; gint tx, ty; gint radiusx, radiusy; gint cx, cy; - if (! color_picker_options->sample_average) + if (! gimp_color_picker_tool_options->sample_average) return; - cp_tool = GIMP_COLOR_PICKER(tool); + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); + dr_tool = GIMP_DRAW_TOOL(tool); 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); + radiusx = SCALEX (tool->gdisp, gimp_color_picker_tool_options->average_radius); + radiusy = SCALEY (tool->gdisp, gimp_color_picker_tool_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, + gdk_draw_rectangle (dr_tool->win, dr_tool->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, + gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0, + tx - radiusx + 2, ty - radiusy + 2, 2 * radiusx + cx - 4, 2 * radiusy + cy - 4); } } static void -color_picker_info_update (GimpTool *tool, +gimp_color_picker_tool_info_update (GimpTool *tool, gboolean valid) { if (!valid) @@ -865,13 +874,13 @@ color_picker_info_update (GimpTool *tool, gimp_color_area_set_color (GIMP_COLOR_AREA (color_area), &color); } - info_dialog_update (color_picker_info); - info_dialog_popup (color_picker_info); + info_dialog_update (gimp_color_picker_tool_info); + info_dialog_popup (gimp_color_picker_tool_info); } static void -color_picker_info_window_close_callback (GtkWidget *widget, - gpointer client_data) +gimp_color_picker_tool_info_window_close_callback (GtkWidget *widget, + gpointer client_data) { info_dialog_popdown ((InfoDialog *) client_data); } diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index 5e4b0760e1..1ea2784d84 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -25,7 +25,6 @@ #include "apptypes.h" -#include "draw_core.h" #include "drawable.h" #include "floating_sel.h" #include "gdisplay.h" @@ -47,7 +46,8 @@ #include "undo.h" #include "tools/by_color_select.h" -#include "tools/paint_core.h" +#include "tools/gimpdrawtool.h" +#include "tools/gimppainttool.h" #include "tools/tool.h" #include "tools/transform_core.h" diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c index eeb7b67375..9f73698eb2 100644 --- a/app/core/gimpprojection.c +++ b/app/core/gimpprojection.c @@ -31,7 +31,6 @@ #include "colormaps.h" #include "cursorutil.h" #include "disp_callbacks.h" -#include "draw_core.h" #include "gdisplay.h" #include "gdisplay_ops.h" #include "gimage.h" diff --git a/app/core/gimptoolinfo.c b/app/core/gimptoolinfo.c index 9dc0122533..2af323300e 100644 --- a/app/core/gimptoolinfo.c +++ b/app/core/gimptoolinfo.c @@ -26,7 +26,7 @@ #include "temp_buf.h" /* FIXME: include rect_select.h here */ -#include "color_picker.h" +#include "gimpcolorpickertool.h" static void gimp_tool_info_class_init (GimpToolInfoClass *klass); @@ -236,7 +236,7 @@ gimp_tool_info_get_standard (void) if (! standard_tool_info) { standard_tool_info = - gimp_tool_info_new (GIMP_TYPE_COLOR_PICKER, + gimp_tool_info_new (GIMP_TYPE_COLOR_PICKER_TOOL, "gimp:standard_tool", "Standard Tool", "Well something must be broken", diff --git a/app/dialogs/info-window.c b/app/dialogs/info-window.c index f9bf5b1219..abb4a21730 100644 --- a/app/dialogs/info-window.c +++ b/app/dialogs/info-window.c @@ -24,7 +24,7 @@ #include "apptypes.h" -#include "tools/color_picker.h" +#include "tools/gimpcolorpickertool.h" #include "tools/tool.h" #include "tools/tool_manager.h" @@ -161,7 +161,7 @@ info_window_create_extended (InfoDialog *info_win) gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); - preview = gimp_preview_new (GIMP_VIEWABLE (tool_manager_get_info_by_type (GIMP_TYPE_COLOR_PICKER)), 22, 0, FALSE); + preview = gimp_preview_new (GIMP_VIEWABLE (tool_manager_get_info_by_type (GIMP_TYPE_COLOR_PICKER_TOOL)), 22, 0, FALSE); gtk_table_attach (GTK_TABLE (table), preview, 0, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); gtk_widget_show (preview); diff --git a/app/display/gimpdisplay.c b/app/display/gimpdisplay.c index eeb7b67375..9f73698eb2 100644 --- a/app/display/gimpdisplay.c +++ b/app/display/gimpdisplay.c @@ -31,7 +31,6 @@ #include "colormaps.h" #include "cursorutil.h" #include "disp_callbacks.h" -#include "draw_core.h" #include "gdisplay.h" #include "gdisplay_ops.h" #include "gimage.h" diff --git a/app/draw_core.c b/app/draw_core.c deleted file mode 100644 index 6fa5e28c6f..0000000000 --- a/app/draw_core.c +++ /dev/null @@ -1,132 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include - -#include "apptypes.h" - -#include "appenv.h" -#include "draw_core.h" - - -DrawCore * -draw_core_new (DrawCoreDraw draw_func) -{ - DrawCore * core; - - core = (DrawCore *) g_malloc (sizeof (DrawCore)); - - core->draw_func = draw_func; - core->draw_state = INVISIBLE; - core->gc = NULL; - core->paused_count = 0; - core->data = NULL; - core->line_width = 0; - core->line_style = GDK_LINE_SOLID; - core->cap_style = GDK_CAP_NOT_LAST; - core->join_style = GDK_JOIN_MITER; - - return core; -} - - -void -draw_core_start (DrawCore *core, - GdkWindow *win, - GimpTool *tool) -{ - GdkColor fg, bg; - - if (core->draw_state != INVISIBLE) - draw_core_stop (core, tool); - - core->win = win; - core->data = (void *) tool; - core->paused_count = 0; /* reset pause counter to 0 */ - - /* create a new graphics context */ - if (! core->gc) - core->gc = gdk_gc_new (win); - - gdk_gc_set_function (core->gc, GDK_INVERT); - fg.pixel = 0xFFFFFFFF; - bg.pixel = 0x00000000; - gdk_gc_set_foreground (core->gc, &fg); - gdk_gc_set_background (core->gc, &bg); - gdk_gc_set_line_attributes (core->gc, core->line_width, core->line_style, - core->cap_style, core->join_style); - - (* core->draw_func) (tool); - - core->draw_state = VISIBLE; -} - - -void -draw_core_stop (DrawCore *core, - GimpTool *tool) -{ - if (core->draw_state == INVISIBLE) - return; - - (* core->draw_func) (tool); - - core->draw_state = INVISIBLE; -} - - -void -draw_core_resume (DrawCore *core, - GimpTool *tool) -{ - core->paused_count = (core->paused_count > 0) ? core->paused_count - 1 : 0; - if (core->paused_count == 0) - { - core->draw_state = VISIBLE; - (* core->draw_func) (tool); - } -} - - -void -draw_core_pause (DrawCore *core, - GimpTool *tool) -{ - if (core->paused_count == 0) - { - core->draw_state = INVISIBLE; - (* core->draw_func) (tool); - } - core->paused_count++; -} - - -void -draw_core_free (DrawCore *core) -{ - if (core) - { - if (core->gc) - gdk_gc_destroy (core->gc); - g_free (core); - } -} - - diff --git a/app/draw_core.h b/app/draw_core.h deleted file mode 100644 index 88499f1b0c..0000000000 --- a/app/draw_core.h +++ /dev/null @@ -1,67 +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 __DRAW_CORE_H__ -#define __DRAW_CORE_H__ - - -/* drawing states */ -#define INVISIBLE 0 -#define VISIBLE 1 - - -/* Structure definitions */ - -typedef void (* DrawCoreDraw) (GimpTool *); - -struct _DrawCore -{ - GdkGC * gc; /* Grahpics context for drawing functions */ - GdkWindow * win; /* Window to draw draw operation to */ - - gint draw_state; /* Current state in the drawing process */ - - gint line_width; /**/ - gint line_style; /**/ - gint cap_style; /* line attributes */ - gint join_style; /**/ - - gint paused_count; /* count to keep track of multiple pauses */ - - gpointer data; /* data to pass to draw_func */ - - DrawCoreDraw draw_func; /* Member function for actual drawing */ -}; - - -/* draw core functions */ - -DrawCore * draw_core_new (DrawCoreDraw ); -void draw_core_start (DrawCore *, - GdkWindow *, - GimpTool *); -void draw_core_stop (DrawCore *, - GimpTool *); -void draw_core_pause (DrawCore *, - GimpTool *); -void draw_core_resume (DrawCore *, - GimpTool *); -void draw_core_free (DrawCore *); - - -#endif /* __DRAW_CORE_H__ */ diff --git a/app/gdisplay.c b/app/gdisplay.c index eeb7b67375..9f73698eb2 100644 --- a/app/gdisplay.c +++ b/app/gdisplay.c @@ -31,7 +31,6 @@ #include "colormaps.h" #include "cursorutil.h" #include "disp_callbacks.h" -#include "draw_core.h" #include "gdisplay.h" #include "gdisplay_ops.h" #include "gimage.h" diff --git a/app/gimage_mask.c b/app/gimage_mask.c index 2ad07bdc7c..b487cce71f 100644 --- a/app/gimage_mask.c +++ b/app/gimage_mask.c @@ -22,7 +22,7 @@ #include "apptypes.h" -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "tools/paint_options.h" #include "tools/tool.h" #include "tools/tool_manager.h" diff --git a/app/gimpbrush.c b/app/gimpbrush.c index d58eb9a2d2..6d1b0e0475 100644 --- a/app/gimpbrush.c +++ b/app/gimpbrush.c @@ -51,7 +51,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "brush_scale.h" #include "libgimp/gimpintl.h" @@ -65,8 +65,8 @@ static TempBuf * gimp_brush_get_new_preview (GimpViewable *viewable, gint height); static gchar * gimp_brush_get_extension (GimpData *data); -static GimpBrush * gimp_brush_select_brush (PaintCore *paint_core); -static gboolean gimp_brush_want_null_motion (PaintCore *paint_core); +static GimpBrush * gimp_brush_select_brush (GimpPaintTool *paint_tool); +static gboolean gimp_brush_want_null_motion (GimpPaintTool *paint_tool); static GimpViewableClass *parent_class = NULL; @@ -108,7 +108,7 @@ gimp_brush_class_init (GimpBrushClass *klass) data_class = (GimpDataClass *) klass; parent_class = gtk_type_class (GIMP_TYPE_DATA); - + object_class->destroy = gimp_brush_destroy; viewable_class->get_new_preview = gimp_brush_get_new_preview; @@ -180,7 +180,7 @@ gimp_brush_get_new_preview (GimpViewable *viewable, gdouble ratio_x = (gdouble) brush_width / width; gdouble ratio_y = (gdouble) brush_height / height; - brush_width = (gdouble) brush_width / MAX (ratio_x, ratio_y) + 0.5; + brush_width = (gdouble) brush_width / MAX (ratio_x, ratio_y) + 0.5; brush_height = (gdouble) brush_height / MAX (ratio_x, ratio_y) + 0.5; mask_buf = brush_scale_mask (mask_buf, brush_width, brush_height); @@ -218,7 +218,7 @@ gimp_brush_get_new_preview (GimpViewable *viewable, bg = (255 - *mask); *b++ = bg + (*mask * *pixmap++) / 255; - *b++ = bg + (*mask * *pixmap++) / 255; + *b++ = bg + (*mask * *pixmap++) / 255; *b++ = bg + (*mask * *pixmap++) / 255; mask++; @@ -305,7 +305,7 @@ gimp_brush_load (const gchar *filename) g_return_val_if_fail (filename != NULL, NULL); fd = open (filename, O_RDONLY | _O_BINARY); - if (fd == -1) + if (fd == -1) return NULL; brush = gimp_brush_load_brush (fd, filename); @@ -330,13 +330,13 @@ gimp_brush_load (const gchar *filename) } static GimpBrush * -gimp_brush_select_brush (PaintCore *paint_core) +gimp_brush_select_brush (GimpPaintTool *paint_core) { return paint_core->brush; } static gboolean -gimp_brush_want_null_motion (PaintCore *paint_core) +gimp_brush_want_null_motion (GimpPaintTool *paint_core) { return TRUE; } diff --git a/app/gimpbrush.h b/app/gimpbrush.h index 542ed64a43..53cd8e1733 100644 --- a/app/gimpbrush.h +++ b/app/gimpbrush.h @@ -53,8 +53,8 @@ struct _GimpBrushClass GimpDataClass parent_class; /* FIXME: these are no virtual function pointers but bad hacks: */ - GimpBrush * (* select_brush) (PaintCore *paint_core); - gboolean (* want_null_motion) (PaintCore *paint_core); + GimpBrush * (* select_brush) (GimpPaintTool *paint_tool); + gboolean (* want_null_motion) (GimpPaintTool *paint_tool); }; diff --git a/app/gimpbrushgenerated.c b/app/gimpbrushgenerated.c index 0d865a7ca9..9265736f6e 100644 --- a/app/gimpbrushgenerated.c +++ b/app/gimpbrushgenerated.c @@ -41,7 +41,7 @@ #include "temp_buf.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #define OVERSAMPLING 5 diff --git a/app/gimpbrushpipe.c b/app/gimpbrushpipe.c index e9d16721bd..e9ff8f2ccb 100644 --- a/app/gimpbrushpipe.c +++ b/app/gimpbrushpipe.c @@ -53,15 +53,15 @@ #include "gimprc.h" /* this needs to go away */ -#include "tools/paint_core.h" +#include "tools/gimppainttool.h" #include "libgimp/gimpparasiteio.h" #include "libgimp/gimpintl.h" -static GimpBrush * gimp_brush_pipe_select_brush (PaintCore *paint_core); -static gboolean gimp_brush_pipe_want_null_motion (PaintCore *paint_core); +static GimpBrush * gimp_brush_pipe_select_brush (GimpPaintTool *paint_tool); +static gboolean gimp_brush_pipe_want_null_motion (GimpPaintTool *paint_tool); static void gimp_brush_pipe_destroy (GtkObject *object); @@ -69,16 +69,16 @@ static GimpBrushClass *parent_class = NULL; static GimpBrush * -gimp_brush_pipe_select_brush (PaintCore *paint_core) +gimp_brush_pipe_select_brush (GimpPaintTool *paint_tool) { GimpBrushPipe *pipe; gint i, brushix, ix; gdouble angle; - g_return_val_if_fail (paint_core != NULL, NULL); - g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_core->brush), NULL); + g_return_val_if_fail (paint_tool != NULL, NULL); + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_tool->brush), NULL); - pipe = GIMP_BRUSH_PIPE (paint_core->brush); + pipe = GIMP_BRUSH_PIPE (paint_tool->brush); if (pipe->nbrushes == 1) return GIMP_BRUSH (pipe->current); @@ -92,8 +92,8 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) ix = (pipe->index[i] + 1) % pipe->rank[i]; break; case PIPE_SELECT_ANGULAR: - angle = atan2 (paint_core->cury - paint_core->lasty, - paint_core->curx - paint_core->lastx); + angle = atan2 (paint_tool->cury - paint_tool->lasty, + paint_tool->curx - paint_tool->lastx); /* Offset angle to be compatible with PSP tubes */ angle += G_PI_2; /* Map it to the [0..2*G_PI) interval */ @@ -108,13 +108,13 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) ix = rand () % pipe->rank[i]; break; case PIPE_SELECT_PRESSURE: - ix = RINT (paint_core->curpressure * (pipe->rank[i] - 1)); + ix = RINT (paint_tool->curpressure * (pipe->rank[i] - 1)); break; case PIPE_SELECT_TILT_X: - ix = RINT (paint_core->curxtilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; + ix = RINT (paint_tool->curxtilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; break; case PIPE_SELECT_TILT_Y: - ix = RINT (paint_core->curytilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; + ix = RINT (paint_tool->curytilt / 2.0 * pipe->rank[i]) + pipe->rank[i]/2; break; case PIPE_SELECT_CONSTANT: default: @@ -134,15 +134,15 @@ gimp_brush_pipe_select_brush (PaintCore *paint_core) } static gboolean -gimp_brush_pipe_want_null_motion (PaintCore *paint_core) +gimp_brush_pipe_want_null_motion (GimpPaintTool *paint_tool) { GimpBrushPipe *pipe; gint i; - g_return_val_if_fail (paint_core != NULL, TRUE); - g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_core->brush), TRUE); + g_return_val_if_fail (paint_tool != NULL, TRUE); + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (paint_tool->brush), TRUE); - pipe = GIMP_BRUSH_PIPE (paint_core->brush); + pipe = GIMP_BRUSH_PIPE (paint_tool->brush); if (pipe->nbrushes == 1) return TRUE; diff --git a/app/gimpcontext.c b/app/gimpcontext.c index 2ebee3bd0c..ae267df27d 100644 --- a/app/gimpcontext.c +++ b/app/gimpcontext.c @@ -1394,6 +1394,8 @@ gimp_context_real_set_tool (GimpContext *context, GTK_SIGNAL_FUNC (gimp_context_tool_dirty), context); + /* FIXME if (tool_info != standard_tool_info) */ + if (tool_info != standard_tool_info) context->tool_name = g_strdup (GIMP_OBJECT (tool_info)->name); } diff --git a/app/gui/info-window.c b/app/gui/info-window.c index f9bf5b1219..abb4a21730 100644 --- a/app/gui/info-window.c +++ b/app/gui/info-window.c @@ -24,7 +24,7 @@ #include "apptypes.h" -#include "tools/color_picker.h" +#include "tools/gimpcolorpickertool.h" #include "tools/tool.h" #include "tools/tool_manager.h" @@ -161,7 +161,7 @@ info_window_create_extended (InfoDialog *info_win) gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); - preview = gimp_preview_new (GIMP_VIEWABLE (tool_manager_get_info_by_type (GIMP_TYPE_COLOR_PICKER)), 22, 0, FALSE); + preview = gimp_preview_new (GIMP_VIEWABLE (tool_manager_get_info_by_type (GIMP_TYPE_COLOR_PICKER_TOOL)), 22, 0, FALSE); gtk_table_attach (GTK_TABLE (table), preview, 0, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); gtk_widget_show (preview); diff --git a/app/info_window.c b/app/info_window.c index f9bf5b1219..abb4a21730 100644 --- a/app/info_window.c +++ b/app/info_window.c @@ -24,7 +24,7 @@ #include "apptypes.h" -#include "tools/color_picker.h" +#include "tools/gimpcolorpickertool.h" #include "tools/tool.h" #include "tools/tool_manager.h" @@ -161,7 +161,7 @@ info_window_create_extended (InfoDialog *info_win) gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); - preview = gimp_preview_new (GIMP_VIEWABLE (tool_manager_get_info_by_type (GIMP_TYPE_COLOR_PICKER)), 22, 0, FALSE); + preview = gimp_preview_new (GIMP_VIEWABLE (tool_manager_get_info_by_type (GIMP_TYPE_COLOR_PICKER_TOOL)), 22, 0, FALSE); gtk_table_attach (GTK_TABLE (table), preview, 0, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); gtk_widget_show (preview); diff --git a/app/tools/paintbrush.c b/app/paint/gimppaintbrush.c similarity index 78% rename from app/tools/paintbrush.c rename to app/paint/gimppaintbrush.c index 3f9eb86fb0..aa9f23d43c 100644 --- a/app/tools/paintbrush.c +++ b/app/paint/gimppaintbrush.c @@ -36,15 +36,17 @@ #include "selection.h" #include "temp_buf.h" -#include "paint_core.h" +#include "tools/gimppainttool.h" #include "paint_options.h" -#include "paintbrush.h" +#include "tools/gimppaintbrushtool.h" #include "tool_options.h" -#include "tools.h" +#include "tools/tool.h" +#include "tools/tool_manager.h" + +#include "pixmaps2.h" #include "libgimp/gimpintl.h" - /* defines */ #define PAINT_LEFT_THRESHOLD 0.05 @@ -106,24 +108,51 @@ static gdouble non_gui_incremental; static GimpUnit non_gui_fade_unit; static GimpUnit non_gui_gradient_unit; +static GimpPaintToolClass *parent_class; /* forward function declarations */ -static void paintbrush_motion (PaintCore *, +static void gimp_paintbrush_tool_motion (GimpPaintTool *, GimpDrawable *, PaintPressureOptions *, gdouble , gdouble , PaintApplicationMode , GradientPaintMode ); -static gpointer paintbrush_paint_func (PaintCore *paint_core, +static void gimp_paintbrush_tool_paint_func (GimpPaintTool *paint_core, GimpDrawable *drawable, PaintState state); - +static void gimp_paintbrush_tool_class_init (GimpPaintToolClass *klass); /* functions */ +GtkType +gimp_paintbrush_tool_get_type (void) +{ + static GtkType tool_type = 0; + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpPaintbrushTool", + sizeof (GimpPaintbrushTool), + sizeof (GimpPaintbrushToolClass), + (GtkClassInitFunc) gimp_paintbrush_tool_class_init, + (GtkObjectInitFunc) NULL /*gimp_paintbrush_tool_initialize*/, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + NULL + }; + + tool_type = gtk_type_unique (GIMP_TYPE_PAINT_TOOL, &tool_info); + } + + return tool_type; +} + + static void -paintbrush_gradient_toggle_callback (GtkWidget *widget, +gimp_paintbrush_tool_gradient_toggle_callback (GtkWidget *widget, gpointer data) { PaintbrushOptions *options = paintbrush_options; @@ -147,7 +176,7 @@ paintbrush_gradient_toggle_callback (GtkWidget *widget, } static void -paintbrush_options_reset (void) +gimp_paintbrush_tool_options_reset (void) { PaintbrushOptions *options = paintbrush_options; GtkWidget *spinbutton; @@ -181,12 +210,12 @@ paintbrush_options_reset (void) options->gradient_type = options->gradient_type_d; - gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w), + gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w), options->gradient_type_d); } static PaintbrushOptions * -paintbrush_options_new (void) +gimp_paintbrush_tool_options_new (void) { PaintbrushOptions *options; @@ -199,24 +228,24 @@ paintbrush_options_new (void) /* the new paint tool options structure */ options = g_new (PaintbrushOptions, 1); paint_options_init ((PaintOptions *) options, - PAINTBRUSH, - paintbrush_options_reset); + GIMP_TYPE_PAINTBRUSH_TOOL, + gimp_paintbrush_tool_options_reset); - options->use_fade = + options->use_fade = options->use_fade_d = PAINTBRUSH_DEFAULT_USE_FADE; - options->fade_out = + options->fade_out = options->fade_out_d = PAINTBRUSH_DEFAULT_FADE_OUT; - options->fade_unit = + options->fade_unit = options->fade_unit_d = PAINTBRUSH_DEFAULT_FADE_UNIT; - options->use_gradient = + options->use_gradient = options->use_gradient_d = PAINTBRUSH_DEFAULT_USE_GRADIENT; - options->gradient_length = + options->gradient_length = options->gradient_length_d = PAINTBRUSH_DEFAULT_GRADIENT_LENGTH; - options->gradient_unit = + options->gradient_unit = options->gradient_unit_d = PAINTBRUSH_DEFAULT_GRADIENT_UNIT; - options->gradient_type = + options->gradient_type = options->gradient_type_d = PAINTBRUSH_DEFAULT_GRADIENT_TYPE; - + /* the main vbox */ vbox = ((ToolOptions *) options)->main_vbox; @@ -241,7 +270,7 @@ paintbrush_options_new (void) gtk_widget_show (options->use_fade_w); /* the fade-out sizeentry */ - options->fade_out_w = + options->fade_out_w = gtk_adjustment_new (options->fade_out_d, 1e-5, 32767.0, 1.0, 50.0, 0.0); spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (options->fade_out_w), 1.0, 0.0); gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), GTK_SHADOW_NONE); @@ -254,7 +283,7 @@ paintbrush_options_new (void) gtk_widget_show (spinbutton); /* the fade-out unitmenu */ - options->fade_unit_w = + options->fade_unit_w = gimp_unit_menu_new ("%a", options->fade_unit_d, TRUE, TRUE, TRUE); gtk_signal_connect (GTK_OBJECT (options->fade_unit_w), "unit_changed", GTK_SIGNAL_FUNC (gimp_unit_menu_update), @@ -282,12 +311,12 @@ paintbrush_options_new (void) gtk_check_button_new_with_label (_("Gradient")); gtk_container_add (GTK_CONTAINER (abox), options->use_gradient_w); gtk_signal_connect (GTK_OBJECT (options->use_gradient_w), "toggled", - GTK_SIGNAL_FUNC (paintbrush_gradient_toggle_callback), + GTK_SIGNAL_FUNC (gimp_paintbrush_tool_gradient_toggle_callback), &options->use_gradient); gtk_widget_show (options->use_gradient_w); /* the gradient length scale */ - options->gradient_length_w = + options->gradient_length_w = gtk_adjustment_new (options->gradient_length_d, 1e-5, 32767.0, 1.0, 50.0, 0.0); spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (options->gradient_length_w), 1.0, 0.0); gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), GTK_SHADOW_NONE); @@ -300,7 +329,7 @@ paintbrush_options_new (void) gtk_widget_show (spinbutton); /* the gradient unitmenu */ - options->gradient_unit_w = + options->gradient_unit_w = gimp_unit_menu_new ("%a", options->gradient_unit_d, TRUE, TRUE, TRUE); gtk_signal_connect (GTK_OBJECT (options->gradient_unit_w), "unit_changed", GTK_SIGNAL_FUNC (gimp_unit_menu_update), @@ -361,17 +390,17 @@ paintbrush_options_new (void) #define TIMED_BRUSH 0 -static gpointer -paintbrush_paint_func (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState state) -{ +static void +gimp_paintbrush_tool_paint_func (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + PaintState state) +{ GDisplay *gdisp = gdisplay_active (); double fade_out; double gradient_length; double unit_factor; - - g_return_val_if_fail (gdisp != NULL, NULL); + + g_return_if_fail (gdisp != NULL); #if TIMED_BRUSH static GTimer *timer = NULL; @@ -392,40 +421,40 @@ paintbrush_paint_func (PaintCore *paint_core, fade_out = paintbrush_options->fade_out; break; case GIMP_UNIT_PERCENT: - fade_out = MAX (gdisp->gimage->width, gdisp->gimage->height) * + fade_out = MAX (gdisp->gimage->width, gdisp->gimage->height) * paintbrush_options->fade_out / 100; break; default: unit_factor = gimp_unit_get_factor (paintbrush_options->fade_unit); - fade_out = paintbrush_options->fade_out * + fade_out = paintbrush_options->fade_out * MAX (gdisp->gimage->xresolution, gdisp->gimage->yresolution) / unit_factor; break; } - + switch (paintbrush_options->gradient_unit) { case GIMP_UNIT_PIXEL: gradient_length = paintbrush_options->gradient_length; break; case GIMP_UNIT_PERCENT: - gradient_length = MAX (gdisp->gimage->width, gdisp->gimage->height) * + gradient_length = MAX (gdisp->gimage->width, gdisp->gimage->height) * paintbrush_options->gradient_length / 100; break; default: unit_factor = gimp_unit_get_factor (paintbrush_options->gradient_unit); - gradient_length = paintbrush_options->gradient_length * + gradient_length = paintbrush_options->gradient_length * MAX (gdisp->gimage->xresolution, gdisp->gimage->yresolution) / unit_factor; break; } - - paintbrush_motion (paint_core, drawable, + + gimp_paintbrush_tool_motion (paint_tool, drawable, paintbrush_options->paint_options.pressure_options, - paintbrush_options->use_fade ? fade_out : 0, + paintbrush_options->use_fade ? fade_out : 0, paintbrush_options->use_gradient ? gradient_length : 0, paintbrush_options->paint_options.incremental, paintbrush_options->gradient_type); break; - + case FINISH_PAINT : #if TIMED_BRUSH if (timer) @@ -441,47 +470,45 @@ paintbrush_paint_func (PaintCore *paint_core, default : break; } - - return NULL; } -Tool * -tools_new_paintbrush () +GimpTool * +gimp_paintbrush_tool_new (void) { - Tool * tool; - PaintCore * private; - - /* The tool options */ - if (! paintbrush_options) - { - paintbrush_options = paintbrush_options_new (); - tools_register (PAINTBRUSH, (ToolOptions *) paintbrush_options); - - /* press all default buttons */ - paintbrush_options_reset (); - } - - tool = paint_core_new (PAINTBRUSH); - - private = (PaintCore *) tool->private; - private->paint_func = paintbrush_paint_func; - private->pick_colors = TRUE; - private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - - return tool; + return gtk_type_new (GIMP_TYPE_PAINTBRUSH_TOOL); } - void -tools_free_paintbrush (Tool *tool) +gimp_paintbrush_tool_initialize (GimpPaintTool *tool) { - paint_core_free (tool); + tool->pick_colors = TRUE; + tool->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; } +void +gimp_paintbrush_tool_class_init (GimpPaintToolClass *klass) +{ + parent_class = gtk_type_class (GIMP_TYPE_PAINT_TOOL); + + klass->paint_func = gimp_paintbrush_tool_paint_func; +} + +void +gimp_paintbrush_tool_register (void) +{ + tool_manager_register_tool (GIMP_TYPE_PAINTBRUSH_TOOL, + "gimp:paintbrush_tool", + N_("Paintbrush"), + N_("Paint fuzzy brush strokes"), + N_("/Tools/Paint Tools/Paintbrush"), "P", + NULL, "tools/paintbrush.html", (const gchar **) paint_bits); +} + + static void -paintbrush_motion (PaintCore *paint_core, +gimp_paintbrush_tool_motion (GimpPaintTool *paint_tool, GimpDrawable *drawable, PaintPressureOptions *pressure_options, double fade_out, @@ -507,7 +534,7 @@ paintbrush_motion (PaintCore *paint_core, return; if (pressure_options->size) - scale = paint_core->curpressure; + scale = paint_tool->curpressure; else scale = 1.0; @@ -515,14 +542,14 @@ paintbrush_motion (PaintCore *paint_core, gradient_length = 1.0; /* not really used, only for if cases */ /* Get a region which can be used to paint to */ - if (! (area = paint_core_get_paint_area (paint_core, drawable, scale))) + if (! (area = gimp_paint_tool_get_paint_area (paint_tool, drawable, scale))) return; /* factor in the fade out value */ if (fade_out) { /* Model the amount of paint left as a gaussian curve */ - x = ((double) paint_core->pixel_dist / fade_out); + x = ((double) paint_tool->pixel_dist / fade_out); paint_left = exp (- x * x * 5.541); /* ln (1/255) */ local_blend = (int) (255 * paint_left); } @@ -537,9 +564,9 @@ paintbrush_motion (PaintCore *paint_core, { if (pressure_options->color) gimp_gradient_get_color_at (gimp_context_get_gradient (NULL), - paint_core->curpressure, &color); + paint_tool->curpressure, &color); else - paint_core_get_color_from_gradient (paint_core, gradient_length, + gimp_paint_tool_get_color_from_gradient (paint_tool, gradient_length, &color, mode); temp_blend = (gint) ((color.a * local_blend)); @@ -558,14 +585,14 @@ paintbrush_motion (PaintCore *paint_core, } /* we check to see if this is a pixmap, if so composite the pixmap image into the are instead of the color */ - else if (paint_core->brush && paint_core->brush->pixmap) + else if (paint_tool->brush && paint_tool->brush->pixmap) { - paint_core_color_area_with_pixmap (paint_core, gimage, drawable, - area, + gimp_paint_tool_color_area_with_pixmap (paint_tool, gimage, drawable, + area, scale, SOFT); paint_appl_mode = INCREMENTAL; } - else + else { gimp_image_get_foreground (gimage, drawable, col); col[area->bytes - 1] = OPAQUE_OPACITY; @@ -575,10 +602,10 @@ paintbrush_motion (PaintCore *paint_core, opacity = (gdouble)temp_blend; if (pressure_options->opacity) - opacity = opacity * 2.0 * paint_core->curpressure; + opacity = opacity * 2.0 * paint_tool->curpressure; - paint_core_paste_canvas (paint_core, drawable, - MIN (opacity, 255), + gimp_paint_tool_paste_canvas (paint_tool, drawable, + MIN (opacity, 255), gimp_context_get_opacity (NULL) * 255, gimp_context_get_paint_mode (NULL), pressure_options->pressure ? PRESSURE : SOFT, @@ -588,7 +615,7 @@ paintbrush_motion (PaintCore *paint_core, static gpointer -paintbrush_non_gui_paint_func (PaintCore *paint_core, +gimp_paintbrush_tool_non_gui_paint_func (GimpPaintTool *paint_tool, GimpDrawable *drawable, PaintState state) { @@ -606,44 +633,44 @@ paintbrush_non_gui_paint_func (PaintCore *paint_core, fade_out = non_gui_fade_out; break; case GIMP_UNIT_PERCENT: - fade_out = MAX (gimage->width, gimage->height) * + fade_out = MAX (gimage->width, gimage->height) * non_gui_fade_out / 100; break; default: unit_factor = gimp_unit_get_factor (non_gui_fade_unit); - fade_out = non_gui_fade_out * + fade_out = non_gui_fade_out * MAX (gimage->xresolution, gimage->yresolution) / unit_factor; break; } - + switch (non_gui_gradient_unit) { case GIMP_UNIT_PIXEL: gradient_length = non_gui_gradient_length; break; case GIMP_UNIT_PERCENT: - gradient_length = MAX (gimage->width, gimage->height) * + gradient_length = MAX (gimage->width, gimage->height) * non_gui_gradient_length / 100; break; default: unit_factor = gimp_unit_get_factor (non_gui_gradient_unit); - gradient_length = non_gui_gradient_length * + gradient_length = non_gui_gradient_length * MAX (gimage->xresolution, gimage->yresolution) / unit_factor; break; } - paintbrush_motion (paint_core,drawable, + gimp_paintbrush_tool_motion (paint_tool,drawable, &non_gui_pressure_options, fade_out, gradient_length, - non_gui_incremental, + non_gui_incremental, non_gui_gradient_type); return NULL; } gboolean -paintbrush_non_gui_default (GimpDrawable *drawable, +gimp_paintbrush_tool_non_gui_default (GimpDrawable *drawable, int num_strokes, double *stroke_array) { @@ -676,10 +703,10 @@ paintbrush_non_gui_default (GimpDrawable *drawable, if (use_fade == FALSE) fade_out = 0.0; - /* Hmmm... PDB paintbrush should have gradient type added to it!*/ - /* thats why the code below is duplicated. - */ - if (paint_core_init (&non_gui_paint_core, drawable, + /* Hmmm... PDB paintbrush should have gradient type added to it! + * thats why the code below is duplicated. + */ + if (gimp_paint_tool_start (&non_gui_paint_tool, drawable, stroke_array[0], stroke_array[1])) { non_gui_fade_out = fade_out; @@ -690,31 +717,31 @@ paintbrush_non_gui_default (GimpDrawable *drawable, non_gui_gradient_unit = gradient_unit; /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = paintbrush_non_gui_paint_func; + non_gui_paint_tool_class->paint_func =(PaintFunc) gimp_paintbrush_tool_non_gui_paint_func; - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; + non_gui_paint_tool->startx = non_gui_paint_tool->lastx = stroke_array[0]; + non_gui_paint_tool->starty = non_gui_paint_tool->lasty = stroke_array[1]; - non_gui_paint_core.flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; + non_gui_paint_tool->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; - paintbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0); + gimp_paintbrush_tool_non_gui_paint_func (&non_gui_paint_tool, 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]; + non_gui_paint_tool->curx = stroke_array[i * 2 + 0]; + non_gui_paint_tool->cury = stroke_array[i * 2 + 1]; - paint_core_interpolate (&non_gui_paint_core, drawable); + gimp_paint_tool_interpolate (&non_gui_paint_tool, drawable); - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; + non_gui_paint_tool->lastx = non_gui_paint_tool->curx; + non_gui_paint_tool->lasty = non_gui_paint_tool->cury; } /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); + gimp_paint_tool_finish (&non_gui_paint_tool, drawable); /* Cleanup */ - paint_core_cleanup (); + gimp_paint_tool_cleanup (); return TRUE; } else @@ -722,7 +749,7 @@ paintbrush_non_gui_default (GimpDrawable *drawable, } gboolean -paintbrush_non_gui (GimpDrawable *drawable, +gimp_paintbrush_tool_non_gui (GimpDrawable *drawable, int num_strokes, double *stroke_array, double fade_out, @@ -732,7 +759,7 @@ paintbrush_non_gui (GimpDrawable *drawable, int i; /* Code duplicated above */ - if (paint_core_init (&non_gui_paint_core, drawable, + if (gimp_paint_tool_start (&non_gui_paint_tool, drawable, stroke_array[0], stroke_array[1])) { non_gui_fade_out = fade_out; @@ -741,32 +768,32 @@ paintbrush_non_gui (GimpDrawable *drawable, non_gui_incremental = method; /* Set the paint core's paint func */ - non_gui_paint_core.paint_func = paintbrush_non_gui_paint_func; + non_gui_paint_tool_class->paint_func = gimp_paintbrush_tool_non_gui_paint_func; - non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0]; - non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1]; + non_gui_paint_tool->startx = non_gui_paint_tool->lastx = stroke_array[0]; + non_gui_paint_tool->starty = non_gui_paint_tool->lasty = stroke_array[1]; - non_gui_paint_core.flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; + non_gui_paint_tool->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; if (num_strokes == 1) - paintbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0); + gimp_paintbrush_tool_non_gui_paint_func (&non_gui_paint_tool, 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]; + non_gui_paint_tool->curx = stroke_array[i * 2 + 0]; + non_gui_paint_tool->cury = stroke_array[i * 2 + 1]; - paint_core_interpolate (&non_gui_paint_core, drawable); + gimp_paint_tool_interpolate (&non_gui_paint_tool, drawable); - non_gui_paint_core.lastx = non_gui_paint_core.curx; - non_gui_paint_core.lasty = non_gui_paint_core.cury; + non_gui_paint_tool->lastx = non_gui_paint_tool->curx; + non_gui_paint_tool->lasty = non_gui_paint_tool->cury; } /* Finish the painting */ - paint_core_finish (&non_gui_paint_core, drawable, -1); + gimp_paint_tool_finish (&non_gui_paint_tool, drawable); /* Cleanup */ - paint_core_cleanup (); + gimp_paint_tool_cleanup (); return TRUE; } else diff --git a/app/paint/gimppaintbrush.h b/app/paint/gimppaintbrush.h new file mode 100644 index 0000000000..95b3b20454 --- /dev/null +++ b/app/paint/gimppaintbrush.h @@ -0,0 +1,59 @@ +/* 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 __GIMP_PAINTBRUSH_TOOL_H__ +#define __GIMP_PAINTBRUSH_TOOL_H__ + +#include "gimppainttool.h" + +#define GIMP_TYPE_PAINTBRUSH_TOOL (gimp_paintbrush_tool_get_type ()) +#define GIMP_PAINTBRUSH_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_PAINTBRUSH_TOOL, GimpPaintbrushTool)) +#define GIMP_IS_PAINTBRUSH_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_PAINTBRUSH_TOOL)) +#define GIMP_PAINTBRUSH_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PAINTBRUSH_TOOL, GimpPaintbrushToolClass)) +#define GIMP_IS_PAINTBRUSH_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PAINTBRUSH_TOOL)) + +struct _GimpPaintbrushTool +{ + GimpPaintTool parent_instance; +}; + +struct _GimpPaintbrushToolClass +{ + GimpPaintToolClass parent_class; +}; + +typedef struct _GimpPaintbrushTool GimpPaintbrushTool; +typedef struct _GimpPaintbrushToolClass GimpPaintbrushToolClass; + +/* FIXME: this antique code doesn't follow the coding style */ + +gboolean gimp_paintbrush_tool_non_gui (GimpDrawable *, + gint , + gdouble *, + gdouble , + gint , + gdouble ); +gboolean gimp_paintbrush_tool_non_gui_default (GimpDrawable *, + gint , + gdouble *); + +GimpTool * gimp_paintbrush_tool_new (void); + +GtkType gimp_paintbrush_tool_get_type (void); + +#endif /* __GIMP_PAINTBRUSH_TOOL_H__ */ diff --git a/app/tools/paint_core.c b/app/paint/gimppaintcore.c similarity index 65% rename from app/tools/paint_core.c rename to app/paint/gimppaintcore.c index 23973695ce..02a021b311 100644 --- a/app/tools/paint_core.c +++ b/app/paint/gimppaintcore.c @@ -31,7 +31,7 @@ #include "brush_scale.h" #include "cursorutil.h" #include "devices.h" -#include "draw_core.h" +#include "gimpdrawtool.h" #include "drawable.h" #include "gdisplay.h" #include "gimage_mask.h" @@ -41,7 +41,7 @@ #include "gimpimage.h" #include "gimprc.h" #include "paint_funcs.h" -#include "paint_core.h" +#include "gimppainttool.h" #include "pixel_region.h" #include "selection.h" #include "temp_buf.h" @@ -52,7 +52,7 @@ #include "libgimp/gimpintl.h" -#include "paint_core_kernels.h" +#include "gimppainttool_kernels.h" /* target size */ @@ -64,52 +64,53 @@ #define STATUSBAR_SIZE 128 /* global variables--for use in the various paint tools */ -PaintCore non_gui_paint_core; +GimpPaintTool *non_gui_painting_tool; +GimpPaintToolClass *non_gui_painting_tool_class; /* local function prototypes */ -static void paint_core_calculate_brush_size (MaskBuf *mask, +static void gimp_paint_tool_calculate_brush_size (MaskBuf *mask, gdouble scale, gint *width, gint *height); -static MaskBuf * paint_core_subsample_mask (MaskBuf *mask, - gdouble x, +static MaskBuf * gimp_paint_tool_subsample_mask (MaskBuf *mask, + gdouble x, gdouble y); -static MaskBuf * paint_core_pressurize_mask (MaskBuf *brush_mask, - gdouble x, - gdouble y, +static MaskBuf * gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask, + gdouble x, + gdouble y, gdouble pressure); -static MaskBuf * paint_core_solidify_mask (MaskBuf *brush_mask); -static MaskBuf * paint_core_scale_mask (MaskBuf *brush_mask, +static MaskBuf * gimp_paint_tool_solidify_mask (MaskBuf *brush_mask); +static MaskBuf * gimp_paint_tool_scale_mask (MaskBuf *brush_mask, gdouble scale); -static MaskBuf * paint_core_scale_pixmap (MaskBuf *brush_mask, +static MaskBuf * gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask, gdouble scale); -static MaskBuf * paint_core_get_brush_mask (PaintCore *paint_core, +static MaskBuf * gimp_paint_tool_get_brush_mask (GimpPaintTool *gimp_paint_tool, BrushApplicationMode brush_hardness, gdouble scale); -static void paint_core_paste (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - LayerModeEffects paint_mode, +static void gimp_paint_tool_paste (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, PaintApplicationMode mode); -static void paint_core_replace (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, +static void gimp_paint_tool_replace (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, PaintApplicationMode mode); -static void brush_to_canvas_tiles (PaintCore *paint_core, - MaskBuf *brush_mask, - gint brush_opacity); -static void brush_to_canvas_buf (PaintCore *paint_core, +static void brush_to_canvas_tiles (GimpPaintTool *gimp_paint_tool, MaskBuf *brush_mask, gint brush_opacity); -static void canvas_tiles_to_canvas_buf (PaintCore *paint_core); +static void brush_to_canvas_buf (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + gint brush_opacity); +static void canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool); -static void set_undo_tiles (GimpDrawable *drawable, +static void set_undo_tiles (GimpDrawable *drawable, gint x, gint y, gint w, @@ -118,7 +119,7 @@ static void set_canvas_tiles (gint x, gint y, gint w, gint h); -static void paint_core_invalidate_cache (GimpBrush *brush, +static void gimp_paint_tool_invalidate_cache (GimpBrush *brush, gpointer data); @@ -163,19 +164,66 @@ static MaskBuf *kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1]; static MaskBuf *last_brush_mask = NULL; static gboolean cache_invalid = FALSE; +static void gimp_paint_tool_initialize (GimpPaintTool *); +static void gimp_paint_tool_class_init (GimpToolClass *); + +enum { /* signals */ + PAINT, + LAST_SIGNAL +}; + +static guint gimp_paint_tool_signals[LAST_SIGNAL] = { 0 }; + +static void standard_paint_func (GimpPaintTool *tool) +{ +} + +GtkType +gimp_paint_tool_get_type (void) +{ + static GtkType tool_type = 0; + + g_message ("sizeof GimpPaintTool = %i, GimpPaintToolClass = %i", sizeof(GimpPaintTool), sizeof (GimpPaintToolClass)); + g_message ("sizeof GimpDrawTool = %i, GimpDrawToolClass = %i", sizeof(GimpDrawTool), sizeof (GimpDrawToolClass)); + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpPaintTool", + sizeof (GimpPaintTool), + sizeof (GimpPaintToolClass), + (GtkClassInitFunc) gimp_paint_tool_class_init, + (GtkObjectInitFunc) gimp_paint_tool_initialize, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + NULL + }; + + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); + } + + return tool_type; +} + +GimpPaintTool * +gimp_paint_tool_new (void) +{ + return gtk_type_new (GIMP_TYPE_PAINT_TOOL); +} /***********************************************************************/ static void -paint_core_sample_color (GimpDrawable *drawable, - gint x, - gint y, +gimp_paint_tool_sample_color (GimpDrawable *drawable, + gint x, + gint y, gint state) { GimpRGB color; guchar *col; - if( x >= 0 && x < gimp_drawable_width (drawable) && + if( x >= 0 && x < gimp_drawable_width (drawable) && y >= 0 && y < gimp_drawable_height (drawable)) { if ((col = gimp_drawable_get_color_at (drawable, x, y))) @@ -198,43 +246,43 @@ paint_core_sample_color (GimpDrawable *drawable, void -paint_core_button_press (GimpTool *tool, - GdkEventButton *bevent, - GDisplay *gdisp) +gimp_paint_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) { - PaintCore *paint_core; - GimpBrush *current_brush; - gboolean draw_line; - gdouble x, y; - GimpDrawable *drawable; - - paint_core = tool->paint_core; + GimpPaintTool *paint_tool; + GimpBrush *current_brush; + gboolean draw_line; + gdouble x, y; + GimpDrawable *drawable; g_return_if_fail (gdisp != NULL); - g_return_if_fail (paint_core != NULL); + g_return_if_fail (tool != NULL); + + paint_tool = GIMP_PAINT_TOOL(tool); gdisplay_untransform_coords_f (gdisp, (double) bevent->x, (double) bevent->y, &x, &y, TRUE); drawable = gimp_image_active_drawable (gdisp->gimage); - if (! paint_core_init (paint_core, drawable, x, y)) + if (! gimp_paint_tool_start (paint_tool, drawable, x, y)) return; draw_line = FALSE; - paint_core->curpressure = bevent->pressure; - paint_core->curxtilt = bevent->xtilt; - paint_core->curytilt = bevent->ytilt; + paint_tool->curpressure = bevent->pressure; + paint_tool->curxtilt = bevent->xtilt; + paint_tool->curytilt = bevent->ytilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = bevent->wheel; -#endif /* GTK_HAVE_SIX_VALUATORS */ - paint_core->state = bevent->state; + paint_tool->curwheel = bevent->wheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + paint_tool->state = bevent->state; if (gdisp != tool->gdisp || - paint_core->context_id < 1) + paint_tool->context_id < 1) { /* initialize the statusbar display */ - paint_core->context_id = + paint_tool->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); } @@ -242,13 +290,13 @@ paint_core_button_press (GimpTool *tool, if ((gdisp != tool->gdisp) || ! (bevent->state & GDK_SHIFT_MASK)) { /* initialize some values */ - paint_core->startx = paint_core->lastx = paint_core->curx = x; - paint_core->starty = paint_core->lasty = paint_core->cury = y; - paint_core->startpressure = paint_core->lastpressure = paint_core->curpressure; - paint_core->startytilt = paint_core->lastytilt = paint_core->curytilt; - paint_core->startxtilt = paint_core->lastxtilt = paint_core->curxtilt; + paint_tool->startx = paint_tool->lastx = paint_tool->curx = x; + paint_tool->starty = paint_tool->lasty = paint_tool->cury = y; + paint_tool->startpressure = paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->startytilt = paint_tool->lastytilt = paint_tool->curytilt; + paint_tool->startxtilt = paint_tool->lastxtilt = paint_tool->curxtilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->startwheel = paint_core->lastwheel = paint_core->curwheel; + paint_tool->startwheel = paint_tool->lastwheel = paint_tool->curwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ } @@ -258,13 +306,13 @@ paint_core_button_press (GimpTool *tool, else if (bevent->state & GDK_SHIFT_MASK) { draw_line = TRUE; - paint_core->startx = paint_core->lastx; - paint_core->starty = paint_core->lasty; - paint_core->startpressure = paint_core->lastpressure; - paint_core->startxtilt = paint_core->lastxtilt; - paint_core->startytilt = paint_core->lastytilt; + paint_tool->startx = paint_tool->lastx; + paint_tool->starty = paint_tool->lasty; + paint_tool->startpressure = paint_tool->lastpressure; + paint_tool->startxtilt = paint_tool->lastxtilt; + paint_tool->startytilt = paint_tool->lastytilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->startwheel = paint_core->lastwheel; + paint_tool->startwheel = paint_tool->lastwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ /* Restrict to multiples of 15 degrees if ctrl is pressed */ @@ -274,8 +322,8 @@ paint_core_button_press (GimpTool *tool, gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; gint dx, dy, i, radius, frac; - dx = paint_core->curx - paint_core->lastx; - dy = paint_core->cury - paint_core->lasty; + dx = paint_tool->curx - paint_tool->lastx; + dy = paint_tool->cury - paint_tool->lasty; if (dy) { @@ -284,13 +332,13 @@ paint_core_button_press (GimpTool *tool, for (i = 0; i < 6; i++) { if (frac < tangens2[i]) - break; + break; } dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); } - paint_core->curx = paint_core->lastx + dx; - paint_core->cury = paint_core->lasty + dy; + paint_tool->curx = paint_tool->lastx + dx; + paint_tool->cury = paint_tool->lasty + dy; } } @@ -315,35 +363,35 @@ paint_core_button_press (GimpTool *tool, NULL, NULL, bevent->time); /* Let the specific painting function initialize itself */ - (* paint_core->paint_func) (paint_core, drawable, INIT_PAINT); + gimp_paint_tool_paint(paint_tool, drawable, INIT_PAINT); - if (paint_core->pick_colors - && !(bevent->state & GDK_SHIFT_MASK) + if (paint_tool->pick_colors + && !(bevent->state & GDK_SHIFT_MASK) && (bevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) { - paint_core_sample_color (drawable, x, y, bevent->state); - paint_core->pick_state = TRUE; + gimp_paint_tool_sample_color (drawable, x, y, bevent->state); + paint_tool->pick_state = TRUE; return; } else - paint_core->pick_state = FALSE; + paint_tool->pick_state = FALSE; /* store the current brush pointer */ - current_brush = paint_core->brush; + current_brush = paint_tool->brush; /* Paint to the image */ if (draw_line) { - draw_core_pause (paint_core->core, tool); - paint_core_interpolate (paint_core, drawable); + gimp_draw_tool_pause (GIMP_DRAW_TOOL(paint_tool)); + gimp_paint_tool_interpolate (paint_tool, drawable); - paint_core->lastx = paint_core->curx; - paint_core->lasty = paint_core->cury; - paint_core->lastpressure = paint_core->curpressure; - paint_core->lastxtilt = paint_core->curxtilt; - paint_core->lastytilt = paint_core->curytilt; + paint_tool->lastx = paint_tool->curx; + paint_tool->lasty = paint_tool->cury; + paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->lastxtilt = paint_tool->curxtilt; + paint_tool->lastytilt = paint_tool->curytilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->lastwheel = paint_core->curwheel; + paint_tool->lastwheel = paint_tool->curwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ } else @@ -353,42 +401,42 @@ paint_core_button_press (GimpTool *tool, * pixmap brush pipes don't, as they don't know which * pixmap to select.) */ - if (paint_core->lastx != paint_core->curx - || paint_core->lasty != paint_core->cury - || (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_core->brush) - ->klass)->want_null_motion) (paint_core)) + if (paint_tool->lastx != paint_tool->curx + || paint_tool->lasty != paint_tool->cury + || (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->want_null_motion) (paint_tool)) { - if (paint_core->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) - paint_core->brush = - (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_core->brush) - ->klass)->select_brush) (paint_core); + if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) + paint_tool->brush = + (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->select_brush) (paint_tool); - (* paint_core->paint_func) (paint_core, drawable, MOTION_PAINT); + gimp_paint_tool_paint(paint_tool, drawable, MOTION_PAINT); } } - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, drawable, PRETRACE_PAINT); + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, drawable, PRETRACE_PAINT); gdisplay_flush_now (gdisp); - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, drawable, POSTTRACE_PAINT); + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, drawable, POSTTRACE_PAINT); /* restore the current brush pointer */ - paint_core->brush = current_brush; + paint_tool->brush = current_brush; } void -paint_core_button_release (GimpTool *tool, +gimp_paint_tool_button_release (GimpTool *tool, GdkEventButton *bevent, GDisplay *gdisp) { GImage *gimage; - PaintCore *paint_core; + GimpPaintTool *paint_tool; gimage = gdisp->gimage; - paint_core = tool->paint_core; + paint_tool = GIMP_PAINT_TOOL(tool); /* resume the current selection and ungrab the pointer */ gdisplays_selection_visibility (gdisp->gimage, SelectionResume); @@ -397,120 +445,123 @@ paint_core_button_release (GimpTool *tool, gdk_flush (); /* Let the specific painting function finish up */ - (* paint_core->paint_func) (paint_core, - gimp_image_active_drawable (gdisp->gimage), + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), FINISH_PAINT); /* Set tool state to inactive -- no longer painting */ - draw_core_stop (paint_core->core, tool); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(paint_tool)); tool->state = INACTIVE; - paint_core->pick_state = FALSE; + paint_tool->pick_state = FALSE; - paint_core_finish (paint_core, gimp_image_active_drawable (gdisp->gimage), - tool->ID); + gimp_paint_tool_finish (paint_tool, gimp_image_active_drawable (gdisp->gimage)); gdisplays_flush (); } void -paint_core_motion (GimpTool *tool, +gimp_paint_tool_motion (GimpTool *tool, GdkEventMotion *mevent, GDisplay *gdisp) { - PaintCore *paint_core; + GimpPaintTool *paint_tool; - paint_core = tool->paint_core; + paint_tool = GIMP_PAINT_TOOL(tool); gdisplay_untransform_coords_f (gdisp, (double) mevent->x, (double) mevent->y, - &paint_core->curx, &paint_core->cury, TRUE); + &paint_tool->curx, &paint_tool->cury, TRUE); - if (paint_core->pick_state) + if (paint_tool->pick_state) { - paint_core_sample_color (gimp_image_active_drawable (gdisp->gimage), - paint_core->curx, paint_core->cury, + gimp_paint_tool_sample_color (gimp_image_active_drawable (gdisp->gimage), + paint_tool->curx, paint_tool->cury, mevent->state); return; } - paint_core->curpressure = mevent->pressure; - paint_core->curxtilt = mevent->xtilt; - paint_core->curytilt = mevent->ytilt; + paint_tool->curpressure = mevent->pressure; + paint_tool->curxtilt = mevent->xtilt; + paint_tool->curytilt = mevent->ytilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = mevent->wheel; + paint_tool->curwheel = mevent->wheel; #endif /* GTK_HAVE_SIX_VALUATORS */ - paint_core->state = mevent->state; + paint_tool->state = mevent->state; - paint_core_interpolate (paint_core, + gimp_paint_tool_interpolate (paint_tool, gimp_image_active_drawable (gdisp->gimage)); - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, - gimp_image_active_drawable (gdisp->gimage), + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), PRETRACE_PAINT); gdisplay_flush_now (gdisp); - if (paint_core->flags & TOOL_TRACES_ON_WINDOW) - (* paint_core->paint_func) (paint_core, - gimp_image_active_drawable (gdisp->gimage), + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), POSTTRACE_PAINT); - paint_core->lastx = paint_core->curx; - paint_core->lasty = paint_core->cury; - paint_core->lastpressure = paint_core->curpressure; - paint_core->lastxtilt = paint_core->curxtilt; - paint_core->lastytilt = paint_core->curytilt; + paint_tool->lastx = paint_tool->curx; + paint_tool->lasty = paint_tool->cury; + paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->lastxtilt = paint_tool->curxtilt; + paint_tool->lastytilt = paint_tool->curytilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->lastwheel = paint_core->curwheel; + paint_tool->lastwheel = paint_tool->curwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ } + +/* FIXME: this belongs in the individual tools */ void -paint_core_cursor_update (Tool *tool, - GdkEventMotion *mevent, - GDisplay *gdisp) +gimp_paint_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) { - GimpLayer *layer; - PaintCore *paint_core; - gint x, y; - gchar status_str[STATUSBAR_SIZE]; + GimpLayer *layer; + GimpPaintTool *paint_tool; + GimpDrawTool *draw_tool; + gint x, y; + gchar status_str[STATUSBAR_SIZE]; - GdkCursorType ctype = GDK_TOP_LEFT_ARROW; + GdkCursorType ctype = GDK_TOP_LEFT_ARROW; GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE; - gboolean ctoggle = FALSE; + gboolean ctoggle = FALSE; - paint_core = tool->paint_core; + paint_tool = GIMP_PAINT_TOOL(tool); + draw_tool = GIMP_DRAW_TOOL(tool); - /* undraw the current tool */ - draw_core_pause (paint_core->core, tool); +/* undraw the current tool */ + gimp_draw_tool_pause (draw_tool); - if (gdisp != tool->gdisp || paint_core->context_id < 1) + if (gdisp != tool->gdisp || paint_tool->context_id < 1) { /* initialize the statusbar display */ - paint_core->context_id = + paint_tool->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); } - if (paint_core->context_id) - gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), paint_core->context_id); + if (paint_tool->context_id) + gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), paint_tool->context_id); if ((layer = gimp_image_get_active_layer (gdisp->gimage))) { /* If shift is down and this is not the first paint stroke, draw a line */ if (gdisp == tool->gdisp && (mevent->state & GDK_SHIFT_MASK)) - { + { gdouble dx, dy, d; ctype = GDK_PENCIL; - /* Get the current coordinates */ + /* Get the current coordinates */ gdisplay_untransform_coords_f (gdisp, (double) mevent->x, (double) mevent->y, - &paint_core->curx, - &paint_core->cury, TRUE); + &paint_tool->curx, + &paint_tool->cury, TRUE); - dx = paint_core->curx - paint_core->lastx; - dy = paint_core->cury - paint_core->lasty; + dx = paint_tool->curx - paint_tool->lastx; + dy = paint_tool->cury - paint_tool->lasty; /* Restrict to multiples of 15 degrees if ctrl is pressed */ if (mevent->state & GDK_CONTROL_MASK) @@ -528,14 +579,14 @@ paint_core_cursor_update (Tool *tool, for (i = 0; i < 6; i++) { if (frac < tangens2[i]) - break; + break; } dx = idx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); dy = idy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); } - paint_core->curx = paint_core->lastx + dx; - paint_core->cury = paint_core->lasty + dy; + paint_tool->curx = paint_tool->lastx + dx; + paint_tool->cury = paint_tool->lasty + dy; } /* show distance in statusbar */ @@ -550,7 +601,7 @@ paint_core_cursor_update (Tool *tool, g_strdup_printf ("%%.%df %s", gimp_unit_get_digits (gdisp->gimage->unit), gimp_unit_get_symbol (gdisp->gimage->unit)); - d = (gimp_unit_get_factor (gdisp->gimage->unit) * + d = (gimp_unit_get_factor (gdisp->gimage->unit) * sqrt (SQR (dx / gdisp->gimage->xresolution) + SQR (dy / gdisp->gimage->yresolution))); @@ -559,26 +610,28 @@ paint_core_cursor_update (Tool *tool, } gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), - paint_core->context_id, status_str); + paint_tool->context_id, status_str); - if (paint_core->core->gc == NULL) + if (draw_tool->gc == NULL) { - draw_core_start (paint_core->core, gdisp->canvas->window, tool); + gimp_draw_tool_start (draw_tool, gdisp->canvas->window); } else { /* is this a bad hack ? */ - paint_core->core->paused_count = 0; - draw_core_resume (paint_core->core, tool); + draw_tool->paused_count = 0; + gimp_draw_tool_resume (draw_tool); } - } - /* If Ctrl or Mod1 is pressed, pick colors */ - else if (paint_core->pick_colors && + } + /* If Ctrl or Mod1 is pressed, pick colors */ + else if (paint_tool->pick_colors && !(mevent->state & GDK_SHIFT_MASK) && (mevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) { ctype = GIMP_COLOR_PICKER_CURSOR; } +#warning this doesnt belong here +#if 0 /* Set toggle cursors for various paint tools */ else if (tool->toggled) { @@ -586,11 +639,11 @@ paint_core_cursor_update (Tool *tool, { case ERASER: ctype = GIMP_MOUSE_CURSOR; - cmodifier = GIMP_CURSOR_MODIFIER_MINUS; + cmodifier = CURSOR_MODIFIER_MINUS; break; case CONVOLVE: ctype = GIMP_MOUSE_CURSOR; - cmodifier = GIMP_CURSOR_MODIFIER_MINUS; + cmodifier = CURSOR_MODIFIER_MINUS; break; case DODGEBURN: ctype = GIMP_MOUSE_CURSOR; @@ -601,8 +654,9 @@ paint_core_cursor_update (Tool *tool, break; } } +#endif /* Normal operation -- no modifier pressed or first stroke */ - else + else { gint off_x, off_y; @@ -610,7 +664,7 @@ paint_core_cursor_update (Tool *tool, gdisplay_untransform_coords (gdisp, (double) mevent->x, (double) mevent->y, &x, &y, TRUE, FALSE); - + if (x >= off_x && y >= off_y && x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) @@ -625,25 +679,24 @@ paint_core_cursor_update (Tool *tool, } } - gdisplay_install_tool_cursor (gdisp, - ctype, + /* FIXME: install correct cursor */ + /*gdisplay_install_tool_cursor (gdisp, ctype, ctype == GIMP_COLOR_PICKER_CURSOR ? - GIMP_COLOR_PICKER_CURSOR : - ctoggle ? - tool->toggle_cursor : tool->tool_cursor, - cmodifier); + COLOR_PICKER : tool->type, + cmodifier, + ctoggle); */ } } void -paint_core_control (GimpTool *tool, +gimp_paint_tool_control (GimpTool *tool, ToolAction action, GDisplay *gdisp) { - PaintCore *paint_core; + GimpPaintTool *paint_tool; GimpDrawable *drawable; - paint_core = (PaintCore *) tool->paint_core; + paint_tool = GIMP_PAINT_TOOL (tool); drawable = gimp_image_active_drawable (gdisp->gimage); switch (action) @@ -655,9 +708,9 @@ paint_core_control (GimpTool *tool, break; case HALT: - (* paint_core->paint_func) (paint_core, drawable, FINISH_PAINT); - draw_core_stop (paint_core->core, tool); - paint_core_cleanup (); + gimp_paint_tool_paint(paint_tool, drawable, FINISH_PAINT); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(tool)); + gimp_paint_tool_cleanup (); break; default: @@ -666,23 +719,26 @@ paint_core_control (GimpTool *tool, } void -paint_core_draw (GimpTool *tool) +gimp_paint_tool_draw (GimpTool *tool) { GDisplay *gdisp; - PaintCore *paint_core; + GimpPaintTool *paint_tool; + GimpDrawTool *draw_tool; gint tx1, ty1, tx2, ty2; - paint_core = tool->paint_core; - /* if shift was never used, paint_core->core->gc is NULL + paint_tool = GIMP_PAINT_TOOL(tool); + draw_tool = GIMP_DRAW_TOOL(tool); + + /* if shift was never used, draw_tool->gc is NULL and we don't care about a redraw */ - if (paint_core->core->gc != NULL) + if (draw_tool->gc != NULL) { gdisp = tool->gdisp; - gdisplay_transform_coords (gdisp, paint_core->lastx, paint_core->lasty, + gdisplay_transform_coords (gdisp, paint_tool->lastx, paint_tool->lasty, &tx1, &ty1, 1); - gdisplay_transform_coords (gdisp, paint_core->curx, paint_core->cury, + gdisplay_transform_coords (gdisp, paint_tool->curx, paint_tool->cury, &tx2, &ty2, 1); /* Only draw line if it's in the visible area @@ -702,95 +758,110 @@ paint_core_draw (GimpTool *tool) ty2 += offy; /* Draw start target */ - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, tx1 - (TARGET_WIDTH >> 1), ty1, tx1 + (TARGET_WIDTH >> 1), ty1); - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, tx1, ty1 - (TARGET_HEIGHT >> 1), tx1, ty1 + (TARGET_HEIGHT >> 1)); /* Draw end target */ - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, tx2 - (TARGET_WIDTH >> 1), ty2, tx2 + (TARGET_WIDTH >> 1), ty2); - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, tx2, ty2 - (TARGET_HEIGHT >> 1), tx2, ty2 + (TARGET_HEIGHT >> 1)); /* Draw the line between the start and end coords */ - gdk_draw_line (gdisp->canvas->window, paint_core->core->gc, + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, tx1, ty1, tx2, ty2); } } return; -} +} -Tool * -paint_core_new (GimpToolClas *type) +static void +gimp_paint_tool_initialize (GimpPaintTool *tool) { - GimpTool *tool; - PaintCore *private; + tool->pick_colors = FALSE; + tool->flags = 0; + tool->context_id = 0; +} - tool = tools_new_tool (type); - private = g_new0 (PaintCore, 1); +static void +gimp_paint_tool_class_init (GimpToolClass *klass) +{ + GtkObjectClass * oc = GTK_OBJECT_CLASS (klass); + GimpPaintToolClass * pc = GIMP_PAINT_TOOL_CLASS (klass); - private->core = draw_core_new (paint_core_draw); + g_message ("gimp_paint_tool_class_init"); - private->pick_colors = FALSE; - private->flags = 0; - private->context_id = 0; + klass->button_press = gimp_paint_tool_button_press; + klass->button_release = gimp_paint_tool_button_release; + klass->motion = gimp_paint_tool_motion; + klass->cursor_update = gimp_paint_tool_cursor_update; + klass->control = gimp_paint_tool_control; - tool->private = (void *) private; - tool->button_press_func = paint_core_button_press; - tool->button_release_func = paint_core_button_release; - tool->motion_func = paint_core_motion; - tool->cursor_update_func = paint_core_cursor_update; - tool->control_func = paint_core_control; + gimp_paint_tool_signals[PAINT] = + gtk_signal_new ("paint", + GTK_RUN_FIRST, + oc->type, + GTK_SIGNAL_OFFSET (GimpPaintToolClass, + paint_func), + gtk_marshal_NONE__POINTER_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_INT); + + gtk_object_class_add_signals (oc, gimp_paint_tool_signals, LAST_SIGNAL); + + pc->paint_func = (PaintFunc) standard_paint_func; - return tool; } void -paint_core_free (GimpTool *tool) +gimp_paint_tool_paint (GimpPaintTool *tool, GimpDrawable *drawable, PaintState state) { - PaintCore * paint_core; + gtk_signal_emit (GTK_OBJECT(tool), gimp_paint_tool_signals[PAINT], drawable, state); +} - paint_core = (PaintCore *) tool->paint_core; +void +gimp_paint_tool_destroy (GimpTool *tool) +{ + GimpPaintTool * paint_tool; + GimpDrawTool * draw_tool; + + + paint_tool = GIMP_PAINT_TOOL (tool); + draw_tool = GIMP_DRAW_TOOL (tool); /* Make sure the selection core is not visible */ - if (tool->state == ACTIVE && paint_core->core) - draw_core_stop (paint_core->core, tool); - - /* Free the selection core */ - if (paint_core->core) - draw_core_free (paint_core->core); + if (tool->state == ACTIVE) + gimp_draw_tool_stop (draw_tool); /* Cleanup memory */ - paint_core_cleanup (); - - /* Free the paint core */ - g_free (paint_core); + gimp_paint_tool_cleanup (); } gboolean -paint_core_init (PaintCore *paint_core, - GimpDrawable *drawable, - gdouble x, +gimp_paint_tool_start (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gdouble x, gdouble y) { static GimpBrush *brush = NULL; - - paint_core->curx = x; - paint_core->cury = y; + + paint_tool->curx = x; + paint_tool->cury = y; /* Set up some defaults for non-gui use */ - if (paint_core == &non_gui_paint_core) + if (paint_tool == &non_gui_paint_tool) { - paint_core->startpressure = paint_core->lastpressure = paint_core->curpressure = 0.5; - paint_core->startxtilt = paint_core->lastxtilt = paint_core->curxtilt = 0; - paint_core->startytilt = paint_core->lastytilt = paint_core->curytilt = 0; + paint_tool->startpressure = paint_tool->lastpressure = paint_tool->curpressure = 0.5; + paint_tool->startxtilt = paint_tool->lastxtilt = paint_tool->curxtilt = 0; + paint_tool->startytilt = paint_tool->lastytilt = paint_tool->curytilt = 0; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->startwheel = paint_core->lastwheel = paint_core->curwheel = 0.5; + paint_tool->startwheel = paint_tool->lastwheel = paint_tool->curwheel = 0.5; #endif /* GTK_HAVE_SIX_VALUATORS */ } @@ -798,7 +869,7 @@ paint_core_init (PaintCore *paint_core, if (brush && brush != gimp_context_get_brush (NULL)) { gtk_signal_disconnect_by_func (GTK_OBJECT (brush), - GTK_SIGNAL_FUNC (paint_core_invalidate_cache), + GTK_SIGNAL_FUNC (gimp_paint_tool_invalidate_cache), NULL); gtk_object_unref (GTK_OBJECT (brush)); } @@ -810,12 +881,12 @@ paint_core_init (PaintCore *paint_core, gtk_object_ref (GTK_OBJECT (brush)); gtk_signal_connect (GTK_OBJECT (brush), "invalidate_preview", - GTK_SIGNAL_FUNC (paint_core_invalidate_cache), + GTK_SIGNAL_FUNC (gimp_paint_tool_invalidate_cache), NULL); - paint_core->spacing = (double) gimp_brush_get_spacing (brush) / 100.0; + paint_tool->spacing = (double) gimp_brush_get_spacing (brush) / 100.0; - paint_core->brush = brush; + paint_tool->brush = brush; /* free the block structures */ if (undo_tiles) @@ -833,16 +904,16 @@ paint_core_init (PaintCore *paint_core, gimp_drawable_height (drawable), 1); /* Get the initial undo extents */ - paint_core->x1 = paint_core->x2 = paint_core->curx; - paint_core->y1 = paint_core->y2 = paint_core->cury; - paint_core->distance = 0.0; - paint_core->pixel_dist = 0.0; + paint_tool->x1 = paint_tool->x2 = paint_tool->curx; + paint_tool->y1 = paint_tool->y2 = paint_tool->cury; + paint_tool->distance = 0.0; + paint_tool->pixel_dist = 0.0; return TRUE; } void -paint_core_interpolate (PaintCore *paint_core, +gimp_paint_tool_interpolate (GimpPaintTool *paint_tool, GimpDrawable *drawable) { GimpBrush *current_brush; @@ -864,13 +935,13 @@ paint_core_interpolate (PaintCore *paint_core, gdouble xd, yd; gdouble mag; - delta.x = paint_core->curx - paint_core->lastx; - delta.y = paint_core->cury - paint_core->lasty; - dpressure = paint_core->curpressure - paint_core->lastpressure; - dxtilt = paint_core->curxtilt - paint_core->lastxtilt; - dytilt = paint_core->curytilt - paint_core->lastytilt; + delta.x = paint_tool->curx - paint_tool->lastx; + delta.y = paint_tool->cury - paint_tool->lasty; + dpressure = paint_tool->curpressure - paint_tool->lastpressure; + dxtilt = paint_tool->curxtilt - paint_tool->lastxtilt; + dytilt = paint_tool->curytilt - paint_tool->lastytilt; #ifdef GTK_HAVE_SIX_VALUATORS - dwheel = paint_core->curwheel - paint_core->lastwheel; + dwheel = paint_tool->curwheel - paint_tool->lastwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ /* return if there has been no motion */ @@ -882,77 +953,76 @@ paint_core_interpolate (PaintCore *paint_core, return; /* calculate the distance traveled in the coordinate space of the brush */ - mag = gimp_vector2_length (&(paint_core->brush->x_axis)); + mag = gimp_vector2_length (&(paint_tool->brush->x_axis)); xd = gimp_vector2_inner_product (&delta, - &(paint_core->brush->x_axis)) / (mag*mag); + &(paint_tool->brush->x_axis)) / (mag*mag); - mag = gimp_vector2_length (&(paint_core->brush->y_axis)); + mag = gimp_vector2_length (&(paint_tool->brush->y_axis)); yd = gimp_vector2_inner_product (&delta, - &(paint_core->brush->y_axis)) / (mag*mag); + &(paint_tool->brush->y_axis)) / (mag*mag); - dist = 0.5 * sqrt (xd*xd + yd*yd); - total = dist + paint_core->distance; - initial = paint_core->distance; + dist = 0.5 * sqrt (xd*xd + yd*yd); + total = dist + paint_tool->distance; + initial = paint_tool->distance; pixel_dist = gimp_vector2_length (&delta); - pixel_initial = paint_core->pixel_dist; + pixel_initial = paint_tool->pixel_dist; /* FIXME: need to adapt the spacing to the size */ - /* lastscale = MIN (paint_core->lastpressure, 1/256); */ - /* curscale = MIN (paint_core->curpressure, 1/256); */ - /* spacing = paint_core->spacing * sqrt (0.5 * (lastscale + curscale)); */ + /* lastscale = MIN (gimp_paint_tool->lastpressure, 1/256); */ + /* curscale = MIN (gimp_paint_tool->curpressure, 1/256); */ + /* spacing = gimp_paint_tool->spacing * sqrt (0.5 * (lastscale + curscale)); */ - while (paint_core->distance < total) + while (paint_tool->distance < total) { - n = (gint) (paint_core->distance / paint_core->spacing + 1.0 + EPSILON); - left = n * paint_core->spacing - paint_core->distance; + n = (gint) (paint_tool->distance / paint_tool->spacing + 1.0 + EPSILON); + left = n * paint_tool->spacing - paint_tool->distance; - paint_core->distance += left; + paint_tool->distance += left; - if (paint_core->distance <= (total+EPSILON)) + if (paint_tool->distance <= (total+EPSILON)) { - t = (paint_core->distance - initial) / dist; + t = (paint_tool->distance - initial) / dist; - paint_core->curx = paint_core->lastx + delta.x * t; - paint_core->cury = paint_core->lasty + delta.y * t; - paint_core->pixel_dist = pixel_initial + pixel_dist * t; - paint_core->curpressure = paint_core->lastpressure + dpressure * t; - paint_core->curxtilt = paint_core->lastxtilt + dxtilt * t; - paint_core->curytilt = paint_core->lastytilt + dytilt * t; + paint_tool->curx = paint_tool->lastx + delta.x * t; + paint_tool->cury = paint_tool->lasty + delta.y * t; + paint_tool->pixel_dist = pixel_initial + pixel_dist * t; + paint_tool->curpressure = paint_tool->lastpressure + dpressure * t; + paint_tool->curxtilt = paint_tool->lastxtilt + dxtilt * t; + paint_tool->curytilt = paint_tool->lastytilt + dytilt * t; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = paint_core->lastwheel + dwheel * t; + paint_tool->curwheel = paint_tool->lastwheel + dwheel * t; #endif /* GTK_HAVE_SIX_VALUATORS */ /* save the current brush */ - current_brush = paint_core->brush; + current_brush = paint_tool->brush; - if (paint_core->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) - paint_core->brush = - (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_core->brush) - ->klass)->select_brush) (paint_core); - (* paint_core->paint_func) (paint_core, drawable, MOTION_PAINT); + if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) + paint_tool->brush = + (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->select_brush) (paint_tool); + gimp_paint_tool_paint(paint_tool, drawable, MOTION_PAINT); /* restore the current brush pointer */ - paint_core->brush = current_brush; + paint_tool->brush = current_brush; } } - paint_core->distance = total; - paint_core->pixel_dist = pixel_initial + pixel_dist; - paint_core->curx = paint_core->lastx + delta.x; - paint_core->cury = paint_core->lasty + delta.y; - paint_core->curpressure = paint_core->lastpressure + dpressure; - paint_core->curxtilt = paint_core->lastxtilt + dxtilt; - paint_core->curytilt = paint_core->lastytilt + dytilt; + paint_tool->distance = total; + paint_tool->pixel_dist = pixel_initial + pixel_dist; + paint_tool->curx = paint_tool->lastx + delta.x; + paint_tool->cury = paint_tool->lasty + delta.y; + paint_tool->curpressure = paint_tool->lastpressure + dpressure; + paint_tool->curxtilt = paint_tool->lastxtilt + dxtilt; + paint_tool->curytilt = paint_tool->lastytilt + dytilt; #ifdef GTK_HAVE_SIX_VALUATORS - paint_core->curwheel = paint_core->lastwheel + dwheel; + paint_tool->curwheel = paint_tool->lastwheel + dwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ } void -paint_core_finish (PaintCore *paint_core, - GimpDrawable *drawable, - gint tool_ID) +gimp_paint_tool_finish (GimpPaintTool *paint_tool, + GimpDrawable *drawable) { GImage *gimage; PaintUndo *pu; @@ -964,29 +1034,29 @@ paint_core_finish (PaintCore *paint_core, * if nothing has, then just return... */ - if ((paint_core->x2 == paint_core->x1) || - (paint_core->y2 == paint_core->y1)) + if ((paint_tool->x2 == paint_tool->x1) || + (paint_tool->y2 == paint_tool->y1)) return; undo_push_group_start (gimage, PAINT_CORE_UNDO); pu = g_new (PaintUndo, 1); - pu->tool_ID = tool_ID; - pu->lastx = paint_core->startx; - pu->lasty = paint_core->starty; - pu->lastpressure = paint_core->startpressure; - pu->lastxtilt = paint_core->startxtilt; - pu->lastytilt = paint_core->startytilt; + pu->tool = paint_tool; + pu->lastx = paint_tool->startx; + pu->lasty = paint_tool->starty; + pu->lastpressure = paint_tool->startpressure; + pu->lastxtilt = paint_tool->startxtilt; + pu->lastytilt = paint_tool->startytilt; #ifdef GTK_HAVE_SIX_VALUATORS - pu->lastwheel = paint_core->startwheel; + pu->lastwheel = paint_tool->startwheel; #endif /* GTK_HAVE_SIX_VALUATORS */ /* Push a paint undo */ undo_push_paint (gimage, pu); /* push an undo */ - drawable_apply_image (drawable, paint_core->x1, paint_core->y1, - paint_core->x2, paint_core->y2, undo_tiles, TRUE); + drawable_apply_image (drawable, paint_tool->x1, paint_tool->y1, + paint_tool->x2, paint_tool->y2, undo_tiles, TRUE); undo_tiles = NULL; /* push the group end */ @@ -999,7 +1069,7 @@ paint_core_finish (PaintCore *paint_core, } void -paint_core_cleanup (void) +gimp_paint_tool_cleanup (void) { /* CLEANUP */ /* If the undo tiles exist, nuke them */ @@ -1021,20 +1091,20 @@ paint_core_cleanup (void) } void -paint_core_get_color_from_gradient (PaintCore *paint_core, - gdouble gradient_length, +gimp_paint_tool_get_color_from_gradient (GimpPaintTool *paint_tool, + gdouble gradient_length, GimpRGB *color, GradientPaintMode mode) { gdouble y; gdouble distance; /* distance in current brush stroke */ - distance = paint_core->pixel_dist; + distance = paint_tool->pixel_dist; y = ((double) distance / gradient_length); /* for the once modes, set y close to 1.0 after the first chunk */ if ( (mode == ONCE_FORWARD || mode == ONCE_BACKWARDS) && y >= 1.0 ) - y = 0.9999999; + y = 0.9999999; if ( (((int)y & 1) && mode != LOOP_SAWTOOTH) || mode == ONCE_BACKWARDS ) y = 1.0 - (y - (int)y); @@ -1050,7 +1120,7 @@ paint_core_get_color_from_gradient (PaintCore *paint_core, /************************/ TempBuf * -paint_core_get_paint_area (PaintCore *paint_core, +gimp_paint_tool_get_paint_area (GimpPaintTool *paint_tool, GimpDrawable *drawable, gdouble scale) { @@ -1063,12 +1133,12 @@ paint_core_get_paint_area (PaintCore *paint_core, bytes = gimp_drawable_has_alpha (drawable) ? gimp_drawable_bytes (drawable) : gimp_drawable_bytes (drawable) + 1; - paint_core_calculate_brush_size (paint_core->brush->mask, scale, + gimp_paint_tool_calculate_brush_size (paint_tool->brush->mask, scale, &bwidth, &bheight); /* adjust the x and y coordinates to the upper left corner of the brush */ - x = (gint) floor (paint_core->curx) - (bwidth >> 1); - y = (gint) floor (paint_core->cury) - (bheight >> 1); + x = (gint) floor (paint_tool->curx) - (bwidth >> 1); + y = (gint) floor (paint_tool->cury) - (bheight >> 1); dwidth = gimp_drawable_width (drawable); dheight = gimp_drawable_height (drawable); @@ -1089,8 +1159,8 @@ paint_core_get_paint_area (PaintCore *paint_core, } TempBuf * -paint_core_get_orig_image (PaintCore *paint_core, - GimpDrawable *drawable, +gimp_paint_tool_get_orig_image (GimpPaintTool *paint_tool, + GimpDrawable *drawable, gint x1, gint y1, gint x2, @@ -1169,10 +1239,10 @@ paint_core_get_orig_image (PaintCore *paint_core, } void -paint_core_paste_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, +gimp_paint_tool_paste_canvas (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, LayerModeEffects paint_mode, BrushApplicationMode brush_hardness, gdouble brush_scale, @@ -1181,22 +1251,22 @@ paint_core_paste_canvas (PaintCore *paint_core, MaskBuf *brush_mask; /* get the brush mask */ - brush_mask = paint_core_get_brush_mask (paint_core, + brush_mask = gimp_paint_tool_get_brush_mask (paint_tool, brush_hardness, brush_scale); /* paste the canvas buf */ - paint_core_paste (paint_core, brush_mask, drawable, + gimp_paint_tool_paste (paint_tool, brush_mask, drawable, brush_opacity, image_opacity, paint_mode, mode); } -/* Similar to paint_core_paste_canvas, but replaces the alpha channel +/* Similar to gimp_paint_tool_paste_canvas, but replaces the alpha channel rather than using it to composite (i.e. transparent over opaque becomes transparent rather than opauqe. */ void -paint_core_replace_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, +gimp_paint_tool_replace_canvas (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, BrushApplicationMode brush_hardness, gdouble brush_scale, PaintApplicationMode mode) @@ -1204,19 +1274,19 @@ paint_core_replace_canvas (PaintCore *paint_core, MaskBuf *brush_mask; /* get the brush mask */ - brush_mask = - paint_core_get_brush_mask (paint_core, brush_hardness, brush_scale); + brush_mask = + gimp_paint_tool_get_brush_mask (paint_tool, brush_hardness, brush_scale); /* paste the canvas buf */ - paint_core_replace (paint_core, brush_mask, drawable, + gimp_paint_tool_replace (paint_tool, brush_mask, drawable, brush_opacity, image_opacity, mode); } static void -paint_core_invalidate_cache (GimpBrush *brush, +gimp_paint_tool_invalidate_cache (GimpBrush *brush, gpointer data) -{ +{ /* Make sure we don't cache data for a brush that has changed */ if (last_brush_mask == brush->mask) cache_invalid = TRUE; @@ -1227,7 +1297,7 @@ paint_core_invalidate_cache (GimpBrush *brush, ************************************************************/ static void -paint_core_calculate_brush_size (MaskBuf *mask, +gimp_paint_tool_calculate_brush_size (MaskBuf *mask, gdouble scale, gint *width, gint *height) @@ -1251,11 +1321,11 @@ paint_core_calculate_brush_size (MaskBuf *mask, *width = MAX ((gint) (mask->width * ratio + 0.5), 1); *height = MAX ((gint) (mask->height * ratio + 0.5), 1); } -} +} static MaskBuf * -paint_core_subsample_mask (MaskBuf *mask, - gdouble x, +gimp_paint_tool_subsample_mask (MaskBuf *mask, + gdouble x, gdouble y) { MaskBuf *dest; @@ -1300,7 +1370,7 @@ paint_core_subsample_mask (MaskBuf *mask, cache_invalid = FALSE; } - dest = kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, + dest = kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, mask->height + 2); m = mask_buf_data (mask); @@ -1329,9 +1399,9 @@ paint_core_subsample_mask (MaskBuf *mask, /* #define FANCY_PRESSURE */ static MaskBuf * -paint_core_pressurize_mask (MaskBuf *brush_mask, - gdouble x, - gdouble y, +gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask, + gdouble x, + gdouble y, gdouble pressure) { static MaskBuf *last_brush = NULL; @@ -1346,7 +1416,7 @@ paint_core_pressurize_mask (MaskBuf *brush_mask, #endif /* Get the raw subsampled mask */ - subsample_mask = paint_core_subsample_mask (brush_mask, x, y); + subsample_mask = gimp_paint_tool_subsample_mask (brush_mask, x, y); /* Special case pressure = 0.5 */ if ((int)(pressure * 100 + 0.5) == 50) @@ -1435,7 +1505,7 @@ paint_core_pressurize_mask (MaskBuf *brush_mask, } static MaskBuf * -paint_core_solidify_mask (MaskBuf *brush_mask) +gimp_paint_tool_solidify_mask (MaskBuf *brush_mask) { static MaskBuf *last_brush = NULL; gint i; @@ -1471,24 +1541,24 @@ paint_core_solidify_mask (MaskBuf *brush_mask) } static MaskBuf * -paint_core_scale_mask (MaskBuf *brush_mask, +gimp_paint_tool_scale_mask (MaskBuf *brush_mask, gdouble scale) { static MaskBuf *last_brush = NULL; - static gint last_width = 0.0; - static gint last_height = 0.0; + static gint last_width = 0.0; + static gint last_height = 0.0; gint dest_width; gint dest_height; scale = CLAMP (scale, 0.0, 1.0); - if (scale == 0.0) + if (scale == 0.0) return NULL; if (scale == 1.0) return brush_mask; - paint_core_calculate_brush_size (brush_mask, scale, + gimp_paint_tool_calculate_brush_size (brush_mask, scale, &dest_width, &dest_height); if (brush_mask == last_brush && !cache_invalid && @@ -1509,12 +1579,12 @@ paint_core_scale_mask (MaskBuf *brush_mask, } static MaskBuf * -paint_core_scale_pixmap (MaskBuf *brush_mask, +gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask, gdouble scale) { static MaskBuf *last_brush = NULL; - static gint last_width = 0.0; - static gint last_height = 0.0; + static gint last_width = 0.0; + static gint last_height = 0.0; gint dest_width; gint dest_height; @@ -1526,7 +1596,7 @@ paint_core_scale_pixmap (MaskBuf *brush_mask, if (scale == 1.0) return brush_mask; - paint_core_calculate_brush_size (brush_mask, scale, + gimp_paint_tool_calculate_brush_size (brush_mask, scale, &dest_width, &dest_height); if (brush_mask == last_brush && !cache_invalid && @@ -1547,30 +1617,30 @@ paint_core_scale_pixmap (MaskBuf *brush_mask, } static MaskBuf * -paint_core_get_brush_mask (PaintCore *paint_core, +gimp_paint_tool_get_brush_mask (GimpPaintTool *paint_tool, BrushApplicationMode brush_hardness, gdouble scale) { MaskBuf *mask; if (current_device == GDK_CORE_POINTER) - mask = paint_core->brush->mask; + mask = paint_tool->brush->mask; else - mask = paint_core_scale_mask (paint_core->brush->mask, scale); + mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale); switch (brush_hardness) { case SOFT: - mask = paint_core_subsample_mask (mask, - paint_core->curx, paint_core->cury); + mask = gimp_paint_tool_subsample_mask (mask, + paint_tool->curx, paint_tool->cury); break; case HARD: - mask = paint_core_solidify_mask (mask); + mask = gimp_paint_tool_solidify_mask (mask); break; case PRESSURE: - mask = paint_core_pressurize_mask (mask, - paint_core->curx, paint_core->cury, - paint_core->curpressure); + mask = gimp_paint_tool_pressurize_mask (mask, + paint_tool->curx, paint_tool->cury, + paint_tool->curpressure); break; default: break; @@ -1580,12 +1650,12 @@ paint_core_get_brush_mask (PaintCore *paint_core, } static void -paint_core_paste (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, - LayerModeEffects paint_mode, +gimp_paint_tool_paste (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, PaintApplicationMode mode) { GimpImage *gimage; @@ -1611,8 +1681,8 @@ paint_core_paste (PaintCore *paint_core, set_canvas_tiles (canvas_buf->x, canvas_buf->y, canvas_buf->width, canvas_buf->height); - brush_to_canvas_tiles (paint_core, brush_mask, brush_opacity); - canvas_tiles_to_canvas_buf (paint_core); + brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity); + canvas_tiles_to_canvas_buf (paint_tool); alt = undo_tiles; } /* Otherwise: @@ -1620,7 +1690,7 @@ paint_core_paste (PaintCore *paint_core, */ else { - brush_to_canvas_buf (paint_core, brush_mask, brush_opacity); + brush_to_canvas_buf (paint_tool, brush_mask, brush_opacity); } /* intialize canvas buf source pixel regions */ @@ -1638,10 +1708,10 @@ paint_core_paste (PaintCore *paint_core, canvas_buf->x, canvas_buf->y); /* Update the undo extents */ - paint_core->x1 = MIN (paint_core->x1, canvas_buf->x); - paint_core->y1 = MIN (paint_core->y1, canvas_buf->y); - paint_core->x2 = MAX (paint_core->x2, (canvas_buf->x + canvas_buf->width)); - paint_core->y2 = MAX (paint_core->y2, (canvas_buf->y + canvas_buf->height)); + paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x); + paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y); + paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width)); + paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height)); /* Update the gimage--it is important to call gdisplays_update_area * instead of drawable_update because we don't want the drawable @@ -1652,20 +1722,20 @@ paint_core_paste (PaintCore *paint_core, canvas_buf->width, canvas_buf->height); } -/* This works similarly to paint_core_paste. However, instead of combining +/* This works similarly to gimp_paint_tool_paste. However, instead of combining the canvas to the paint core drawable using one of the combination - modes, it uses a "replace" mode (i.e. transparent pixels in the + modes, it uses a "replace" mode (i.e. transparent pixels in the canvas erase the paint core drawable). When not drawing on alpha-enabled images, it just paints using NORMAL mode. */ static void -paint_core_replace (PaintCore *paint_core, - MaskBuf *brush_mask, - GimpDrawable *drawable, - gint brush_opacity, - gint image_opacity, +gimp_paint_tool_replace (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, PaintApplicationMode mode) { GimpImage *gimage; @@ -1677,7 +1747,7 @@ paint_core_replace (PaintCore *paint_core, if (! gimp_drawable_has_alpha (drawable)) { - paint_core_paste (paint_core, brush_mask, drawable, + gimp_paint_tool_paste (paint_tool, brush_mask, drawable, brush_opacity, image_opacity, NORMAL_MODE, mode); return; @@ -1691,16 +1761,16 @@ paint_core_replace (PaintCore *paint_core, canvas_buf->x, canvas_buf->y, canvas_buf->width, canvas_buf->height); - if (mode == CONSTANT) + if (mode == CONSTANT) { /* initialize any invalid canvas tiles */ set_canvas_tiles (canvas_buf->x, canvas_buf->y, canvas_buf->width, canvas_buf->height); /* combine the brush mask and the canvas tiles */ - brush_to_canvas_tiles (paint_core, brush_mask, brush_opacity); + brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity); - /* set the alt source as the unaltered undo_tiles */ + /* set the alt source as the unaltered undo_tiles */ alt = undo_tiles; /* initialize the maskPR from the canvas tiles */ @@ -1712,7 +1782,7 @@ paint_core_replace (PaintCore *paint_core, { /* The mask is just the brush mask */ maskPR.bytes = 1; - maskPR.x = 0; + maskPR.x = 0; maskPR.y = 0; maskPR.w = canvas_buf->width; maskPR.h = canvas_buf->height; @@ -1722,7 +1792,7 @@ paint_core_replace (PaintCore *paint_core, /* intialize canvas buf source pixel regions */ srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; + srcPR.x = 0; srcPR.y = 0; srcPR.w = canvas_buf->width; srcPR.h = canvas_buf->height; @@ -1732,14 +1802,14 @@ paint_core_replace (PaintCore *paint_core, /* apply the paint area to the gimage */ gimp_image_replace_image (gimage, drawable, &srcPR, FALSE, image_opacity, - &maskPR, + &maskPR, canvas_buf->x, canvas_buf->y); /* Update the undo extents */ - paint_core->x1 = MIN (paint_core->x1, canvas_buf->x); - paint_core->y1 = MIN (paint_core->y1, canvas_buf->y); - paint_core->x2 = MAX (paint_core->x2, (canvas_buf->x + canvas_buf->width)); - paint_core->y2 = MAX (paint_core->y2, (canvas_buf->y + canvas_buf->height)); + paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x); + paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y); + paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width)); + paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height)); /* Update the gimage--it is important to call gdisplays_update_area * instead of drawable_update because we don't want the drawable @@ -1751,14 +1821,14 @@ paint_core_replace (PaintCore *paint_core, } static void -canvas_tiles_to_canvas_buf (PaintCore *paint_core) +canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool) { PixelRegion srcPR; PixelRegion maskPR; /* combine the canvas tiles and the canvas buf */ srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; + srcPR.x = 0; srcPR.y = 0; srcPR.w = canvas_buf->width; srcPR.h = canvas_buf->height; @@ -1774,8 +1844,8 @@ canvas_tiles_to_canvas_buf (PaintCore *paint_core) } static void -brush_to_canvas_tiles (PaintCore *paint_core, - MaskBuf *brush_mask, +brush_to_canvas_tiles (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, gint brush_opacity) { PixelRegion srcPR; @@ -1790,13 +1860,13 @@ brush_to_canvas_tiles (PaintCore *paint_core, canvas_buf->x, canvas_buf->y, canvas_buf->width, canvas_buf->height, TRUE); - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); xoff = (x < 0) ? -x : 0; yoff = (y < 0) ? -y : 0; maskPR.bytes = 1; - maskPR.x = 0; + maskPR.x = 0; maskPR.y = 0; maskPR.w = srcPR.w; maskPR.h = srcPR.h; @@ -1808,7 +1878,7 @@ brush_to_canvas_tiles (PaintCore *paint_core, } static void -brush_to_canvas_buf (PaintCore *paint_core, +brush_to_canvas_buf (GimpPaintTool *paint_tool, MaskBuf *brush_mask, gint brush_opacity) { @@ -1819,14 +1889,14 @@ brush_to_canvas_buf (PaintCore *paint_core, gint xoff; gint yoff; - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); xoff = (x < 0) ? -x : 0; yoff = (y < 0) ? -y : 0; /* combine the canvas buf and the brush mask to the canvas buf */ srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; + srcPR.x = 0; srcPR.y = 0; srcPR.w = canvas_buf->width; srcPR.h = canvas_buf->height; @@ -1834,7 +1904,7 @@ brush_to_canvas_buf (PaintCore *paint_core, srcPR.data = temp_buf_data (canvas_buf); maskPR.bytes = 1; - maskPR.x = 0; + maskPR.x = 0; maskPR.y = 0; maskPR.w = srcPR.w; maskPR.h = srcPR.h; @@ -1847,8 +1917,8 @@ brush_to_canvas_buf (PaintCore *paint_core, #if 0 static void -paint_to_canvas_tiles (PaintCore *paint_core, - MaskBuf *brush_mask, +paint_to_canvas_tiles (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, gint brush_opacity) { PixelRegion srcPR; @@ -1863,13 +1933,13 @@ paint_to_canvas_tiles (PaintCore *paint_core, canvas_buf->x, canvas_buf->y, canvas_buf->width, canvas_buf->height, TRUE); - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); xoff = (x < 0) ? -x : 0; yoff = (y < 0) ? -y : 0; maskPR.bytes = 1; - maskPR.x = 0; + maskPR.x = 0; maskPR.y = 0; maskPR.w = srcPR.w; maskPR.h = srcPR.h; @@ -1881,7 +1951,7 @@ paint_to_canvas_tiles (PaintCore *paint_core, /* combine the canvas tiles and the canvas buf */ srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; + srcPR.x = 0; srcPR.y = 0; srcPR.w = canvas_buf->width; srcPR.h = canvas_buf->height; @@ -1897,8 +1967,8 @@ paint_to_canvas_tiles (PaintCore *paint_core, } static void -paint_to_canvas_buf (PaintCore *paint_core, - MaskBuf *brush_mask, +paint_to_canvas_buf (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, gint brush_opacity) { PixelRegion srcPR; @@ -1908,15 +1978,15 @@ paint_to_canvas_buf (PaintCore *paint_core, gint xoff; gint yoff; - x = (gint) floor (paint_core->curx) - (brush_mask->width >> 1); - y = (gint) floor (paint_core->cury) - (brush_mask->height >> 1); + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); xoff = (x < 0) ? -x : 0; yoff = (y < 0) ? -y : 0; /* combine the canvas buf and the brush mask to the canvas buf */ srcPR.bytes = canvas_buf->bytes; - srcPR.x = 0; + srcPR.x = 0; srcPR.y = 0; srcPR.w = canvas_buf->width; srcPR.h = canvas_buf->height; @@ -1924,7 +1994,7 @@ paint_to_canvas_buf (PaintCore *paint_core, srcPR.data = temp_buf_data (canvas_buf); maskPR.bytes = 1; - maskPR.x = 0; + maskPR.x = 0; maskPR.y = 0; maskPR.w = srcPR.w; maskPR.h = srcPR.h; @@ -1937,7 +2007,7 @@ paint_to_canvas_buf (PaintCore *paint_core, #endif static void -set_undo_tiles (GimpDrawable *drawable, +set_undo_tiles (GimpDrawable *drawable, gint x, gint y, gint w, @@ -1948,7 +2018,7 @@ set_undo_tiles (GimpDrawable *drawable, Tile *src_tile; Tile *dest_tile; - if (undo_tiles == NULL) + if (undo_tiles == NULL) { g_warning ("set_undo_tiles: undo_tiles is null"); return; @@ -2019,7 +2089,7 @@ free_paint_buffers (void) /**************************************************/ void -paint_core_color_area_with_pixmap (PaintCore *paint_core, +gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *paint_tool, GimpImage *dest, GimpDrawable *drawable, TempBuf *area, @@ -2037,19 +2107,19 @@ paint_core_color_area_with_pixmap (PaintCore *paint_core, TempBuf *pixmap_mask; TempBuf *brush_mask; - g_return_if_fail (GIMP_IS_BRUSH (paint_core->brush)); - g_return_if_fail (paint_core->brush->pixmap != NULL); - + g_return_if_fail (GIMP_IS_BRUSH (paint_tool->brush)); + g_return_if_fail (paint_tool->brush->pixmap != NULL); + /* scale the brushes */ - pixmap_mask = paint_core_scale_pixmap (paint_core->brush->pixmap, scale); + pixmap_mask = gimp_paint_tool_scale_pixmap (paint_tool->brush->pixmap, scale); if (mode == SOFT) - brush_mask = paint_core_scale_mask (paint_core->brush->mask, scale); + brush_mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale); else brush_mask = NULL; destPR.bytes = area->bytes; - destPR.x = 0; + destPR.x = 0; destPR.y = 0; destPR.w = area->width; destPR.h = area->height; @@ -2059,11 +2129,11 @@ paint_core_color_area_with_pixmap (PaintCore *paint_core, pr = pixel_regions_register (1, &destPR); /* Calculate upper left corner of brush as in - * paint_core_get_paint_area. Ugly to have to do this here, too. + * gimp_paint_tool_get_paint_area. Ugly to have to do this here, too. */ - ulx = (gint) floor (paint_core->curx) - (pixmap_mask->width >> 1); - uly = (gint) floor (paint_core->cury) - (pixmap_mask->height >> 1); + ulx = (gint) floor (paint_tool->curx) - (pixmap_mask->width >> 1); + uly = (gint) floor (paint_tool->cury) - (pixmap_mask->height >> 1); offsetx = area->x - ulx; offsety = area->y - uly; diff --git a/app/tools/paint_core.h b/app/paint/gimppaintcore.h similarity index 66% rename from app/tools/paint_core.h rename to app/paint/gimppaintcore.h index 672809b08b..9b1fc62c81 100644 --- a/app/tools/paint_core.h +++ b/app/paint/gimppaintcore.h @@ -16,15 +16,24 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __PAINT_CORE_H__ -#define __PAINT_CORE_H__ +#ifndef __GIMP_PAINT_TOOL_H__ +#define __GIMP_PAINT_TOOL_H__ +#include "tools/gimpdrawtool.h" + +#define GIMP_TYPE_PAINT_TOOL (gimp_paint_tool_get_type ()) +#define GIMP_PAINT_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_PAINT_TOOL, GimpPaintTool)) +#define GIMP_IS_PAINT_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_PAINT_TOOL)) +#define GIMP_PAINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PAINT_TOOL, GimpPaintToolClass)) +#define GIMP_IS_PAINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PAINT_TOOL)) + +GtkType gimp_paint_tool_get_type (void); /* the different states that the painting function can be called with */ typedef enum /*< skip >*/ { - INIT_PAINT, /* Setup PaintFunc internals */ + INIT_PAINT, /* Setup PaintFunc internals */ MOTION_PAINT, /* PaintFunc performs motion-related rendering */ PAUSE_PAINT, /* Unused. Reserved */ RESUME_PAINT, /* Unused. Reserved */ @@ -47,13 +56,13 @@ typedef enum /*< skip >*/ */ } ToolFlags; -typedef gpointer (* PaintFunc) (PaintCore *paint_core, - GimpDrawable *drawable, - PaintState paint_state); +typedef void (* PaintFunc) (GimpPaintTool *tool, + GimpDrawable *drawable, + PaintState paint_state); -struct _PaintCore +struct _GimpPaintTool { - DrawCore * core; /* Core select object */ + GimpDrawTool parent_instance; gdouble startx; /* starting x coord */ gdouble starty; /* starting y coord */ @@ -61,7 +70,7 @@ struct _PaintCore gdouble startxtilt; /* starting xtilt */ gdouble startytilt; /* starting ytilt */ #ifdef GTK_HAVE_SIX_VALUATORS - gdouble startwheel; /* starting wheel */ + gdouble startwheel; /* starting wheel */ #endif /* GTK_HAVE_SIX_VALUATORS */ gdouble curx; /* current x coord */ @@ -79,8 +88,8 @@ struct _PaintCore gdouble lastxtilt; /* last xtilt */ gdouble lastytilt; /* last ytilt */ #ifdef GTK_HAVE_SIX_VALUATORS - gdouble lastwheel; /* last wheel */ -#endif /* GTK_HAVE_SIX_VALUATORS */ + gdouble lastwheel; /* last wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ gint state; /* state of buttons and keys */ @@ -93,8 +102,6 @@ struct _PaintCore GimpBrush * brush; /* current brush */ - PaintFunc paint_func; /* painting function */ - gboolean pick_colors; /* pick color if ctrl or alt is pressed */ gboolean pick_state; /* was ctrl or alt pressed when clicked? */ ToolFlags flags; /* tool flags, see ToolFlags above */ @@ -102,14 +109,28 @@ struct _PaintCore guint context_id; /* for the statusbar */ }; -extern PaintCore non_gui_paint_core; +struct _GimpPaintToolClass +{ + GimpDrawToolClass parent_class; + + PaintFunc paint_func; /* painting function */ +}; + +typedef struct _GimpPaintToolClass GimpPaintToolClass; + + +/* this should change */ +extern GimpPaintTool *non_gui_paint_tool; +extern GimpPaintToolClass *non_gui_paint_tool_class; /* Special undo type */ typedef struct _PaintUndo PaintUndo; struct _PaintUndo { - gint tool_ID; + GimpPaintTool *tool; + + gdouble lastx; gdouble lasty; gdouble lastpressure; @@ -121,73 +142,73 @@ struct _PaintUndo }; /* paint tool action functions */ -void paint_core_button_press (Tool *tool, +void gimp_paint_tool_button_press (GimpTool *tool, GdkEventButton *bevent, GDisplay *gdisp); -void paint_core_button_release (Tool *tool, +void gimp_paint_tool_button_release (GimpTool *tool, GdkEventButton *bevent, GDisplay *gdisp); -void paint_core_motion (Tool *tool, +void gimp_paint_tool_motion (GimpTool *tool, GdkEventMotion *mevent, GDisplay *gdisp); -void paint_core_cursor_update (Tool *tool, +void gimp_paint_tool_cursor_update (GimpTool *tool, GdkEventMotion *mevent, GDisplay *gdisp); -void paint_core_control (Tool *tool, +void gimp_paint_tool_control (GimpTool *tool, ToolAction action, GDisplay *gdisp); +void gimp_paint_tool_paint (GimpPaintTool *tool, + GimpDrawable *drawable, + PaintState state); + /* paint tool functions */ -void paint_core_no_draw (Tool *tool); +void gimp_paint_tool_no_draw (GimpPaintTool *tool); -/* ToolType doesn't exist an more -Tool * paint_core_new (ToolType type); -*/ - -void paint_core_free (Tool *tool); -int paint_core_init (PaintCore *paint_core, - GimpDrawable *drawable, - gdouble x, +GimpPaintTool *gimp_paint_tool_new (void); +void gimp_paint_tool_destroy (GimpTool *tool); +int gimp_paint_tool_start (GimpPaintTool *tool, + GimpDrawable *drawable, + gdouble x, gdouble y); -void paint_core_interpolate (PaintCore *paint_core, +void gimp_paint_tool_interpolate (GimpPaintTool *tool, GimpDrawable *drawable); -void paint_core_finish (PaintCore *paint_core, - GimpDrawable *drawable, - gint tool_ID); -void paint_core_cleanup (void); +void gimp_paint_tool_finish (GimpPaintTool *tool, + GimpDrawable *drawable); +void gimp_paint_tool_cleanup (void); -void paint_core_get_color_from_gradient (PaintCore *paint_core, - gdouble gradient_length, +void gimp_paint_tool_get_color_from_gradient (GimpPaintTool *tool, + gdouble gradient_length, GimpRGB *color, GradientPaintMode mode); /* paint tool painting functions */ -TempBuf * paint_core_get_paint_area (PaintCore *paint_core, +TempBuf * gimp_paint_tool_get_paint_area (GimpPaintTool *tool, GimpDrawable *drawable, gdouble scale); -TempBuf * paint_core_get_orig_image (PaintCore *paint_core, +TempBuf * gimp_paint_tool_get_orig_image (GimpPaintTool *tool, GimpDrawable *drawable, - gint x1, - gint y1, + gint x1, + gint y1, gint x2, gint y2); -void paint_core_paste_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, +void gimp_paint_tool_paste_canvas (GimpPaintTool *tool, + GimpDrawable *drawable, + gint brush_opacity, gint image_opacity, LayerModeEffects paint_mode, BrushApplicationMode brush_hardness, gdouble brush_scale, PaintApplicationMode mode); -void paint_core_replace_canvas (PaintCore *paint_core, - GimpDrawable *drawable, - gint brush_opacity, +void gimp_paint_tool_replace_canvas (GimpPaintTool *tool, + GimpDrawable *drawable, + gint brush_opacity, gint image_opacity, BrushApplicationMode brush_hardness, gdouble brush_scale, PaintApplicationMode mode); -void paint_core_color_area_with_pixmap (PaintCore *paint_core, +void gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *tool, GimpImage *dest, GimpDrawable *drawable, TempBuf *area, @@ -195,4 +216,4 @@ void paint_core_color_area_with_pixmap (PaintCore *paint_core, BrushApplicationMode mode); -#endif /* __PAINT_CORE_H__ */ +#endif /* __GIMP_PAINT_TOOL_H__ */ diff --git a/app/path_transform.h b/app/path_transform.h index 1b7dd03644..271e590791 100644 --- a/app/path_transform.h +++ b/app/path_transform.h @@ -29,7 +29,7 @@ void path_transform_current_path (GimpImage *gimage, GimpMatrix3 transform, gboolean forpreview); void path_transform_draw_current (GDisplay *gimage, - DrawCore *core, + GimpDrawTool *core, GimpMatrix3 transform); void path_transform_flip_horz (GimpImage *gimage); diff --git a/app/pdb/tools_cmds.c b/app/pdb/tools_cmds.c index d5ce94507c..2cf9ebefb5 100644 --- a/app/pdb/tools_cmds.c +++ b/app/pdb/tools_cmds.c @@ -34,7 +34,7 @@ #include "tools/bucket_fill.h" #include "tools/by_color_select.h" #include "tools/clone.h" -#include "tools/color_picker.h" +#include "tools/gimpcolorpickertool.h" #include "tools/convolve.h" #include "tools/crop.h" #include "tools/dodgeburn.h" @@ -43,7 +43,7 @@ #include "tools/flip_tool.h" #include "tools/free_select.h" #include "tools/fuzzy_select.h" -#include "tools/paintbrush.h" +#include "tools/gimppaintbrushtool.h" #include "tools/pencil.h" #include "tools/perspective_tool.h" #include "tools/rect_select.h" @@ -1928,7 +1928,7 @@ paintbrush_invoker (Argument *args) success = FALSE; if (success) - success = paintbrush_non_gui (drawable, num_strokes, strokes, fade_out, + success = gimp_paintbrush_tool_non_gui (drawable, num_strokes, strokes, fade_out, method, gradient_length); return procedural_db_return_args (&paintbrush_proc, success); @@ -2005,7 +2005,7 @@ paintbrush_default_invoker (Argument *args) strokes = (gdouble *) args[2].value.pdb_pointer; if (success) - success = paintbrush_non_gui_default (drawable, num_strokes, strokes); + success = gimp_paintbrush_tool_non_gui_default (drawable, num_strokes, strokes); return procedural_db_return_args (&paintbrush_default_proc, success); } diff --git a/app/tools/Makefile.am b/app/tools/Makefile.am index 7fd9d21a4a..25932a32cb 100644 --- a/app/tools/Makefile.am +++ b/app/tools/Makefile.am @@ -24,8 +24,8 @@ libapptools_la_SOURCES = \ ## clone.h \ ## color_balance.c \ ## color_balance.h \ - color_picker.c \ - color_picker.h \ + gimpcolorpickertool.c \ + gimpcolorpickertool.h \ ## convolve.c \ ## convolve.h \ ## crop.c \ @@ -34,6 +34,8 @@ libapptools_la_SOURCES = \ ## curves.h \ ## dodgeburn.c \ ## dodgeburn.h \ + gimpdrawtool.c \ + gimpdrawgtool.h \ ## edit_selection.c \ ## edit_selection.h \ ## ellipse_select.c \ @@ -60,15 +62,15 @@ libapptools_la_SOURCES = \ ## levels.h \ ## magnify.c \ ## magnify.h \ - measure.c \ - measure.h \ +## measure.c \ +## measure.h \ move.c \ move.h \ -## paintbrush.c \ -## paintbrush.h \ -## paint_core.c \ -## paint_core.h \ -## paint_core_kernels.h \ + gimppaintbrushtool.c \ + gimppaintbrushtool.h \ + gimppainttool.c \ + gimppainttool.h \ + gimppainttool_kernels.h \ paint_options.c \ paint_options.h \ ## pencil.c \ diff --git a/app/tools/bezier_selectP.h b/app/tools/bezier_selectP.h index 1e87e88c31..70e0322357 100644 --- a/app/tools/bezier_selectP.h +++ b/app/tools/bezier_selectP.h @@ -19,7 +19,7 @@ #ifndef __BEZIER_SELECTP_H__ #define __BEZIER_SELECTP_H__ -#include "draw_core.h" +#include "tools/gimpdrawtool.h" #define BEZIER_START 1 #define BEZIER_ADD 2 @@ -56,7 +56,7 @@ 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 */ + GimpDrawTool *core; /* Core drawing object */ BezierPoint *points; /* the curve */ BezierPoint *cur_anchor; /* the current active anchor point */ BezierPoint *cur_control; /* the current active control point */ diff --git a/app/tools/color_picker.h b/app/tools/color_picker.h deleted file mode 100644 index 4f7428f872..0000000000 --- a/app/tools/color_picker.h +++ /dev/null @@ -1,70 +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__ - - -#include "tool.h" - - -#define GIMP_TYPE_COLOR_PICKER (gimp_color_picker_get_type ()) -#define GIMP_COLOR_PICKER(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_COLOR_PICKER, GimpColorPicker)) -#define GIMP_IS_COLOR_PICKER(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_COLOR_PICKER)) -#define GIMP_COLOR_PICKER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_COLOR_PICKER, GimpColorPickerClass)) -#define GIMP_IS_COLOR_PICKER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_COLOR_PICKER)) - - -typedef struct _GimpColorPicker GimpColorPicker; -typedef struct _GimpColorPickerClass GimpColorPickerClass; - -struct _GimpColorPicker -{ - GimpTool parent_instance; - - DrawCore *core; /* Core select object */ - - gint centerx; /* starting x coord */ - gint centery; /* starting y coord */ - -}; - -struct _GimpColorPickerClass -{ - GimpToolClass parent_class; -}; - -/* FIXME: Whats this doing here? */ -extern gint col_value[5]; - -GtkType gimp_color_picker_get_type (void); -GimpTool * gimp_color_picker_new (void); - -void gimp_color_picker_register (void); - -gboolean pick_color (GimpImage *gimage, - GimpDrawable *drawable, - gint x, - gint y, - gboolean sample_merged, - gboolean sample_average, - double average_radius, - gint final); - - -#endif /* __COLOR_PICKER_H__ */ diff --git a/app/tools/gimpbrushtool.c b/app/tools/gimpbrushtool.c new file mode 100644 index 0000000000..02a021b311 --- /dev/null +++ b/app/tools/gimpbrushtool.c @@ -0,0 +1,2225 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include + +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +#include "apptypes.h" + +#include "brush_scale.h" +#include "cursorutil.h" +#include "devices.h" +#include "gimpdrawtool.h" +#include "drawable.h" +#include "gdisplay.h" +#include "gimage_mask.h" +#include "gimpbrushpipe.h" +#include "gimpcontext.h" +#include "gimpgradient.h" +#include "gimpimage.h" +#include "gimprc.h" +#include "paint_funcs.h" +#include "gimppainttool.h" +#include "pixel_region.h" +#include "selection.h" +#include "temp_buf.h" +#include "tile.h" +#include "tile_manager.h" +#include "tool.h" +#include "undo.h" + +#include "libgimp/gimpintl.h" + +#include "gimppainttool_kernels.h" + + +/* target size */ +#define TARGET_HEIGHT 15 +#define TARGET_WIDTH 15 + +#define EPSILON 0.00001 + +#define STATUSBAR_SIZE 128 + +/* global variables--for use in the various paint tools */ +GimpPaintTool *non_gui_painting_tool; +GimpPaintToolClass *non_gui_painting_tool_class; + +/* local function prototypes */ +static void gimp_paint_tool_calculate_brush_size (MaskBuf *mask, + gdouble scale, + gint *width, + gint *height); +static MaskBuf * gimp_paint_tool_subsample_mask (MaskBuf *mask, + gdouble x, + gdouble y); +static MaskBuf * gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask, + gdouble x, + gdouble y, + gdouble pressure); +static MaskBuf * gimp_paint_tool_solidify_mask (MaskBuf *brush_mask); +static MaskBuf * gimp_paint_tool_scale_mask (MaskBuf *brush_mask, + gdouble scale); +static MaskBuf * gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask, + gdouble scale); + +static MaskBuf * gimp_paint_tool_get_brush_mask (GimpPaintTool *gimp_paint_tool, + BrushApplicationMode brush_hardness, + gdouble scale); +static void gimp_paint_tool_paste (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + PaintApplicationMode mode); +static void gimp_paint_tool_replace (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + PaintApplicationMode mode); + +static void brush_to_canvas_tiles (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + gint brush_opacity); +static void brush_to_canvas_buf (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + gint brush_opacity); +static void canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool); + +static void set_undo_tiles (GimpDrawable *drawable, + gint x, + gint y, + gint w, + gint h); +static void set_canvas_tiles (gint x, + gint y, + gint w, + gint h); +static void gimp_paint_tool_invalidate_cache (GimpBrush *brush, + gpointer data); + + +/* paint buffers utility functions */ +static void free_paint_buffers (void); + +/* brush pipe utility functions */ +static void paint_line_pixmap_mask (GimpImage *dest, + GimpDrawable *drawable, + TempBuf *pixmap_mask, + TempBuf *brush_mask, + guchar *d, + gint x, + gint y, + gint bytes, + gint width, + BrushApplicationMode mode); + +/***********************************************************************/ + + +/* undo blocks variables */ +static TileManager *undo_tiles = NULL; +static TileManager *canvas_tiles = NULL; + + +/***********************************************************************/ + + +/* paint buffers variables */ +static TempBuf *orig_buf = NULL; +static TempBuf *canvas_buf = NULL; + + +/* brush buffers */ +static MaskBuf *pressure_brush; +static MaskBuf *solid_brush; +static MaskBuf *scale_brush = NULL; +static MaskBuf *scale_pixmap = NULL; +static MaskBuf *kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1]; + +static MaskBuf *last_brush_mask = NULL; +static gboolean cache_invalid = FALSE; + +static void gimp_paint_tool_initialize (GimpPaintTool *); +static void gimp_paint_tool_class_init (GimpToolClass *); + +enum { /* signals */ + PAINT, + LAST_SIGNAL +}; + +static guint gimp_paint_tool_signals[LAST_SIGNAL] = { 0 }; + +static void standard_paint_func (GimpPaintTool *tool) +{ +} + +GtkType +gimp_paint_tool_get_type (void) +{ + static GtkType tool_type = 0; + + g_message ("sizeof GimpPaintTool = %i, GimpPaintToolClass = %i", sizeof(GimpPaintTool), sizeof (GimpPaintToolClass)); + g_message ("sizeof GimpDrawTool = %i, GimpDrawToolClass = %i", sizeof(GimpDrawTool), sizeof (GimpDrawToolClass)); + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpPaintTool", + sizeof (GimpPaintTool), + sizeof (GimpPaintToolClass), + (GtkClassInitFunc) gimp_paint_tool_class_init, + (GtkObjectInitFunc) gimp_paint_tool_initialize, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + NULL + }; + + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); + } + + return tool_type; +} + +GimpPaintTool * +gimp_paint_tool_new (void) +{ + return gtk_type_new (GIMP_TYPE_PAINT_TOOL); +} + +/***********************************************************************/ + +static void +gimp_paint_tool_sample_color (GimpDrawable *drawable, + gint x, + gint y, + gint state) +{ + GimpRGB color; + guchar *col; + + if( x >= 0 && x < gimp_drawable_width (drawable) && + y >= 0 && y < gimp_drawable_height (drawable)) + { + if ((col = gimp_drawable_get_color_at (drawable, x, y))) + { + gimp_rgba_set_uchar (&color, + col[RED_PIX], + col[GREEN_PIX], + col[BLUE_PIX], + 255); + + if ((state & GDK_CONTROL_MASK)) + gimp_context_set_foreground (gimp_context_get_user (), &color); + else + gimp_context_set_background (gimp_context_get_user (), &color); + + g_free (col); + } + } +} + + +void +gimp_paint_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GimpPaintTool *paint_tool; + GimpBrush *current_brush; + gboolean draw_line; + gdouble x, y; + GimpDrawable *drawable; + + g_return_if_fail (gdisp != NULL); + g_return_if_fail (tool != NULL); + + paint_tool = GIMP_PAINT_TOOL(tool); + + gdisplay_untransform_coords_f (gdisp, (double) bevent->x, (double) bevent->y, + &x, &y, TRUE); + drawable = gimp_image_active_drawable (gdisp->gimage); + + if (! gimp_paint_tool_start (paint_tool, drawable, x, y)) + return; + + draw_line = FALSE; + + paint_tool->curpressure = bevent->pressure; + paint_tool->curxtilt = bevent->xtilt; + paint_tool->curytilt = bevent->ytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = bevent->wheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + paint_tool->state = bevent->state; + + if (gdisp != tool->gdisp || + paint_tool->context_id < 1) + { + /* initialize the statusbar display */ + paint_tool->context_id = + gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); + } + + /* if this is a new image, reinit the core vals */ + if ((gdisp != tool->gdisp) || ! (bevent->state & GDK_SHIFT_MASK)) + { + /* initialize some values */ + paint_tool->startx = paint_tool->lastx = paint_tool->curx = x; + paint_tool->starty = paint_tool->lasty = paint_tool->cury = y; + paint_tool->startpressure = paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->startytilt = paint_tool->lastytilt = paint_tool->curytilt; + paint_tool->startxtilt = paint_tool->lastxtilt = paint_tool->curxtilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->startwheel = paint_tool->lastwheel = paint_tool->curwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + } + + /* If shift is down and this is not the first paint + * stroke, then draw a line from the last coords to the pointer + */ + else if (bevent->state & GDK_SHIFT_MASK) + { + draw_line = TRUE; + paint_tool->startx = paint_tool->lastx; + paint_tool->starty = paint_tool->lasty; + paint_tool->startpressure = paint_tool->lastpressure; + paint_tool->startxtilt = paint_tool->lastxtilt; + paint_tool->startytilt = paint_tool->lastytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->startwheel = paint_tool->lastwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + + /* Restrict to multiples of 15 degrees if ctrl is pressed */ + if (bevent->state & GDK_CONTROL_MASK) + { + gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; + gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; + gint dx, dy, i, radius, frac; + + dx = paint_tool->curx - paint_tool->lastx; + dy = paint_tool->cury - paint_tool->lasty; + + if (dy) + { + radius = sqrt (SQR (dx) + SQR (dy)); + frac = abs ((dx << 8) / dy); + for (i = 0; i < 6; i++) + { + if (frac < tangens2[i]) + break; + } + dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); + dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); + } + paint_tool->curx = paint_tool->lastx + dx; + paint_tool->cury = paint_tool->lasty + dy; + } + } + + tool->state = ACTIVE; + tool->gdisp = gdisp; + tool->paused_count = 0; + + /* pause the current selection and grab the pointer */ + gdisplays_selection_visibility (gdisp->gimage, SelectionPause); + + /* add motion memory if perfectmouse is set */ + if (perfectmouse != 0) + gdk_pointer_grab (gdisp->canvas->window, FALSE, + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, NULL, bevent->time); + else + gdk_pointer_grab (gdisp->canvas->window, FALSE, + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, NULL, bevent->time); + + /* Let the specific painting function initialize itself */ + gimp_paint_tool_paint(paint_tool, drawable, INIT_PAINT); + + if (paint_tool->pick_colors + && !(bevent->state & GDK_SHIFT_MASK) + && (bevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) + { + gimp_paint_tool_sample_color (drawable, x, y, bevent->state); + paint_tool->pick_state = TRUE; + return; + } + else + paint_tool->pick_state = FALSE; + + /* store the current brush pointer */ + current_brush = paint_tool->brush; + + /* Paint to the image */ + if (draw_line) + { + gimp_draw_tool_pause (GIMP_DRAW_TOOL(paint_tool)); + gimp_paint_tool_interpolate (paint_tool, drawable); + + paint_tool->lastx = paint_tool->curx; + paint_tool->lasty = paint_tool->cury; + paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->lastxtilt = paint_tool->curxtilt; + paint_tool->lastytilt = paint_tool->curytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->lastwheel = paint_tool->curwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + } + else + { + /* If we current point == last point, check if the brush + * wants to be painted in that case. (Direction dependent + * pixmap brush pipes don't, as they don't know which + * pixmap to select.) + */ + if (paint_tool->lastx != paint_tool->curx + || paint_tool->lasty != paint_tool->cury + || (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->want_null_motion) (paint_tool)) + { + if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) + paint_tool->brush = + (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->select_brush) (paint_tool); + + gimp_paint_tool_paint(paint_tool, drawable, MOTION_PAINT); + } + } + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, drawable, PRETRACE_PAINT); + + gdisplay_flush_now (gdisp); + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, drawable, POSTTRACE_PAINT); + + /* restore the current brush pointer */ + paint_tool->brush = current_brush; +} + +void +gimp_paint_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GImage *gimage; + GimpPaintTool *paint_tool; + + gimage = gdisp->gimage; + paint_tool = GIMP_PAINT_TOOL(tool); + + /* resume the current selection and ungrab the pointer */ + gdisplays_selection_visibility (gdisp->gimage, SelectionResume); + + gdk_pointer_ungrab (bevent->time); + gdk_flush (); + + /* Let the specific painting function finish up */ + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), + FINISH_PAINT); + + /* Set tool state to inactive -- no longer painting */ + gimp_draw_tool_stop (GIMP_DRAW_TOOL(paint_tool)); + tool->state = INACTIVE; + + paint_tool->pick_state = FALSE; + + gimp_paint_tool_finish (paint_tool, gimp_image_active_drawable (gdisp->gimage)); + gdisplays_flush (); +} + +void +gimp_paint_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpPaintTool *paint_tool; + + paint_tool = GIMP_PAINT_TOOL(tool); + + gdisplay_untransform_coords_f (gdisp, (double) mevent->x, (double) mevent->y, + &paint_tool->curx, &paint_tool->cury, TRUE); + + if (paint_tool->pick_state) + { + gimp_paint_tool_sample_color (gimp_image_active_drawable (gdisp->gimage), + paint_tool->curx, paint_tool->cury, + mevent->state); + return; + } + + paint_tool->curpressure = mevent->pressure; + paint_tool->curxtilt = mevent->xtilt; + paint_tool->curytilt = mevent->ytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = mevent->wheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + paint_tool->state = mevent->state; + + gimp_paint_tool_interpolate (paint_tool, + gimp_image_active_drawable (gdisp->gimage)); + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), + PRETRACE_PAINT); + + gdisplay_flush_now (gdisp); + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), + POSTTRACE_PAINT); + + paint_tool->lastx = paint_tool->curx; + paint_tool->lasty = paint_tool->cury; + paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->lastxtilt = paint_tool->curxtilt; + paint_tool->lastytilt = paint_tool->curytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->lastwheel = paint_tool->curwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ +} + + +/* FIXME: this belongs in the individual tools */ +void +gimp_paint_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpLayer *layer; + GimpPaintTool *paint_tool; + GimpDrawTool *draw_tool; + gint x, y; + gchar status_str[STATUSBAR_SIZE]; + + GdkCursorType ctype = GDK_TOP_LEFT_ARROW; + GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE; + gboolean ctoggle = FALSE; + + paint_tool = GIMP_PAINT_TOOL(tool); + draw_tool = GIMP_DRAW_TOOL(tool); + +/* undraw the current tool */ + gimp_draw_tool_pause (draw_tool); + + if (gdisp != tool->gdisp || paint_tool->context_id < 1) + { + /* initialize the statusbar display */ + paint_tool->context_id = + gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); + } + + if (paint_tool->context_id) + gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), paint_tool->context_id); + + if ((layer = gimp_image_get_active_layer (gdisp->gimage))) + { + /* If shift is down and this is not the first paint stroke, draw a line */ + if (gdisp == tool->gdisp && (mevent->state & GDK_SHIFT_MASK)) + { + gdouble dx, dy, d; + + ctype = GDK_PENCIL; + /* Get the current coordinates */ + gdisplay_untransform_coords_f (gdisp, + (double) mevent->x, + (double) mevent->y, + &paint_tool->curx, + &paint_tool->cury, TRUE); + + dx = paint_tool->curx - paint_tool->lastx; + dy = paint_tool->cury - paint_tool->lasty; + + /* Restrict to multiples of 15 degrees if ctrl is pressed */ + if (mevent->state & GDK_CONTROL_MASK) + { + gint idx = dx; + gint idy = dy; + gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; + gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; + gint i, radius, frac; + + if (idy) + { + radius = sqrt (SQR (idx) + SQR (idy)); + frac = abs ((idx << 8) / idy); + for (i = 0; i < 6; i++) + { + if (frac < tangens2[i]) + break; + } + dx = idx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); + dy = idy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); + } + + paint_tool->curx = paint_tool->lastx + dx; + paint_tool->cury = paint_tool->lasty + dy; + } + + /* show distance in statusbar */ + if (gdisp->dot_for_dot) + { + d = sqrt (SQR (dx) + SQR (dy)); + g_snprintf (status_str, STATUSBAR_SIZE, "%.1f %s", d, _("pixels")); + } + else + { + gchar *format_str = + g_strdup_printf ("%%.%df %s", + gimp_unit_get_digits (gdisp->gimage->unit), + gimp_unit_get_symbol (gdisp->gimage->unit)); + d = (gimp_unit_get_factor (gdisp->gimage->unit) * + sqrt (SQR (dx / gdisp->gimage->xresolution) + + SQR (dy / gdisp->gimage->yresolution))); + + g_snprintf (status_str, STATUSBAR_SIZE, format_str, d); + g_free (format_str); + } + + gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), + paint_tool->context_id, status_str); + + if (draw_tool->gc == NULL) + { + gimp_draw_tool_start (draw_tool, gdisp->canvas->window); + } + else + { + /* is this a bad hack ? */ + draw_tool->paused_count = 0; + gimp_draw_tool_resume (draw_tool); + } + } + /* If Ctrl or Mod1 is pressed, pick colors */ + else if (paint_tool->pick_colors && + !(mevent->state & GDK_SHIFT_MASK) && + (mevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) + { + ctype = GIMP_COLOR_PICKER_CURSOR; + } +#warning this doesnt belong here +#if 0 + /* Set toggle cursors for various paint tools */ + else if (tool->toggled) + { + switch (tool->type) + { + case ERASER: + ctype = GIMP_MOUSE_CURSOR; + cmodifier = CURSOR_MODIFIER_MINUS; + break; + case CONVOLVE: + ctype = GIMP_MOUSE_CURSOR; + cmodifier = CURSOR_MODIFIER_MINUS; + break; + case DODGEBURN: + ctype = GIMP_MOUSE_CURSOR; + ctoggle = TRUE; + break; + default: + ctype = GIMP_MOUSE_CURSOR; + break; + } + } +#endif + /* Normal operation -- no modifier pressed or first stroke */ + else + { + gint off_x, off_y; + + gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); + gdisplay_untransform_coords (gdisp, + (double) mevent->x, (double) mevent->y, + &x, &y, TRUE, FALSE); + + if (x >= off_x && y >= off_y && + x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && + y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) + { + /* One more test--is there a selected region? + * if so, is cursor inside? + */ + if (gimage_mask_is_empty (gdisp->gimage)) + ctype = GIMP_MOUSE_CURSOR; + else if (gimage_mask_value (gdisp->gimage, x, y)) + ctype = GIMP_MOUSE_CURSOR; + } + } + + /* FIXME: install correct cursor */ + /*gdisplay_install_tool_cursor (gdisp, ctype, + ctype == GIMP_COLOR_PICKER_CURSOR ? + COLOR_PICKER : tool->type, + cmodifier, + ctoggle); */ + } +} + +void +gimp_paint_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp) +{ + GimpPaintTool *paint_tool; + GimpDrawable *drawable; + + paint_tool = GIMP_PAINT_TOOL (tool); + drawable = gimp_image_active_drawable (gdisp->gimage); + + switch (action) + { + case PAUSE: + break; + + case RESUME: + break; + + case HALT: + gimp_paint_tool_paint(paint_tool, drawable, FINISH_PAINT); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(tool)); + gimp_paint_tool_cleanup (); + break; + + default: + break; + } +} + +void +gimp_paint_tool_draw (GimpTool *tool) +{ + GDisplay *gdisp; + GimpPaintTool *paint_tool; + GimpDrawTool *draw_tool; + gint tx1, ty1, tx2, ty2; + + + paint_tool = GIMP_PAINT_TOOL(tool); + draw_tool = GIMP_DRAW_TOOL(tool); + + /* if shift was never used, draw_tool->gc is NULL + and we don't care about a redraw */ + if (draw_tool->gc != NULL) + { + gdisp = tool->gdisp; + + gdisplay_transform_coords (gdisp, paint_tool->lastx, paint_tool->lasty, + &tx1, &ty1, 1); + gdisplay_transform_coords (gdisp, paint_tool->curx, paint_tool->cury, + &tx2, &ty2, 1); + + /* Only draw line if it's in the visible area + * thus preventing from drawing rubbish + */ + + if (tx2 > 0 && ty2 > 0) + { + gint offx, offy; + + /* Adjust coords to start drawing from center of pixel if zoom > 1 */ + offx = (int) SCALEFACTOR_X (gdisp) >> 1; + offy = (int) SCALEFACTOR_Y (gdisp) >> 1; + tx1 += offx; + ty1 += offy; + tx2 += offx; + ty2 += offy; + + /* Draw start target */ + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx1 - (TARGET_WIDTH >> 1), ty1, + tx1 + (TARGET_WIDTH >> 1), ty1); + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx1, ty1 - (TARGET_HEIGHT >> 1), + tx1, ty1 + (TARGET_HEIGHT >> 1)); + + /* Draw end target */ + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx2 - (TARGET_WIDTH >> 1), ty2, + tx2 + (TARGET_WIDTH >> 1), ty2); + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx2, ty2 - (TARGET_HEIGHT >> 1), + tx2, ty2 + (TARGET_HEIGHT >> 1)); + + /* Draw the line between the start and end coords */ + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx1, ty1, tx2, ty2); + } + } + return; +} + +static void +gimp_paint_tool_initialize (GimpPaintTool *tool) +{ + tool->pick_colors = FALSE; + tool->flags = 0; + tool->context_id = 0; +} + +static void +gimp_paint_tool_class_init (GimpToolClass *klass) +{ + GtkObjectClass * oc = GTK_OBJECT_CLASS (klass); + GimpPaintToolClass * pc = GIMP_PAINT_TOOL_CLASS (klass); + + g_message ("gimp_paint_tool_class_init"); + + klass->button_press = gimp_paint_tool_button_press; + klass->button_release = gimp_paint_tool_button_release; + klass->motion = gimp_paint_tool_motion; + klass->cursor_update = gimp_paint_tool_cursor_update; + klass->control = gimp_paint_tool_control; + + gimp_paint_tool_signals[PAINT] = + gtk_signal_new ("paint", + GTK_RUN_FIRST, + oc->type, + GTK_SIGNAL_OFFSET (GimpPaintToolClass, + paint_func), + gtk_marshal_NONE__POINTER_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_INT); + + gtk_object_class_add_signals (oc, gimp_paint_tool_signals, LAST_SIGNAL); + + pc->paint_func = (PaintFunc) standard_paint_func; + +} + +void +gimp_paint_tool_paint (GimpPaintTool *tool, GimpDrawable *drawable, PaintState state) +{ + gtk_signal_emit (GTK_OBJECT(tool), gimp_paint_tool_signals[PAINT], drawable, state); +} + +void +gimp_paint_tool_destroy (GimpTool *tool) +{ + GimpPaintTool * paint_tool; + GimpDrawTool * draw_tool; + + + paint_tool = GIMP_PAINT_TOOL (tool); + draw_tool = GIMP_DRAW_TOOL (tool); + + /* Make sure the selection core is not visible */ + if (tool->state == ACTIVE) + gimp_draw_tool_stop (draw_tool); + + /* Cleanup memory */ + gimp_paint_tool_cleanup (); +} + +gboolean +gimp_paint_tool_start (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gdouble x, + gdouble y) +{ + static GimpBrush *brush = NULL; + + paint_tool->curx = x; + paint_tool->cury = y; + + /* Set up some defaults for non-gui use */ + if (paint_tool == &non_gui_paint_tool) + { + paint_tool->startpressure = paint_tool->lastpressure = paint_tool->curpressure = 0.5; + paint_tool->startxtilt = paint_tool->lastxtilt = paint_tool->curxtilt = 0; + paint_tool->startytilt = paint_tool->lastytilt = paint_tool->curytilt = 0; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->startwheel = paint_tool->lastwheel = paint_tool->curwheel = 0.5; +#endif /* GTK_HAVE_SIX_VALUATORS */ + } + + /* Each buffer is the same size as the maximum bounds of the active brush... */ + if (brush && brush != gimp_context_get_brush (NULL)) + { + gtk_signal_disconnect_by_func (GTK_OBJECT (brush), + GTK_SIGNAL_FUNC (gimp_paint_tool_invalidate_cache), + NULL); + gtk_object_unref (GTK_OBJECT (brush)); + } + if (!(brush = gimp_context_get_brush (NULL))) + { + g_message (_("No brushes available for use with this tool.")); + return FALSE; + } + + gtk_object_ref (GTK_OBJECT (brush)); + gtk_signal_connect (GTK_OBJECT (brush), "invalidate_preview", + GTK_SIGNAL_FUNC (gimp_paint_tool_invalidate_cache), + NULL); + + paint_tool->spacing = (double) gimp_brush_get_spacing (brush) / 100.0; + + paint_tool->brush = brush; + + /* free the block structures */ + if (undo_tiles) + tile_manager_destroy (undo_tiles); + if (canvas_tiles) + tile_manager_destroy (canvas_tiles); + + /* Allocate the undo structure */ + undo_tiles = tile_manager_new (gimp_drawable_width (drawable), + gimp_drawable_height (drawable), + gimp_drawable_bytes (drawable)); + + /* Allocate the canvas blocks structure */ + canvas_tiles = tile_manager_new (gimp_drawable_width (drawable), + gimp_drawable_height (drawable), 1); + + /* Get the initial undo extents */ + paint_tool->x1 = paint_tool->x2 = paint_tool->curx; + paint_tool->y1 = paint_tool->y2 = paint_tool->cury; + paint_tool->distance = 0.0; + paint_tool->pixel_dist = 0.0; + + return TRUE; +} + +void +gimp_paint_tool_interpolate (GimpPaintTool *paint_tool, + GimpDrawable *drawable) +{ + GimpBrush *current_brush; + GimpVector2 delta; + gdouble dpressure, dxtilt, dytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble dwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + /* double spacing; */ + /* double lastscale, curscale; */ + gdouble n; + gdouble left; + gdouble t; + gdouble initial; + gdouble dist; + gdouble total; + gdouble pixel_dist; + gdouble pixel_initial; + gdouble xd, yd; + gdouble mag; + + delta.x = paint_tool->curx - paint_tool->lastx; + delta.y = paint_tool->cury - paint_tool->lasty; + dpressure = paint_tool->curpressure - paint_tool->lastpressure; + dxtilt = paint_tool->curxtilt - paint_tool->lastxtilt; + dytilt = paint_tool->curytilt - paint_tool->lastytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + dwheel = paint_tool->curwheel - paint_tool->lastwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + +/* return if there has been no motion */ +#ifdef GTK_HAVE_SIX_VALUATORS + if (!delta.x && !delta.y && !dpressure && !dxtilt && !dytilt && !dwheel) +#else /* !GTK_HAVE_SIX_VALUATORS */ + if (!delta.x && !delta.y && !dpressure && !dxtilt && !dytilt) +#endif /* GTK_HAVE_SIX_VALUATORS */ + return; + + /* calculate the distance traveled in the coordinate space of the brush */ + mag = gimp_vector2_length (&(paint_tool->brush->x_axis)); + xd = gimp_vector2_inner_product (&delta, + &(paint_tool->brush->x_axis)) / (mag*mag); + + mag = gimp_vector2_length (&(paint_tool->brush->y_axis)); + yd = gimp_vector2_inner_product (&delta, + &(paint_tool->brush->y_axis)) / (mag*mag); + + dist = 0.5 * sqrt (xd*xd + yd*yd); + total = dist + paint_tool->distance; + initial = paint_tool->distance; + + pixel_dist = gimp_vector2_length (&delta); + pixel_initial = paint_tool->pixel_dist; + + /* FIXME: need to adapt the spacing to the size */ + /* lastscale = MIN (gimp_paint_tool->lastpressure, 1/256); */ + /* curscale = MIN (gimp_paint_tool->curpressure, 1/256); */ + /* spacing = gimp_paint_tool->spacing * sqrt (0.5 * (lastscale + curscale)); */ + + while (paint_tool->distance < total) + { + n = (gint) (paint_tool->distance / paint_tool->spacing + 1.0 + EPSILON); + left = n * paint_tool->spacing - paint_tool->distance; + + paint_tool->distance += left; + + if (paint_tool->distance <= (total+EPSILON)) + { + t = (paint_tool->distance - initial) / dist; + + paint_tool->curx = paint_tool->lastx + delta.x * t; + paint_tool->cury = paint_tool->lasty + delta.y * t; + paint_tool->pixel_dist = pixel_initial + pixel_dist * t; + paint_tool->curpressure = paint_tool->lastpressure + dpressure * t; + paint_tool->curxtilt = paint_tool->lastxtilt + dxtilt * t; + paint_tool->curytilt = paint_tool->lastytilt + dytilt * t; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = paint_tool->lastwheel + dwheel * t; +#endif /* GTK_HAVE_SIX_VALUATORS */ + + /* save the current brush */ + current_brush = paint_tool->brush; + + if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) + paint_tool->brush = + (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->select_brush) (paint_tool); + gimp_paint_tool_paint(paint_tool, drawable, MOTION_PAINT); + + /* restore the current brush pointer */ + paint_tool->brush = current_brush; + } + } + + paint_tool->distance = total; + paint_tool->pixel_dist = pixel_initial + pixel_dist; + paint_tool->curx = paint_tool->lastx + delta.x; + paint_tool->cury = paint_tool->lasty + delta.y; + paint_tool->curpressure = paint_tool->lastpressure + dpressure; + paint_tool->curxtilt = paint_tool->lastxtilt + dxtilt; + paint_tool->curytilt = paint_tool->lastytilt + dytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = paint_tool->lastwheel + dwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ +} + +void +gimp_paint_tool_finish (GimpPaintTool *paint_tool, + GimpDrawable *drawable) +{ + GImage *gimage; + PaintUndo *pu; + + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + /* Determine if any part of the image has been altered-- + * if nothing has, then just return... + */ + + if ((paint_tool->x2 == paint_tool->x1) || + (paint_tool->y2 == paint_tool->y1)) + return; + + undo_push_group_start (gimage, PAINT_CORE_UNDO); + + pu = g_new (PaintUndo, 1); + pu->tool = paint_tool; + pu->lastx = paint_tool->startx; + pu->lasty = paint_tool->starty; + pu->lastpressure = paint_tool->startpressure; + pu->lastxtilt = paint_tool->startxtilt; + pu->lastytilt = paint_tool->startytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + pu->lastwheel = paint_tool->startwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + + /* Push a paint undo */ + undo_push_paint (gimage, pu); + + /* push an undo */ + drawable_apply_image (drawable, paint_tool->x1, paint_tool->y1, + paint_tool->x2, paint_tool->y2, undo_tiles, TRUE); + undo_tiles = NULL; + + /* push the group end */ + undo_push_group_end (gimage); + + /* invalidate the drawable--have to do it here, because + * it is not done during the actual painting. + */ + gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable)); +} + +void +gimp_paint_tool_cleanup (void) +{ + /* CLEANUP */ + /* If the undo tiles exist, nuke them */ + if (undo_tiles) + { + tile_manager_destroy (undo_tiles); + undo_tiles = NULL; + } + + /* If the canvas blocks exist, nuke them */ + if (canvas_tiles) + { + tile_manager_destroy (canvas_tiles); + canvas_tiles = NULL; + } + + /* Free the temporary buffers if they exist */ + free_paint_buffers (); +} + +void +gimp_paint_tool_get_color_from_gradient (GimpPaintTool *paint_tool, + gdouble gradient_length, + GimpRGB *color, + GradientPaintMode mode) +{ + gdouble y; + gdouble distance; /* distance in current brush stroke */ + + distance = paint_tool->pixel_dist; + y = ((double) distance / gradient_length); + + /* for the once modes, set y close to 1.0 after the first chunk */ + if ( (mode == ONCE_FORWARD || mode == ONCE_BACKWARDS) && y >= 1.0 ) + y = 0.9999999; + + if ( (((int)y & 1) && mode != LOOP_SAWTOOTH) || mode == ONCE_BACKWARDS ) + y = 1.0 - (y - (int)y); + else + y = y - (int)y; + + gimp_gradient_get_color_at (gimp_context_get_gradient (NULL), y, color); +} + + +/************************/ +/* Painting functions */ +/************************/ + +TempBuf * +gimp_paint_tool_get_paint_area (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gdouble scale) +{ + gint x, y; + gint x1, y1, x2, y2; + gint bytes; + gint dwidth, dheight; + gint bwidth, bheight; + + bytes = gimp_drawable_has_alpha (drawable) ? + gimp_drawable_bytes (drawable) : gimp_drawable_bytes (drawable) + 1; + + gimp_paint_tool_calculate_brush_size (paint_tool->brush->mask, scale, + &bwidth, &bheight); + + /* adjust the x and y coordinates to the upper left corner of the brush */ + x = (gint) floor (paint_tool->curx) - (bwidth >> 1); + y = (gint) floor (paint_tool->cury) - (bheight >> 1); + + dwidth = gimp_drawable_width (drawable); + dheight = gimp_drawable_height (drawable); + + x1 = CLAMP (x - 1, 0, dwidth); + y1 = CLAMP (y - 1, 0, dheight); + x2 = CLAMP (x + bwidth + 1, 0, dwidth); + y2 = CLAMP (y + bheight + 1, 0, dheight); + + /* configure the canvas buffer */ + if ((x2 - x1) && (y2 - y1)) + canvas_buf = temp_buf_resize (canvas_buf, bytes, x1, y1, + (x2 - x1), (y2 - y1)); + else + return NULL; + + return canvas_buf; +} + +TempBuf * +gimp_paint_tool_get_orig_image (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint x1, + gint y1, + gint x2, + gint y2) +{ + PixelRegion srcPR; + PixelRegion destPR; + Tile *undo_tile; + gint h; + gint refd; + gint pixelwidth; + gint dwidth; + gint dheight; + guchar *s; + guchar *d; + gpointer pr; + + orig_buf = temp_buf_resize (orig_buf, gimp_drawable_bytes (drawable), + x1, y1, (x2 - x1), (y2 - y1)); + + dwidth = gimp_drawable_width (drawable); + dheight = gimp_drawable_height (drawable); + + x1 = CLAMP (x1, 0, dwidth); + y1 = CLAMP (y1, 0, dheight); + x2 = CLAMP (x2, 0, dwidth); + y2 = CLAMP (y2, 0, dheight); + + /* configure the pixel regions */ + pixel_region_init (&srcPR, gimp_drawable_data (drawable), x1, y1, + (x2 - x1), (y2 - y1), FALSE); + destPR.bytes = orig_buf->bytes; + destPR.x = 0; destPR.y = 0; + destPR.w = (x2 - x1); destPR.h = (y2 - y1); + destPR.rowstride = orig_buf->bytes * orig_buf->width; + destPR.data = temp_buf_data (orig_buf) + + (y1 - orig_buf->y) * destPR.rowstride + (x1 - orig_buf->x) * destPR.bytes; + + for (pr = pixel_regions_register (2, &srcPR, &destPR); + pr != NULL; + pr = pixel_regions_process (pr)) + { + /* If the undo tile corresponding to this location is valid, use it */ + undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y, + FALSE, FALSE); + if (tile_is_valid (undo_tile) == TRUE) + { + refd = 1; + undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y, + TRUE, FALSE); + s = (unsigned char*)tile_data_pointer (undo_tile, 0, 0) + + srcPR.rowstride * (srcPR.y % TILE_HEIGHT) + + srcPR.bytes * (srcPR.x % TILE_WIDTH); /* dubious... */ + } + else + { + refd = 0; + s = srcPR.data; + } + + d = destPR.data; + pixelwidth = srcPR.w * srcPR.bytes; + h = srcPR.h; + while (h --) + { + memcpy (d, s, pixelwidth); + s += srcPR.rowstride; + d += destPR.rowstride; + } + + if (refd) + tile_release (undo_tile, FALSE); + } + + return orig_buf; +} + +void +gimp_paint_tool_paste_canvas (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode) +{ + MaskBuf *brush_mask; + + /* get the brush mask */ + brush_mask = gimp_paint_tool_get_brush_mask (paint_tool, + brush_hardness, brush_scale); + + /* paste the canvas buf */ + gimp_paint_tool_paste (paint_tool, brush_mask, drawable, + brush_opacity, image_opacity, paint_mode, mode); +} + +/* Similar to gimp_paint_tool_paste_canvas, but replaces the alpha channel + rather than using it to composite (i.e. transparent over opaque + becomes transparent rather than opauqe. */ +void +gimp_paint_tool_replace_canvas (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode) +{ + MaskBuf *brush_mask; + + /* get the brush mask */ + brush_mask = + gimp_paint_tool_get_brush_mask (paint_tool, brush_hardness, brush_scale); + + /* paste the canvas buf */ + gimp_paint_tool_replace (paint_tool, brush_mask, drawable, + brush_opacity, image_opacity, mode); +} + + +static void +gimp_paint_tool_invalidate_cache (GimpBrush *brush, + gpointer data) +{ + /* Make sure we don't cache data for a brush that has changed */ + if (last_brush_mask == brush->mask) + cache_invalid = TRUE; +} + +/************************************************************ + * LOCAL FUNCTION DEFINITIONS * + ************************************************************/ + +static void +gimp_paint_tool_calculate_brush_size (MaskBuf *mask, + gdouble scale, + gint *width, + gint *height) +{ + scale = CLAMP (scale, 0.0, 1.0); + + if (current_device == GDK_CORE_POINTER) + { + *width = mask->width; + *height = mask->height; + } + else + { + gdouble ratio; + + if (scale < 1 / 256) + ratio = 1 / 16; + else + ratio = sqrt (scale); + + *width = MAX ((gint) (mask->width * ratio + 0.5), 1); + *height = MAX ((gint) (mask->height * ratio + 0.5), 1); + } +} + +static MaskBuf * +gimp_paint_tool_subsample_mask (MaskBuf *mask, + gdouble x, + gdouble y) +{ + MaskBuf *dest; + gdouble left; + guchar *m; + guchar *d; + const gint *k; + gint index1; + gint index2; + const gint *kernel; + gint new_val; + gint i, j; + gint r, s; + + x += (x < 0) ? mask->width : 0; + left = x - floor (x); + index1 = (gint) (left * (gdouble) (SUBSAMPLE + 1)); + + y += (y < 0) ? mask->height : 0; + left = y - floor (y); + index2 = (gint) (left * (gdouble) (SUBSAMPLE + 1)); + + kernel = subsample[index2][index1]; + + if (mask == last_brush_mask && !cache_invalid) + { + if (kernel_brushes[index2][index1]) + return kernel_brushes[index2][index1]; + } + else + { + for (i = 0; i <= SUBSAMPLE; i++) + for (j = 0; j <= SUBSAMPLE; j++) + { + if (kernel_brushes[i][j]) + mask_buf_free (kernel_brushes[i][j]); + + kernel_brushes[i][j] = NULL; + } + + last_brush_mask = mask; + cache_invalid = FALSE; + } + + dest = kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, + mask->height + 2); + + m = mask_buf_data (mask); + for (i = 0; i < mask->height; i++) + { + for (j = 0; j < mask->width; j++) + { + k = kernel; + for (r = 0; r < KERNEL_HEIGHT; r++) + { + d = mask_buf_data (dest) + (i+r) * dest->width + j; + s = KERNEL_WIDTH; + while (s--) + { + new_val = *d + ((*m * *k++ + 128) >> 8); + *d++ = MIN (new_val, 255); + } + } + m++; + } + } + + return dest; +} + +/* #define FANCY_PRESSURE */ + +static MaskBuf * +gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask, + gdouble x, + gdouble y, + gdouble pressure) +{ + static MaskBuf *last_brush = NULL; + static guchar mapi[256]; + guchar *source; + guchar *dest; + MaskBuf *subsample_mask; + gint i; +#ifdef FANCY_PRESSURE + static gdouble map[256]; + gdouble ds, s, c; +#endif + + /* Get the raw subsampled mask */ + subsample_mask = gimp_paint_tool_subsample_mask (brush_mask, x, y); + + /* Special case pressure = 0.5 */ + if ((int)(pressure * 100 + 0.5) == 50) + return subsample_mask; + + /* Make sure we have the right sized buffer */ + if (brush_mask != last_brush) + { + if (pressure_brush) + mask_buf_free (pressure_brush); + + pressure_brush = mask_buf_new (brush_mask->width + 2, + brush_mask->height + 2); + } + +#ifdef FANCY_PRESSURE + /* Create the pressure profile + + It is: I'(I) = tanh(20*(pressure-0.5)*I) : pressure > 0.5 + I'(I) = 1 - tanh(20*(0.5-pressure)*(1-I)) : pressure < 0.5 + + It looks like: + + low pressure medium pressure high pressure + + | / -- + | / / + / / | + -- / | + + */ + + ds = (pressure - 0.5)*(20./256.); + s = 0; + c = 1.0; + + if (ds > 0) + { + for (i=0;i<256;i++) + { + map[i] = s/c; + s += c*ds; + c += s*ds; + } + for (i=0;i<256;i++) + mapi[i] = (int)(255*map[i]/map[255]); + } + else + { + ds = -ds; + for (i=255;i>=0;i--) + { + map[i] = s/c; + s += c*ds; + c += s*ds; + } + for (i=0;i<256;i++) + mapi[i] = (int)(255*(1-map[i]/map[0])); + } +#else /* ! FANCY_PRESSURE */ + + for (i = 0; i < 256; i++) + { + gint tmp = (pressure / 0.5) * i; + + if (tmp > 255) + mapi[i] = 255; + else + mapi[i] = tmp; + } + +#endif /* FANCY_PRESSURE */ + + /* Now convert the brush */ + + source = mask_buf_data (subsample_mask); + dest = mask_buf_data (pressure_brush); + + i = subsample_mask->width * subsample_mask->height; + while (i--) + { + *dest++ = mapi[(*source++)]; + } + + return pressure_brush; +} + +static MaskBuf * +gimp_paint_tool_solidify_mask (MaskBuf *brush_mask) +{ + static MaskBuf *last_brush = NULL; + gint i; + gint j; + guchar *data; + guchar *src; + + if (brush_mask == last_brush && !cache_invalid) + return solid_brush; + + last_brush = brush_mask; + + if (solid_brush) + mask_buf_free (solid_brush); + + solid_brush = mask_buf_new (brush_mask->width + 2, brush_mask->height + 2); + + /* get the data and advance one line into it */ + data = mask_buf_data (solid_brush) + solid_brush->width; + src = mask_buf_data (brush_mask); + + for (i = 0; i < brush_mask->height; i++) + { + data++; + for (j = 0; j < brush_mask->width; j++) + { + *data++ = (*src++) ? OPAQUE_OPACITY : TRANSPARENT_OPACITY; + } + data++; + } + + return solid_brush; +} + +static MaskBuf * +gimp_paint_tool_scale_mask (MaskBuf *brush_mask, + gdouble scale) +{ + static MaskBuf *last_brush = NULL; + static gint last_width = 0.0; + static gint last_height = 0.0; + gint dest_width; + gint dest_height; + + scale = CLAMP (scale, 0.0, 1.0); + + if (scale == 0.0) + return NULL; + + if (scale == 1.0) + return brush_mask; + + gimp_paint_tool_calculate_brush_size (brush_mask, scale, + &dest_width, &dest_height); + + if (brush_mask == last_brush && !cache_invalid && + dest_width == last_width && dest_height == last_height) + return scale_brush; + + if (scale_brush) + mask_buf_free (scale_brush); + + last_brush = brush_mask; + last_width = dest_width; + last_height = dest_height; + + scale_brush = brush_scale_mask (brush_mask, dest_width, dest_height); + cache_invalid = TRUE; + + return scale_brush; +} + +static MaskBuf * +gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask, + gdouble scale) +{ + static MaskBuf *last_brush = NULL; + static gint last_width = 0.0; + static gint last_height = 0.0; + gint dest_width; + gint dest_height; + + scale = CLAMP (scale, 0.0, 1.0); + + if (scale == 0.0) + return NULL; + + if (scale == 1.0) + return brush_mask; + + gimp_paint_tool_calculate_brush_size (brush_mask, scale, + &dest_width, &dest_height); + + if (brush_mask == last_brush && !cache_invalid && + dest_width == last_width && dest_height == last_height) + return scale_pixmap; + + if (scale_pixmap) + mask_buf_free (scale_pixmap); + + last_brush = brush_mask; + last_width = dest_width; + last_height = dest_height; + + scale_pixmap = brush_scale_pixmap (brush_mask, dest_width, dest_height); + cache_invalid = TRUE; + + return scale_pixmap; +} + +static MaskBuf * +gimp_paint_tool_get_brush_mask (GimpPaintTool *paint_tool, + BrushApplicationMode brush_hardness, + gdouble scale) +{ + MaskBuf *mask; + + if (current_device == GDK_CORE_POINTER) + mask = paint_tool->brush->mask; + else + mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale); + + switch (brush_hardness) + { + case SOFT: + mask = gimp_paint_tool_subsample_mask (mask, + paint_tool->curx, paint_tool->cury); + break; + case HARD: + mask = gimp_paint_tool_solidify_mask (mask); + break; + case PRESSURE: + mask = gimp_paint_tool_pressurize_mask (mask, + paint_tool->curx, paint_tool->cury, + paint_tool->curpressure); + break; + default: + break; + } + + return mask; +} + +static void +gimp_paint_tool_paste (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + PaintApplicationMode mode) +{ + GimpImage *gimage; + PixelRegion srcPR; + TileManager *alt = NULL; + gint offx; + gint offy; + + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + /* set undo blocks */ + set_undo_tiles (drawable, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + /* If the mode is CONSTANT: + * combine the canvas buf, the brush mask to the canvas tiles + */ + if (mode == CONSTANT) + { + /* initialize any invalid canvas tiles */ + set_canvas_tiles (canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity); + canvas_tiles_to_canvas_buf (paint_tool); + alt = undo_tiles; + } + /* Otherwise: + * combine the canvas buf and the brush mask to the canvas buf + */ + else + { + brush_to_canvas_buf (paint_tool, brush_mask, brush_opacity); + } + + /* intialize canvas buf source pixel regions */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + /* apply the paint area to the gimage */ + gimp_image_apply_image (gimage, drawable, &srcPR, + FALSE, image_opacity, paint_mode, + alt, /* specify an alternative src1 */ + canvas_buf->x, canvas_buf->y); + + /* Update the undo extents */ + paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x); + paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y); + paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width)); + paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height)); + + /* Update the gimage--it is important to call gdisplays_update_area + * instead of drawable_update because we don't want the drawable + * preview to be constantly invalidated + */ + gimp_drawable_offsets (drawable, &offx, &offy); + gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, + canvas_buf->width, canvas_buf->height); +} + +/* This works similarly to gimp_paint_tool_paste. However, instead of combining + the canvas to the paint core drawable using one of the combination + modes, it uses a "replace" mode (i.e. transparent pixels in the + canvas erase the paint core drawable). + + When not drawing on alpha-enabled images, it just paints using NORMAL + mode. +*/ +static void +gimp_paint_tool_replace (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + PaintApplicationMode mode) +{ + GimpImage *gimage; + PixelRegion srcPR; + PixelRegion maskPR; + TileManager *alt = NULL; + gint offx; + gint offy; + + if (! gimp_drawable_has_alpha (drawable)) + { + gimp_paint_tool_paste (paint_tool, brush_mask, drawable, + brush_opacity, image_opacity, NORMAL_MODE, + mode); + return; + } + + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + /* set undo blocks */ + set_undo_tiles (drawable, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + if (mode == CONSTANT) + { + /* initialize any invalid canvas tiles */ + set_canvas_tiles (canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + /* combine the brush mask and the canvas tiles */ + brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity); + + /* set the alt source as the unaltered undo_tiles */ + alt = undo_tiles; + + /* initialize the maskPR from the canvas tiles */ + pixel_region_init (&maskPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, FALSE); + } + else + { + /* The mask is just the brush mask */ + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = canvas_buf->width; + maskPR.h = canvas_buf->height; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask); + } + + /* intialize canvas buf source pixel regions */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + /* apply the paint area to the gimage */ + gimp_image_replace_image (gimage, drawable, &srcPR, + FALSE, image_opacity, + &maskPR, + canvas_buf->x, canvas_buf->y); + + /* Update the undo extents */ + paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x); + paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y); + paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width)); + paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height)); + + /* Update the gimage--it is important to call gdisplays_update_area + * instead of drawable_update because we don't want the drawable + * preview to be constantly invalidated + */ + gimp_drawable_offsets (drawable, &offx, &offy); + gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, + canvas_buf->width, canvas_buf->height); +} + +static void +canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool) +{ + PixelRegion srcPR; + PixelRegion maskPR; + + /* combine the canvas tiles and the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + pixel_region_init (&maskPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, FALSE); + + /* apply the canvas tiles to the canvas buf */ + apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); +} + +static void +brush_to_canvas_tiles (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + /* combine the brush mask and the canvas tiles */ + pixel_region_init (&srcPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, TRUE); + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* combine the mask to the canvas tiles */ + combine_mask_and_region (&srcPR, &maskPR, brush_opacity); +} + +static void +brush_to_canvas_buf (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + /* combine the canvas buf and the brush mask to the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* apply the mask */ + apply_mask_to_region (&srcPR, &maskPR, brush_opacity); +} + +#if 0 +static void +paint_to_canvas_tiles (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + /* combine the brush mask and the canvas tiles */ + pixel_region_init (&srcPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, TRUE); + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* combine the mask and canvas tiles */ + combine_mask_and_region (&srcPR, &maskPR, brush_opacity); + + /* combine the canvas tiles and the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + pixel_region_init (&maskPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, FALSE); + + /* apply the canvas tiles to the canvas buf */ + apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); +} + +static void +paint_to_canvas_buf (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + + /* combine the canvas buf and the brush mask to the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* apply the mask */ + apply_mask_to_region (&srcPR, &maskPR, brush_opacity); +} +#endif + +static void +set_undo_tiles (GimpDrawable *drawable, + gint x, + gint y, + gint w, + gint h) +{ + gint i; + gint j; + Tile *src_tile; + Tile *dest_tile; + + if (undo_tiles == NULL) + { + g_warning ("set_undo_tiles: undo_tiles is null"); + return; + } + + for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) + { + for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) + { + dest_tile = tile_manager_get_tile (undo_tiles, j, i, FALSE, FALSE); + if (tile_is_valid (dest_tile) == FALSE) + { + src_tile = tile_manager_get_tile (gimp_drawable_data (drawable), + j, i, TRUE, FALSE); + tile_manager_map_tile (undo_tiles, j, i, src_tile); + tile_release (src_tile, FALSE); + } + } + } +} + +static void +set_canvas_tiles (gint x, + gint y, + gint w, + gint h) +{ + gint i; + gint j; + Tile *tile; + + for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) + { + for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) + { + tile = tile_manager_get_tile (canvas_tiles, j, i, FALSE, FALSE); + if (tile_is_valid (tile) == FALSE) + { + tile = tile_manager_get_tile (canvas_tiles, j, i, TRUE, TRUE); + memset (tile_data_pointer (tile, 0, 0), 0, tile_size (tile)); + tile_release (tile, TRUE); + } + } + } +} + + +/*****************************************************/ +/* Paint buffers utility functions */ +/*****************************************************/ + + +static void +free_paint_buffers (void) +{ + if (orig_buf) + temp_buf_free (orig_buf); + orig_buf = NULL; + + if (canvas_buf) + temp_buf_free (canvas_buf); + canvas_buf = NULL; +} + + +/**************************************************/ +/* Brush pipe utility functions */ +/**************************************************/ + +void +gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *paint_tool, + GimpImage *dest, + GimpDrawable *drawable, + TempBuf *area, + gdouble scale, + BrushApplicationMode mode) +{ + PixelRegion destPR; + void *pr; + guchar *d; + gint ulx; + gint uly; + gint offsetx; + gint offsety; + gint y; + TempBuf *pixmap_mask; + TempBuf *brush_mask; + + g_return_if_fail (GIMP_IS_BRUSH (paint_tool->brush)); + g_return_if_fail (paint_tool->brush->pixmap != NULL); + + /* scale the brushes */ + pixmap_mask = gimp_paint_tool_scale_pixmap (paint_tool->brush->pixmap, scale); + + if (mode == SOFT) + brush_mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale); + else + brush_mask = NULL; + + destPR.bytes = area->bytes; + destPR.x = 0; + destPR.y = 0; + destPR.w = area->width; + destPR.h = area->height; + destPR.rowstride = destPR.bytes * area->width; + destPR.data = temp_buf_data (area); + + pr = pixel_regions_register (1, &destPR); + + /* Calculate upper left corner of brush as in + * gimp_paint_tool_get_paint_area. Ugly to have to do this here, too. + */ + + ulx = (gint) floor (paint_tool->curx) - (pixmap_mask->width >> 1); + uly = (gint) floor (paint_tool->cury) - (pixmap_mask->height >> 1); + + offsetx = area->x - ulx; + offsety = area->y - uly; + + for (; pr != NULL; pr = pixel_regions_process (pr)) + { + d = destPR.data; + for (y = 0; y < destPR.h; y++) + { + paint_line_pixmap_mask (dest, drawable, pixmap_mask, brush_mask, + d, offsetx, y + offsety, + destPR.bytes, destPR.w, mode); + d += destPR.rowstride; + } + } +} + +static void +paint_line_pixmap_mask (GimpImage *dest, + GimpDrawable *drawable, + TempBuf *pixmap_mask, + TempBuf *brush_mask, + guchar *d, + gint x, + gint y, + gint bytes, + gint width, + BrushApplicationMode mode) +{ + guchar *b; + guchar *p; + guchar *mask; + gdouble alpha; + gdouble factor = 0.00392156986; /* 1.0 / 255.0 */ + gint x_index; + gint i,byte_loop; + + /* Make sure x, y are positive */ + while (x < 0) + x += pixmap_mask->width; + while (y < 0) + y += pixmap_mask->height; + + /* Point to the approriate scanline */ + b = temp_buf_data (pixmap_mask) + + (y % pixmap_mask->height) * pixmap_mask->width * pixmap_mask->bytes; + + if (mode == SOFT && brush_mask) + { + /* ditto, except for the brush mask, so we can pre-multiply the alpha value */ + mask = temp_buf_data (brush_mask) + + (y % brush_mask->height) * brush_mask->width; + for (i = 0; i < width; i++) + { + /* attempt to avoid doing this calc twice in the loop */ + x_index = ((i + x) % pixmap_mask->width); + p = b + x_index * pixmap_mask->bytes; + d[bytes-1] = mask[x_index]; + + /* multiply alpha into the pixmap data */ + /* maybe we could do this at tool creation or brush switch time? */ + /* and compute it for the whole brush at once and cache it? */ + alpha = d[bytes-1] * factor; + if(alpha) + for (byte_loop = 0; byte_loop < bytes - 1; byte_loop++) + d[byte_loop] *= alpha; + + /* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */ + gimp_image_transform_color (dest, drawable, p, d, RGB); + d += bytes; + } + } + else + { + for (i = 0; i < width; i++) + { + /* attempt to avoid doing this calc twice in the loop */ + x_index = ((i + x) % pixmap_mask->width); + p = b + x_index * pixmap_mask->bytes; + d[bytes-1] = 255; + + /* multiply alpha into the pixmap data */ + /* maybe we could do this at tool creation or brush switch time? */ + /* and compute it for the whole brush at once and cache it? */ + gimp_image_transform_color (dest, drawable, p, d, RGB); + d += bytes; + } + } +} diff --git a/app/tools/gimpbrushtool.h b/app/tools/gimpbrushtool.h new file mode 100644 index 0000000000..9b1fc62c81 --- /dev/null +++ b/app/tools/gimpbrushtool.h @@ -0,0 +1,219 @@ +/* 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 __GIMP_PAINT_TOOL_H__ +#define __GIMP_PAINT_TOOL_H__ + +#include "tools/gimpdrawtool.h" + +#define GIMP_TYPE_PAINT_TOOL (gimp_paint_tool_get_type ()) +#define GIMP_PAINT_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_PAINT_TOOL, GimpPaintTool)) +#define GIMP_IS_PAINT_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_PAINT_TOOL)) +#define GIMP_PAINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PAINT_TOOL, GimpPaintToolClass)) +#define GIMP_IS_PAINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PAINT_TOOL)) + +GtkType gimp_paint_tool_get_type (void); + +/* the different states that the painting function can be called with */ + +typedef enum /*< skip >*/ +{ + INIT_PAINT, /* Setup PaintFunc internals */ + MOTION_PAINT, /* PaintFunc performs motion-related rendering */ + PAUSE_PAINT, /* Unused. Reserved */ + RESUME_PAINT, /* Unused. Reserved */ + FINISH_PAINT, /* Cleanup and/or reset PaintFunc operation */ + PRETRACE_PAINT, /* PaintFunc performs window tracing activity prior to rendering */ + POSTTRACE_PAINT /* PaintFunc performs window tracing activity following rendering */ +} PaintState; + +typedef enum /*< skip >*/ +{ + TOOL_CAN_HANDLE_CHANGING_BRUSH = 0x0001, /* Set for tools that don't mind + * if the brush changes while + * painting. + */ + + TOOL_TRACES_ON_WINDOW /* Set for tools that perform temporary + * rendering directly to the window. These + * require sequencing with gdisplay_flush() + * routines. See clone.c for example. + */ +} ToolFlags; + +typedef void (* PaintFunc) (GimpPaintTool *tool, + GimpDrawable *drawable, + PaintState paint_state); + +struct _GimpPaintTool +{ + GimpDrawTool parent_instance; + + gdouble startx; /* starting x coord */ + gdouble starty; /* starting y coord */ + gdouble startpressure; /* starting pressure */ + gdouble startxtilt; /* starting xtilt */ + gdouble startytilt; /* starting ytilt */ +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble startwheel; /* starting wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ + + gdouble curx; /* current x coord */ + gdouble cury; /* current y coord */ + gdouble curpressure; /* current pressure */ + gdouble curxtilt; /* current xtilt */ + gdouble curytilt; /* current ytilt */ +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble curwheel; /* current wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ + + gdouble lastx; /* last x coord */ + gdouble lasty; /* last y coord */ + gdouble lastpressure; /* last pressure */ + gdouble lastxtilt; /* last xtilt */ + gdouble lastytilt; /* last ytilt */ +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble lastwheel; /* last wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ + + gint state; /* state of buttons and keys */ + + gdouble distance; /* distance traveled by brush */ + gdouble pixel_dist; /* distance in pixels */ + gdouble spacing; /* spacing */ + + gint x1, y1; /* image space coordinate */ + gint x2, y2; /* image space coords */ + + GimpBrush * brush; /* current brush */ + + gboolean pick_colors; /* pick color if ctrl or alt is pressed */ + gboolean pick_state; /* was ctrl or alt pressed when clicked? */ + ToolFlags flags; /* tool flags, see ToolFlags above */ + + guint context_id; /* for the statusbar */ +}; + +struct _GimpPaintToolClass +{ + GimpDrawToolClass parent_class; + + PaintFunc paint_func; /* painting function */ +}; + +typedef struct _GimpPaintToolClass GimpPaintToolClass; + + +/* this should change */ +extern GimpPaintTool *non_gui_paint_tool; +extern GimpPaintToolClass *non_gui_paint_tool_class; + +/* Special undo type */ +typedef struct _PaintUndo PaintUndo; + +struct _PaintUndo +{ + GimpPaintTool *tool; + + + gdouble lastx; + gdouble lasty; + gdouble lastpressure; + gdouble lastxtilt; + gdouble lastytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble lastwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ +}; + +/* paint tool action functions */ +void gimp_paint_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); +void gimp_paint_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); +void gimp_paint_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); +void gimp_paint_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +void gimp_paint_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp); + +void gimp_paint_tool_paint (GimpPaintTool *tool, + GimpDrawable *drawable, + PaintState state); + +/* paint tool functions */ +void gimp_paint_tool_no_draw (GimpPaintTool *tool); + +GimpPaintTool *gimp_paint_tool_new (void); +void gimp_paint_tool_destroy (GimpTool *tool); +int gimp_paint_tool_start (GimpPaintTool *tool, + GimpDrawable *drawable, + gdouble x, + gdouble y); +void gimp_paint_tool_interpolate (GimpPaintTool *tool, + GimpDrawable *drawable); +void gimp_paint_tool_finish (GimpPaintTool *tool, + GimpDrawable *drawable); +void gimp_paint_tool_cleanup (void); + +void gimp_paint_tool_get_color_from_gradient (GimpPaintTool *tool, + gdouble gradient_length, + GimpRGB *color, + GradientPaintMode mode); + +/* paint tool painting functions */ +TempBuf * gimp_paint_tool_get_paint_area (GimpPaintTool *tool, + GimpDrawable *drawable, + gdouble scale); +TempBuf * gimp_paint_tool_get_orig_image (GimpPaintTool *tool, + GimpDrawable *drawable, + gint x1, + gint y1, + gint x2, + gint y2); +void gimp_paint_tool_paste_canvas (GimpPaintTool *tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode); +void gimp_paint_tool_replace_canvas (GimpPaintTool *tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode); +void gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *tool, + GimpImage *dest, + GimpDrawable *drawable, + TempBuf *area, + gdouble scale, + BrushApplicationMode mode); + + +#endif /* __GIMP_PAINT_TOOL_H__ */ diff --git a/app/tools/gimpcolorpickertool.c b/app/tools/gimpcolorpickertool.c new file mode 100644 index 0000000000..aceb514238 --- /dev/null +++ b/app/tools/gimpcolorpickertool.c @@ -0,0 +1,886 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "apptypes.h" +#include "appenv.h" + +#include "tools/gimpdrawtool.h" +#include "tools/gimpcolorpickertool.h" + +#include "cursorutil.h" + +#include "drawable.h" +#include "gdisplay.h" +#include "gimpimage.h" +#include "gimpui.h" +#include "gimprc.h" +#include "info_dialog.h" +#include "palette.h" +#include "tool.h" +#include "tool_manager.h" +#include "tool_options.h" + +#include "libgimp/gimpintl.h" + +#include "pixmaps2.h" + +/* maximum information buffer size */ +#define MAX_INFO_BUF 8 + +/* the color picker structures */ + +typedef struct _GimpColorPickerToolOptions GimpColorPickerToolOptions; + +struct _GimpColorPickerToolOptions +{ + 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; +}; + + +/* local function prototypes */ + +static void gimp_color_picker_tool_class_init (GimpColorPickerToolClass *klass); +static void gimp_color_picker_tool_init (GimpColorPickerTool *color_picker_tool); + +static void gimp_color_picker_tool_destroy (GtkObject *object); + +static void gimp_color_picker_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +static void gimp_color_picker_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp); + +static void gimp_color_picker_tool_draw (GimpTool *tool); + + + +static GimpColorPickerToolOptions * gimp_color_picker_tool_options_new (void); + +static void gimp_color_picker_tool_options_reset (void); +static void gimp_color_picker_tool_info_window_close_callback (GtkWidget *widget, + gpointer data); +static void gimp_color_picker_tool_info_update (GimpTool *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); + + +/* the color picker tool options */ +static GimpColorPickerToolOptions * gimp_color_picker_tool_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 *gimp_color_picker_tool_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]; + +static GimpToolClass *parent_class = NULL; + + +void +gimp_color_picker_tool_register (void) +{ + tool_manager_register_tool (GIMP_TYPE_COLOR_PICKER_TOOL, + "gimp:color_picker_tool", + _("Color Picker"), + _("Pick colors from the image"), + N_("/Tools/Color Picker"), "O", + NULL, "tools/color_picker.html", + (const gchar **) colorpicker_bits); +} + +GtkType +gimp_color_picker_tool_get_type (void) +{ + static GtkType tool_type = 0; + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpColorPickerTool", + sizeof (GimpColorPickerTool), + sizeof (GimpColorPickerToolClass), + (GtkClassInitFunc) gimp_color_picker_tool_class_init, + (GtkObjectInitFunc) gimp_color_picker_tool_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); + } + + return tool_type; +} + +static void +gimp_color_picker_tool_class_init (GimpColorPickerToolClass *klass) +{ + GtkObjectClass *object_class; + GimpToolClass *tool_class; + GimpDrawToolClass *draw_class; + + object_class = (GtkObjectClass *) klass; + tool_class = (GimpToolClass *) klass; + + parent_class = gtk_type_class (GIMP_TYPE_DRAW_TOOL); + + object_class->destroy = gimp_color_picker_tool_destroy; + + tool_class->control = gimp_color_picker_tool_control; + tool_class->button_press = gimp_color_picker_tool_button_press; + tool_class->button_release = gimp_color_picker_tool_button_release; + tool_class->motion = gimp_color_picker_tool_motion; + tool_class->cursor_update = gimp_color_picker_tool_cursor_update; + + draw_class->draw = gimp_color_picker_tool_draw; +} + +static void +gimp_color_picker_tool_init (GimpColorPickerTool *color_picker_tool) +{ + GimpTool *tool; + + tool = GIMP_TOOL (color_picker_tool); + + if (! gimp_color_picker_tool_options) + { + gimp_color_picker_tool_options = gimp_color_picker_tool_options_new (); + + tool_manager_register_tool_options (GIMP_TYPE_COLOR_PICKER_TOOL, + (ToolOptions *) gimp_color_picker_tool_options); + } + + tool->preserve = FALSE; /* Don't preserve on drawable change */ +} + +static void +gimp_color_picker_tool_destroy (GtkObject *object) +{ + GimpTool *tool; + GimpDrawTool *draw_tool; + + tool = GIMP_TOOL (object); + draw_tool = GIMP_DRAW_TOOL (object); + + + if (tool->state == ACTIVE) + gimp_draw_tool_stop (draw_tool); + + if (gimp_color_picker_tool_info) + { + info_dialog_free (gimp_color_picker_tool_info); + gimp_color_picker_tool_info = NULL; + + color_area = NULL; + } + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +gimp_color_picker_tool_options_reset (void) +{ + GimpColorPickerToolOptions *options = gimp_color_picker_tool_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 GimpColorPickerToolOptions * +gimp_color_picker_tool_options_new (void) +{ + GimpColorPickerToolOptions *options; + + GtkWidget *vbox; + GtkWidget *abox; + GtkWidget *table; + GtkWidget *label; + GtkWidget *scale; + + /* the new color picker tool options structure */ + options = g_new (GimpColorPickerToolOptions, 1); + tool_options_init ((ToolOptions *) options, + gimp_color_picker_tool_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 +gimp_color_picker_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GimpColorPickerTool *cp_tool; + gint x, y; + + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); + + /* 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 (! gimp_color_picker_tool_info) + { + GtkWidget *hbox; + GtkWidget *frame; + GimpRGB color; + + gimp_color_picker_tool_info = info_dialog_new (_("Color Picker"), + tool_manager_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 (gimp_color_picker_tool_info, _("Red:"), red_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Green:"), green_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Blue:"), blue_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Alpha:"), alpha_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Hex Triplet:"), hex_buf); + break; + + case INDEXED_GIMAGE: case INDEXEDA_GIMAGE: + info_dialog_add_label (gimp_color_picker_tool_info, _("Index:"), index_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Red:"), red_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Green:"), green_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Blue:"), blue_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Alpha:"), alpha_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Hex Triplet"), hex_buf); + break; + + case GRAY_GIMAGE: case GRAYA_GIMAGE: + info_dialog_add_label (gimp_color_picker_tool_info, _("Intensity:"), gray_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Alpha:"), alpha_buf); + info_dialog_add_label (gimp_color_picker_tool_info, _("Hex Triplet:"), hex_buf); + break; + + default : + break; + } + + hbox = gtk_hbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (gimp_color_picker_tool_info->vbox), hbox, + FALSE, FALSE, 0); + gtk_widget_show (hbox); + + gtk_widget_reparent (gimp_color_picker_tool_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 (gimp_color_picker_tool_info->shell), + + _("Close"), gimp_color_picker_tool_info_window_close_callback, + gimp_color_picker_tool_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) + { + gimp_color_picker_tool_info_update + (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, + COLOR_NEW)); + update_type = COLOR_UPDATE_NEW; + } + else + { + gimp_color_picker_tool_info_update + (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, + COLOR_UPDATE)); + update_type = COLOR_UPDATE; + } + + /* Start drawing the colorpicker tool */ + gimp_draw_tool_start (GIMP_DRAW_TOOL(cp_tool), gdisp->canvas->window); +} + +static void +gimp_color_picker_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GimpColorPickerTool *cp_tool; + gint x, y; + + gdk_pointer_ungrab (bevent->time); + gdk_flush (); + + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); + + /* First, transform the coordinates to gimp image space */ + gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, + FALSE, FALSE); + + gimp_color_picker_tool_info_update + (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, + update_type)); + + gimp_draw_tool_stop (GIMP_DRAW_TOOL(cp_tool)); + tool->state = INACTIVE; +} + +static void +gimp_color_picker_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpColorPickerTool *cp_tool; + gint x, y; + + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); + + /* undraw the current tool */ + gimp_draw_tool_pause (GIMP_DRAW_TOOL(cp_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); + + gimp_color_picker_tool_info_update + (tool, pick_color_do (gdisp->gimage, tool->drawable, x, y, + gimp_color_picker_tool_options->sample_merged, + gimp_color_picker_tool_options->sample_average, + gimp_color_picker_tool_options->average_radius, + gimp_color_picker_tool_options->update_active, + update_type)); + + /* redraw the current tool */ + gimp_draw_tool_resume (GIMP_DRAW_TOOL(cp_tool)); +} + +static void +gimp_color_picker_tool_cursor_update (GimpTool *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, + GIMP_COLOR_PICKER_TOOL_CURSOR, + GIMP_CURSOR_MODIFIER_NONE); + } + else + { + gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR, + GIMP_COLOR_PICKER_TOOL_CURSOR, + GIMP_CURSOR_MODIFIER_NONE); + } +} + +static void +gimp_color_picker_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp) +{ + GimpDrawTool *dr_tool; + + dr_tool = GIMP_DRAW_TOOL(tool); + + switch (action) + { + case PAUSE : + gimp_draw_tool_pause (dr_tool); + break; + + case RESUME : + gimp_draw_tool_resume (dr_tool); + break; + + case HALT : + gimp_draw_tool_stop (dr_tool); + info_dialog_popdown (gimp_color_picker_tool_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 +gimp_color_picker_tool_draw (GimpTool *tool) +{ + GimpColorPickerTool *cp_tool; + GimpDrawTool *dr_tool; + gint tx, ty; + gint radiusx, radiusy; + gint cx, cy; + + if (! gimp_color_picker_tool_options->sample_average) + return; + + cp_tool = GIMP_COLOR_PICKER_TOOL(tool); + dr_tool = GIMP_DRAW_TOOL(tool); + + gdisplay_transform_coords (tool->gdisp, cp_tool->centerx, cp_tool->centery, + &tx, &ty, TRUE); + + radiusx = SCALEX (tool->gdisp, gimp_color_picker_tool_options->average_radius); + radiusy = SCALEY (tool->gdisp, gimp_color_picker_tool_options->average_radius); + cx = SCALEX (tool->gdisp, 1); + cy = SCALEY (tool->gdisp, 1); + + /* Draw the circle around the collecting area */ + gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0, + tx - radiusx, + ty - radiusy, + 2 * radiusx + cx, 2 * radiusy + cy); + + if (radiusx > 1 && radiusy > 1) + { + gdk_draw_rectangle (dr_tool->win, dr_tool->gc, 0, + tx - radiusx + 2, + ty - radiusy + 2, + 2 * radiusx + cx - 4, 2 * radiusy + cy - 4); + } +} + +static void +gimp_color_picker_tool_info_update (GimpTool *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 (gimp_color_picker_tool_info); + info_dialog_popup (gimp_color_picker_tool_info); +} + +static void +gimp_color_picker_tool_info_window_close_callback (GtkWidget *widget, + gpointer client_data) +{ + info_dialog_popdown ((InfoDialog *) client_data); +} diff --git a/app/tools/gimpcolorpickertool.h b/app/tools/gimpcolorpickertool.h new file mode 100644 index 0000000000..3423571f0b --- /dev/null +++ b/app/tools/gimpcolorpickertool.h @@ -0,0 +1,68 @@ +/* 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 __GIMP_COLOR_PICKER_TOOL_H__ +#define __GIMP_COLOR_PICKER_TOOL_H__ + + +#include "gimpdrawtool.h" + + +#define GIMP_TYPE_COLOR_PICKER_TOOL (gimp_color_picker_tool_get_type ()) +#define GIMP_COLOR_PICKER_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_COLOR_PICKER_TOOL, GimpColorPickerTool)) +#define GIMP_IS_COLOR_PICKER_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_COLOR_PICKER_TOOL)) +#define GIMP_COLOR_PICKER_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_COLOR_PICKER_TOOL, GimpColorPickerToolClass)) +#define GIMP_IS_COLOR_PICKER_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_COLOR_PICKER_TOOL)) + + +typedef struct _GimpColorPickerTool GimpColorPickerTool; +typedef struct _GimpColorPickerToolClass GimpColorPickerToolClass; + +struct _GimpColorPickerTool +{ + GimpDrawTool parent_instance; + + gint centerx; /* starting x coord */ + gint centery; /* starting y coord */ + +}; + +struct _GimpColorPickerToolClass +{ + GimpDrawToolClass parent_class; +}; + +/* FIXME: Whats this doing here? */ +extern gint col_value[5]; + +GtkType gimp_color_picker_tool_get_type (void); +GimpTool * gimp_color_picker_tool_new (void); + +void gimp_color_picker_tool_register (void); + +gboolean pick_color (GimpImage *gimage, + GimpDrawable *drawable, + gint x, + gint y, + gboolean sample_merged, + gboolean sample_average, + double average_radius, + gint final); + + +#endif /* __GIMP_COLOR_PICKER_TOOL_H__ */ diff --git a/app/tools/gimpdrawtool.c b/app/tools/gimpdrawtool.c new file mode 100644 index 0000000000..73c74ff75e --- /dev/null +++ b/app/tools/gimpdrawtool.c @@ -0,0 +1,192 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "apptypes.h" + +#include "appenv.h" +#include "tool.h" +#include "tools/gimpdrawtool.h" + + +static void gimp_draw_tool_initialize (GimpDrawTool *); + +enum { /* signals */ + DRAW, + LAST_SIGNAL +}; + +static guint gimp_draw_tool_signals[LAST_SIGNAL] = { 0 }; + +static void standard_draw_func (GimpDrawTool *tool) +{ +} + + +GtkType +gimp_draw_tool_get_type (void) +{ + static GtkType tool_type = 0; + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpDrawTool", + sizeof (GimpDrawTool), + sizeof (GimpDrawToolClass), + (GtkClassInitFunc) gimp_draw_tool_class_init, + (GtkObjectInitFunc) gimp_draw_tool_initialize, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + NULL /* (GtkClassInitFunc) gimp_tool_class_init, */ + }; + + tool_type = gtk_type_unique (GIMP_TYPE_TOOL, &tool_info); + } + + return tool_type; +} + +GimpDrawTool * +gimp_draw_tool_new (void) +{ + GimpDrawTool *tool; + + tool = gtk_type_new (GIMP_TYPE_DRAW_TOOL); + + return tool; +} + + +static void +gimp_draw_tool_initialize (GimpDrawTool *tool) +{ + tool->draw_state = INVISIBLE; + tool->gc = NULL; + tool->paused_count = 0; + tool->line_width = 0; + tool->line_style = GDK_LINE_SOLID; + tool->cap_style = GDK_CAP_NOT_LAST; + tool->join_style = GDK_JOIN_MITER; +} + + +void +gimp_draw_tool_class_init (GimpDrawToolClass *klass) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + + gimp_draw_tool_signals[DRAW] = + gtk_signal_new ("draw", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (GimpDrawToolClass, + draw), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + g_message ("draw is %i, DRAW is %i", gimp_draw_tool_signals[DRAW], DRAW); + + gtk_object_class_add_signals (object_class, gimp_draw_tool_signals, LAST_SIGNAL); + + klass->draw = standard_draw_func; +} + + +void +gimp_draw_tool_start (GimpDrawTool *core, + GdkWindow *win) +{ + GdkColor fg, bg; + + if (core->draw_state != INVISIBLE) + gimp_draw_tool_stop (core); /* this seems backwards ;) */ + + core->win = win; + core->paused_count = 0; /* reset pause counter to 0 */ + + /* create a new graphics context */ + if (! core->gc) + core->gc = gdk_gc_new (win); + + gdk_gc_set_function (core->gc, GDK_INVERT); + fg.pixel = 0xFFFFFFFF; + bg.pixel = 0x00000000; + gdk_gc_set_foreground (core->gc, &fg); + gdk_gc_set_background (core->gc, &bg); + gdk_gc_set_line_attributes (core->gc, core->line_width, core->line_style, + core->cap_style, core->join_style); + + gtk_signal_emit (GTK_OBJECT(core), gimp_draw_tool_signals[DRAW]); + + core->draw_state = VISIBLE; +} + + +void +gimp_draw_tool_stop (GimpDrawTool *core) +{ + if (core->draw_state == INVISIBLE) + return; + + gtk_signal_emit (GTK_OBJECT(core), gimp_draw_tool_signals[DRAW]); + + core->draw_state = INVISIBLE; +} + + +void +gimp_draw_tool_resume (GimpDrawTool *core) +{ + core->paused_count = (core->paused_count > 0) ? core->paused_count - 1 : 0; + if (core->paused_count == 0) + { + core->draw_state = VISIBLE; + gtk_signal_emit(GTK_OBJECT(core), gimp_draw_tool_signals[DRAW]); + } +} + + +void +gimp_draw_tool_pause (GimpDrawTool *core) +{ + if (core->paused_count == 0) + { + core->draw_state = INVISIBLE; + gtk_signal_emit (GTK_OBJECT(core), gimp_draw_tool_signals[DRAW]); + } + core->paused_count++; +} + + +/*FIXME: make this get called */ +void +gimp_draw_tool_destroy (GimpDrawTool *core) +{ + if (core) + { + if (core->gc) + gdk_gc_destroy (core->gc); + } +} + + diff --git a/app/tools/gimpdrawtool.h b/app/tools/gimpdrawtool.h new file mode 100644 index 0000000000..7b56afc226 --- /dev/null +++ b/app/tools/gimpdrawtool.h @@ -0,0 +1,77 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others. + * + * 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 __GIMP_DRAW_TOOL_H__ +#define __GIMP_DRAW_TOOL_H__ + +#include "tools/tool.h" + +#define GIMP_TYPE_DRAW_TOOL (gimp_draw_tool_get_type ()) +#define GIMP_DRAW_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_DRAW_TOOL, GimpDrawTool)) +#define GIMP_IS_DRAW_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_DRAW_TOOL)) +#define GIMP_DRAW_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DRAW_TOOL, GimpDrawToolClass)) +#define GIMP_IS_DRAW_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_DRAW_TOOL)) + +/* draw states */ +#define INVISIBLE 0 +#define VISIBLE 1 + +/* Structure definitions */ + +typedef void (* DrawToolDraw) (GimpDrawTool *); + +struct _GimpDrawTool +{ + GimpTool parent_instance; + + GdkGC * gc; /* Graphics context for draw functions */ + GdkWindow * win; /* Window to draw draw operation to */ + + gint draw_state; /* Current state in the draw process */ + + gint line_width; /**/ + gint line_style; /**/ + gint cap_style; /* line attributes */ + gint join_style; /**/ + + gint paused_count; /* count to keep track of multiple pauses */ +}; + +struct _GimpDrawToolClass +{ + GimpToolClass parent_class; + + DrawToolDraw draw; +}; + + +typedef struct _GimpDrawToolClass GimpDrawToolClass; + +/* draw core functions */ +GtkType gimp_draw_tool_get_type (void); +void gimp_draw_tool_class_init (GimpDrawToolClass *); + +GimpDrawTool * gimp_draw_tool_new (void); /* create a new, generic DrawTool */ +void gimp_draw_tool_start (GimpDrawTool *, + GdkWindow *); +void gimp_draw_tool_stop (GimpDrawTool *); +void gimp_draw_tool_pause (GimpDrawTool *); +void gimp_draw_tool_resume (GimpDrawTool *); + + +#endif /* __DRAWTOOL_H__ */ diff --git a/app/tools/gimpmeasuretool.c b/app/tools/gimpmeasuretool.c index 41914d477d..f48654eabf 100644 --- a/app/tools/gimpmeasuretool.c +++ b/app/tools/gimpmeasuretool.c @@ -31,7 +31,6 @@ #include "apptypes.h" #include "cursorutil.h" -#include "draw_core.h" #include "gdisplay.h" #include "gimpimage.h" #include "info_dialog.h" @@ -42,6 +41,8 @@ #include "tool_manager.h" #include "tool_options.h" +#include "tools/gimpdrawingtool.h" + #include "libgimp/gimpintl.h" #include "pixmaps2.h" @@ -143,7 +144,7 @@ gimp_measure_tool_get_type (void) (GtkClassInitFunc) NULL, }; - tool_type = gtk_type_unique (GIMP_TYPE_TOOL, &tool_info); + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); } return tool_type; @@ -185,24 +186,20 @@ gimp_measure_tool_init (GimpMeasureTool *measure_tool) (ToolOptions *) measure_tool_options); } - measure_tool->core = draw_core_new (measure_tool_draw); - tool->preserve = TRUE; /* Preserve on drawable change */ } static void gimp_measure_tool_destroy (GtkObject *object) { - GimpMeasureTool *measure_tool; + GimpDrawTool *draw_tool; GimpTool *tool; - measure_tool = GIMP_MEASURE_TOOL (object); + draw_tool = GIMP_DRAW_TOOL (object); tool = GIMP_TOOL (object); if (tool->state == ACTIVE) - draw_core_stop (measure_tool->core, tool); - - draw_core_free (measure_tool->core); + gimp_draw_tool_stop (draw_tool); if (GTK_OBJECT_CLASS (parent_class)->destroy) GTK_OBJECT_CLASS (parent_class)->destroy (object); @@ -388,7 +385,7 @@ measure_tool_button_press (GimpTool *tool, if (tool->state == ACTIVE) { /* reset everything */ - draw_core_stop (measure_tool->core, tool); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(measure_tool)); gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), measure_tool->context_id); @@ -403,13 +400,13 @@ measure_tool_button_press (GimpTool *tool, else { /* initialize the statusbar display */ - measure_tool->context_id = + measure_tool->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "measure"); } - + /* set the first point and go into ADDING mode */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, + gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &measure_tool->x[0], &measure_tool->y[0], TRUE, FALSE); measure_tool->point = 0; @@ -420,7 +417,7 @@ measure_tool_button_press (GimpTool *tool, tool->gdisp = gdisp; /* start drawing the measure tool */ - draw_core_start (measure_tool->core, gdisp->canvas->window, tool); + gimp_draw_tool_start (GIMP_DRAW_TOOL(measure_tool), gdisp->canvas->window); } /* create the info window if necessary */ @@ -441,14 +438,14 @@ measure_tool_button_press (GimpTool *tool, NULL); } - + gdk_pointer_grab (gdisp->canvas->window, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, bevent->time); tool->state = ACTIVE; - + /* set the pointer to the crosshair, * so one actually sees the cursor position */ @@ -466,7 +463,7 @@ measure_tool_button_release (GimpTool *tool, GimpMeasureTool *measure_tool; measure_tool = GIMP_MEASURE_TOOL (tool); - + measure_tool->function = FINISHED; gdk_pointer_ungrab (bevent->time); @@ -492,15 +489,15 @@ measure_tool_motion (GimpTool *tool, measure_tool = GIMP_MEASURE_TOOL (tool); /* undraw the current tool */ - draw_core_pause (measure_tool->core, tool); + gimp_draw_tool_pause (GIMP_DRAW_TOOL(measure_tool)); /* get the coordinates */ gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, FALSE); - /* + /* * A few comments here, because this routine looks quite weird at first ... * - * The goal is to keep point 0, called the start point, to be always the one + * The goal is to keep point 0, called the start point, to be always the one * in the middle or, if there are only two points, the one that is fixed. * The angle is then always measured at this point. */ @@ -510,7 +507,7 @@ measure_tool_motion (GimpTool *tool, case ADDING: switch (measure_tool->point) { - case 0: /* we are adding to the start point */ + case 0: /* we are adding to the start point */ break; case 1: /* we are adding to the end point, make it the new start point */ tmp = measure_tool->x[0]; @@ -533,8 +530,8 @@ measure_tool_motion (GimpTool *tool, measure_tool->point = measure_tool->num_points - 1; measure_tool->function = MOVING; /* no, don't break here! */ - - case MOVING: + + case MOVING: /* if we are moving the start point and only have two, make it the end point */ if (measure_tool->num_points == 2 && measure_tool->point == 0) { @@ -558,10 +555,10 @@ measure_tool_motion (GimpTool *tool, { dx = measure_tool->x[i] - measure_tool->x[0]; dy = measure_tool->y[i] - measure_tool->y[0]; - - measure_tool->x[i] = measure_tool->x[0] + + + measure_tool->x[i] = measure_tool->x[0] + (dx > 0 ? MAX (abs (dx), abs (dy)) : - MAX (abs (dx), abs (dy))); - measure_tool->y[i] = measure_tool->y[0] + + measure_tool->y[i] = measure_tool->y[0] + (dy > 0 ? MAX (abs (dx), abs (dy)) : - MAX (abs (dx), abs (dy))); } else @@ -592,7 +589,7 @@ measure_tool_motion (GimpTool *tool, /* calculate distance and angle */ ax = measure_tool->x[1] - measure_tool->x[0]; ay = measure_tool->y[1] - measure_tool->y[0]; - + if (measure_tool->num_points == 3) { bx = measure_tool->x[2] - measure_tool->x[0]; @@ -603,23 +600,23 @@ measure_tool_motion (GimpTool *tool, bx = 0; by = 0; } - + if (gdisp->dot_for_dot) { distance = sqrt (SQR (ax - bx) + SQR (ay - by)); - + if (measure_tool->num_points != 3) bx = ax > 0 ? 1 : -1; - + measure_tool->angle1 = measure_get_angle (ax, ay, 1.0, 1.0); measure_tool->angle2 = measure_get_angle (bx, by, 1.0, 1.0); angle = fabs (measure_tool->angle1 - measure_tool->angle2); if (angle > 180.0) angle = fabs (360.0 - angle); - + g_snprintf (status_str, STATUSBAR_SIZE, "%.1f %s, %.2f %s", distance, _("pixels"), angle, _("degrees")); - + if (measure_tool_options) { g_snprintf (distance_buf, MAX_INFO_BUF, "%.1f %s", distance, _("pixels")); @@ -634,20 +631,20 @@ measure_tool_motion (GimpTool *tool, gimp_unit_get_symbol (gdisp->gimage->unit), _("degrees")); - distance = gimp_unit_get_factor (gdisp->gimage->unit) * + distance = gimp_unit_get_factor (gdisp->gimage->unit) * sqrt (SQR ((gdouble)(ax - bx) / gdisp->gimage->xresolution) + SQR ((gdouble)(ay - by) / gdisp->gimage->yresolution)); if (measure_tool->num_points != 3) bx = ax > 0 ? 1 : -1; - measure_tool->angle1 = measure_get_angle (ax, ay, - gdisp->gimage->xresolution, - gdisp->gimage->yresolution); - measure_tool->angle2 = measure_get_angle (bx, by, - gdisp->gimage->xresolution, + measure_tool->angle1 = measure_get_angle (ax, ay, + gdisp->gimage->xresolution, gdisp->gimage->yresolution); - angle = fabs (measure_tool->angle1 - measure_tool->angle2); + measure_tool->angle2 = measure_get_angle (bx, by, + gdisp->gimage->xresolution, + gdisp->gimage->yresolution); + angle = fabs (measure_tool->angle1 - measure_tool->angle2); if (angle > 180.0) angle = fabs (360.0 - angle); @@ -680,7 +677,7 @@ measure_tool_motion (GimpTool *tool, } /* measure_tool->function == MOVING */ /* redraw the current tool */ - draw_core_resume (measure_tool->core, tool); + gimp_draw_tool_resume (GIMP_DRAW_TOOL(measure_tool)); } static void @@ -703,9 +700,9 @@ measure_tool_cursor_update (GimpTool *tool, { for (i = 0; i < measure_tool->num_points; i++) { - gdisplay_transform_coords (gdisp, measure_tool->x[i], measure_tool->y[i], - &x[i], &y[i], FALSE); - + gdisplay_transform_coords (gdisp, measure_tool->x[i], measure_tool->y[i], + &x[i], &y[i], FALSE); + if (mevent->x == CLAMP (mevent->x, x[i] - TARGET, x[i] + TARGET) && mevent->y == CLAMP (mevent->y, y[i] - TARGET, y[i] + TARGET)) { @@ -752,6 +749,7 @@ static void measure_tool_draw (GimpTool *tool) { GimpMeasureTool *measure_tool; + GimpDrawTool *draw_tool; gint x[3]; gint y[3]; gint i; @@ -767,22 +765,22 @@ measure_tool_draw (GimpTool *tool) &x[i], &y[i], FALSE); if (i == 0 && measure_tool->num_points == 3) { - gdk_draw_arc (measure_tool->core->win, measure_tool->core->gc, FALSE, + gdk_draw_arc (draw_tool->win, draw_tool->gc, FALSE, x[i] - (TARGET >> 1), y[i] - (TARGET >> 1), TARGET, TARGET, 0, 23040); } else { - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[i] - TARGET, y[i], + gdk_draw_line (draw_tool->win, draw_tool->gc, + x[i] - TARGET, y[i], x[i] + TARGET, y[i]); - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[i], y[i] - TARGET, + gdk_draw_line (draw_tool->win, draw_tool->gc, + x[i], y[i] - TARGET, x[i], y[i] + TARGET); } if (i > 0) { - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, + gdk_draw_line (draw_tool->win, draw_tool->gc, x[0], y[0], x[i], y[i]); /* only draw the arc if the lines are long enough */ @@ -790,29 +788,29 @@ measure_tool_draw (GimpTool *tool) draw_arc++; } } - + if (measure_tool->num_points > 1 && draw_arc == measure_tool->num_points - 1) { angle1 = measure_tool->angle2 * 64.0; angle2 = (measure_tool->angle1 - measure_tool->angle2) * 64.0; - + if (angle2 > 11520) angle2 -= 23040; if (angle2 < -11520) angle2 += 23040; - + if (angle2 != 0) { - gdk_draw_arc (measure_tool->core->win, measure_tool->core->gc, FALSE, + gdk_draw_arc (draw_tool->win, draw_tool->gc, FALSE, x[0] - ARC_RADIUS, y[0] - ARC_RADIUS, - 2 * ARC_RADIUS, 2 * ARC_RADIUS, - angle1, angle2); + 2 * ARC_RADIUS, 2 * ARC_RADIUS, + angle1, angle2); if (measure_tool->num_points == 2) - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, + gdk_draw_line (draw_tool->win, draw_tool->gc, x[0], y[0], - x[1] - x[0] <= 0 ? x[0] - ARC_RADIUS - (TARGET >> 1) : - x[0] + ARC_RADIUS + (TARGET >> 1), + x[1] - x[0] <= 0 ? x[0] - ARC_RADIUS - (TARGET >> 1) : + x[0] + ARC_RADIUS + (TARGET >> 1), y[0]); } } @@ -823,24 +821,24 @@ measure_tool_control (GimpTool *tool, ToolAction action, GDisplay *gdisp) { - GimpMeasureTool *measure_tool; + GimpDrawTool *draw_tool; - measure_tool = GIMP_MEASURE_TOOL (tool); + draw_tool = GIMP_DRAW_TOOL (tool); switch (action) { case PAUSE: - draw_core_pause (measure_tool->core, tool); + gimp_draw_tool_pause (draw_tool); break; case RESUME: - draw_core_resume (measure_tool->core, tool); + gimp_draw_tool_resume (draw_tool); break; case HALT: gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), measure_tool->context_id); - draw_core_stop (measure_tool->core, tool); + gimp_draw_tool_stop (draw_tool); tool->state = INACTIVE; break; diff --git a/app/tools/gimpmeasuretool.h b/app/tools/gimpmeasuretool.h index de3e48abd0..6212003ea9 100644 --- a/app/tools/gimpmeasuretool.h +++ b/app/tools/gimpmeasuretool.h @@ -46,9 +46,7 @@ typedef struct _GimpMeasureToolClass GimpMeasureToolClass; struct _GimpMeasureTool { - GimpTool parent_instance; - - DrawCore *core; /* Core select object */ + GimpDrawTool parent_instance; /* Core select object */ MeasureFunction function; /* function we're performing */ gint last_x; /* last x coordinate */ diff --git a/app/tools/gimpmovetool.c b/app/tools/gimpmovetool.c index c26f2ba1bc..292540477c 100644 --- a/app/tools/gimpmovetool.c +++ b/app/tools/gimpmovetool.c @@ -25,7 +25,6 @@ #include "apptypes.h" #include "cursorutil.h" -#include "draw_core.h" #include "floating_sel.h" #include "gdisplay.h" #include "gdisplay_ops.h" diff --git a/app/tools/gimppaintbrushtool.c b/app/tools/gimppaintbrushtool.c new file mode 100644 index 0000000000..aa9f23d43c --- /dev/null +++ b/app/tools/gimppaintbrushtool.c @@ -0,0 +1,801 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "apptypes.h" + +#include "drawable.h" +#include "gdisplay.h" +#include "gimpbrush.h" +#include "gimpcontext.h" +#include "gimpgradient.h" +#include "gimpimage.h" +#include "paint_funcs.h" +#include "selection.h" +#include "temp_buf.h" + +#include "tools/gimppainttool.h" +#include "paint_options.h" +#include "tools/gimppaintbrushtool.h" +#include "tool_options.h" +#include "tools/tool.h" +#include "tools/tool_manager.h" + +#include "pixmaps2.h" + +#include "libgimp/gimpintl.h" + +/* defines */ +#define PAINT_LEFT_THRESHOLD 0.05 + +/* defaults for the tool options */ +#define PAINTBRUSH_DEFAULT_INCREMENTAL FALSE +#define PAINTBRUSH_DEFAULT_USE_FADE FALSE +#define PAINTBRUSH_DEFAULT_FADE_OUT 100.0 +#define PAINTBRUSH_DEFAULT_FADE_UNIT GIMP_UNIT_PIXEL +#define PAINTBRUSH_DEFAULT_USE_GRADIENT FALSE +#define PAINTBRUSH_DEFAULT_GRADIENT_LENGTH 100.0 +#define PAINTBRUSH_DEFAULT_GRADIENT_UNIT GIMP_UNIT_PIXEL +#define PAINTBRUSH_DEFAULT_GRADIENT_TYPE LOOP_TRIANGLE + +/* the paintbrush structures */ + +typedef struct _PaintbrushOptions PaintbrushOptions; + +struct _PaintbrushOptions +{ + PaintOptions paint_options; + + gboolean use_fade; + gboolean use_fade_d; + GtkWidget *use_fade_w; + + gdouble fade_out; + gdouble fade_out_d; + GtkObject *fade_out_w; + + GimpUnit fade_unit; + GimpUnit fade_unit_d; + GtkWidget *fade_unit_w; + + gboolean use_gradient; + gboolean use_gradient_d; + GtkWidget *use_gradient_w; + + gdouble gradient_length; + gdouble gradient_length_d; + GtkObject *gradient_length_w; + + GimpUnit gradient_unit; + GimpUnit gradient_unit_d; + GtkWidget *gradient_unit_w; + + gint gradient_type; + gint gradient_type_d; + GtkWidget *gradient_type_w; +}; + +/* the paint brush tool options */ +static PaintbrushOptions * paintbrush_options = NULL; + +/* local variables */ +static gdouble non_gui_fade_out; +static gdouble non_gui_gradient_length; +static gint non_gui_gradient_type; +static gdouble non_gui_incremental; +static GimpUnit non_gui_fade_unit; +static GimpUnit non_gui_gradient_unit; + +static GimpPaintToolClass *parent_class; + +/* forward function declarations */ +static void gimp_paintbrush_tool_motion (GimpPaintTool *, + GimpDrawable *, + PaintPressureOptions *, + gdouble , + gdouble , + PaintApplicationMode , + GradientPaintMode ); +static void gimp_paintbrush_tool_paint_func (GimpPaintTool *paint_core, + GimpDrawable *drawable, + PaintState state); +static void gimp_paintbrush_tool_class_init (GimpPaintToolClass *klass); + +/* functions */ + +GtkType +gimp_paintbrush_tool_get_type (void) +{ + static GtkType tool_type = 0; + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpPaintbrushTool", + sizeof (GimpPaintbrushTool), + sizeof (GimpPaintbrushToolClass), + (GtkClassInitFunc) gimp_paintbrush_tool_class_init, + (GtkObjectInitFunc) NULL /*gimp_paintbrush_tool_initialize*/, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + NULL + }; + + tool_type = gtk_type_unique (GIMP_TYPE_PAINT_TOOL, &tool_info); + } + + return tool_type; +} + + +static void +gimp_paintbrush_tool_gradient_toggle_callback (GtkWidget *widget, + gpointer data) +{ + PaintbrushOptions *options = paintbrush_options; + + static gboolean incremental_save = FALSE; + + gimp_toggle_button_update (widget, data); + + if (paintbrush_options->use_gradient) + { + incremental_save = options->paint_options.incremental; + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON (options->paint_options.incremental_w), TRUE); + } + else + { + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON (options->paint_options.incremental_w), + incremental_save); + } +} + +static void +gimp_paintbrush_tool_options_reset (void) +{ + PaintbrushOptions *options = paintbrush_options; + GtkWidget *spinbutton; + gint digits; + + paint_options_reset ((PaintOptions *) options); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_fade_w), + options->use_fade_d); + gtk_adjustment_set_value (GTK_ADJUSTMENT (options->fade_out_w), + options->fade_out_d); + gimp_unit_menu_set_unit (GIMP_UNIT_MENU (options->fade_unit_w), + options->fade_unit_d); + digits = ((options->fade_unit_d == GIMP_UNIT_PIXEL) ? 0 : + ((options->fade_unit_d == GIMP_UNIT_PERCENT) ? 2 : + (MIN (6, MAX (3, gimp_unit_get_digits (options->fade_unit_d)))))); + spinbutton = gtk_object_get_data (GTK_OBJECT (options->fade_unit_w), "set_digits"); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), digits); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->use_gradient_w), + options->use_gradient_d); + gtk_adjustment_set_value (GTK_ADJUSTMENT (options->gradient_length_w), + options->gradient_length_d); + gimp_unit_menu_set_unit (GIMP_UNIT_MENU (options->gradient_unit_w), + options->gradient_unit_d); + digits = ((options->gradient_unit_d == GIMP_UNIT_PIXEL) ? 0 : + ((options->gradient_unit_d == GIMP_UNIT_PERCENT) ? 2 : + (MIN (6, MAX (3, gimp_unit_get_digits (options->gradient_unit_d)))))); + spinbutton = gtk_object_get_data (GTK_OBJECT (options->gradient_unit_w), "set_digits"); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), digits); + + options->gradient_type = options->gradient_type_d; + + gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w), + options->gradient_type_d); +} + +static PaintbrushOptions * +gimp_paintbrush_tool_options_new (void) +{ + PaintbrushOptions *options; + + GtkWidget *vbox; + GtkWidget *abox; + GtkWidget *table; + GtkWidget *type_label; + GtkWidget *spinbutton; + + /* the new paint tool options structure */ + options = g_new (PaintbrushOptions, 1); + paint_options_init ((PaintOptions *) options, + GIMP_TYPE_PAINTBRUSH_TOOL, + gimp_paintbrush_tool_options_reset); + + options->use_fade = + options->use_fade_d = PAINTBRUSH_DEFAULT_USE_FADE; + options->fade_out = + options->fade_out_d = PAINTBRUSH_DEFAULT_FADE_OUT; + options->fade_unit = + options->fade_unit_d = PAINTBRUSH_DEFAULT_FADE_UNIT; + options->use_gradient = + options->use_gradient_d = PAINTBRUSH_DEFAULT_USE_GRADIENT; + options->gradient_length = + options->gradient_length_d = PAINTBRUSH_DEFAULT_GRADIENT_LENGTH; + options->gradient_unit = + options->gradient_unit_d = PAINTBRUSH_DEFAULT_GRADIENT_UNIT; + options->gradient_type = + options->gradient_type_d = PAINTBRUSH_DEFAULT_GRADIENT_TYPE; + + /* the main vbox */ + vbox = ((ToolOptions *) options)->main_vbox; + + table = gtk_table_new (3, 3, FALSE); + gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); + gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); + gtk_table_set_row_spacing (GTK_TABLE (table), 1, 3); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); + + /* the use fade toggle */ + abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); + gtk_table_attach (GTK_TABLE (table), abox, 0, 1, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (abox); + + options->use_fade_w = + gtk_check_button_new_with_label (_("Fade Out")); + gtk_container_add (GTK_CONTAINER (abox), options->use_fade_w); + gtk_signal_connect (GTK_OBJECT (options->use_fade_w), "toggled", + GTK_SIGNAL_FUNC (gimp_toggle_button_update), + &options->use_fade); + gtk_widget_show (options->use_fade_w); + + /* the fade-out sizeentry */ + options->fade_out_w = + gtk_adjustment_new (options->fade_out_d, 1e-5, 32767.0, 1.0, 50.0, 0.0); + spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (options->fade_out_w), 1.0, 0.0); + gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), GTK_SHADOW_NONE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + gtk_widget_set_usize (spinbutton, 75, 0); + gtk_signal_connect (GTK_OBJECT (options->fade_out_w), "value_changed", + GTK_SIGNAL_FUNC (gimp_double_adjustment_update), + &options->fade_out); + gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 0, 1); + gtk_widget_show (spinbutton); + + /* the fade-out unitmenu */ + options->fade_unit_w = + gimp_unit_menu_new ("%a", options->fade_unit_d, TRUE, TRUE, TRUE); + gtk_signal_connect (GTK_OBJECT (options->fade_unit_w), "unit_changed", + GTK_SIGNAL_FUNC (gimp_unit_menu_update), + &options->fade_unit); + gtk_object_set_data (GTK_OBJECT (options->fade_unit_w), "set_digits", spinbutton); + gtk_table_attach (GTK_TABLE (table), options->fade_unit_w, 2, 3, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (options->fade_unit_w); + + /* automatically set the sensitive state of the fadeout stuff */ + gtk_widget_set_sensitive (spinbutton, options->use_fade_d); + gtk_widget_set_sensitive (options->fade_unit_w, options->use_fade_d); + gtk_object_set_data (GTK_OBJECT (options->use_fade_w), + "set_sensitive", spinbutton); + gtk_object_set_data (GTK_OBJECT (spinbutton), + "set_sensitive", options->fade_unit_w); + + /* the use gradient toggle */ + abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0); + gtk_table_attach (GTK_TABLE (table), abox, 0, 1, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (abox); + + options->use_gradient_w = + gtk_check_button_new_with_label (_("Gradient")); + gtk_container_add (GTK_CONTAINER (abox), options->use_gradient_w); + gtk_signal_connect (GTK_OBJECT (options->use_gradient_w), "toggled", + GTK_SIGNAL_FUNC (gimp_paintbrush_tool_gradient_toggle_callback), + &options->use_gradient); + gtk_widget_show (options->use_gradient_w); + + /* the gradient length scale */ + options->gradient_length_w = + gtk_adjustment_new (options->gradient_length_d, 1e-5, 32767.0, 1.0, 50.0, 0.0); + spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (options->gradient_length_w), 1.0, 0.0); + gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinbutton), GTK_SHADOW_NONE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + gtk_widget_set_usize (spinbutton, 75, 0); + gtk_signal_connect (GTK_OBJECT (options->gradient_length_w), "value_changed", + GTK_SIGNAL_FUNC (gimp_double_adjustment_update), + &options->gradient_length); + gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 1, 2); + gtk_widget_show (spinbutton); + + /* the gradient unitmenu */ + options->gradient_unit_w = + gimp_unit_menu_new ("%a", options->gradient_unit_d, TRUE, TRUE, TRUE); + gtk_signal_connect (GTK_OBJECT (options->gradient_unit_w), "unit_changed", + GTK_SIGNAL_FUNC (gimp_unit_menu_update), + &options->gradient_unit); + gtk_object_set_data (GTK_OBJECT (options->gradient_unit_w), "set_digits", + spinbutton); + gtk_table_attach (GTK_TABLE (table), options->gradient_unit_w, 2, 3, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (options->gradient_unit_w); + + /* the gradient type */ + type_label = gtk_label_new (_("Type:")); + gtk_misc_set_alignment (GTK_MISC (type_label), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), type_label, 0, 1, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (type_label); + + abox = gtk_alignment_new (0.0, 0.5, 0.0, 0.0); + gtk_table_attach_defaults (GTK_TABLE (table), abox, 1, 3, 2, 3); + gtk_widget_show (abox); + + options->gradient_type_w = gimp_option_menu_new2 + (FALSE, gimp_menu_item_update, + &options->gradient_type, (gpointer) options->gradient_type_d, + + _("Once Forward"), (gpointer) ONCE_FORWARD, NULL, + _("Once Backward"), (gpointer) ONCE_BACKWARDS, NULL, + _("Loop Sawtooth"), (gpointer) LOOP_SAWTOOTH, NULL, + _("Loop Triangle"), (gpointer) LOOP_TRIANGLE, NULL, + + NULL); + gtk_container_add (GTK_CONTAINER (abox), options->gradient_type_w); + gtk_widget_show (options->gradient_type_w); + + gtk_widget_show (table); + + /* automatically set the sensitive state of the gradient stuff */ + gtk_widget_set_sensitive (spinbutton, options->use_gradient_d); + gtk_widget_set_sensitive (spinbutton, options->use_gradient_d); + gtk_widget_set_sensitive (options->gradient_unit_w, options->use_gradient_d); + gtk_widget_set_sensitive (options->gradient_type_w, options->use_gradient_d); + gtk_widget_set_sensitive (type_label, options->use_gradient_d); + gtk_widget_set_sensitive (options->paint_options.incremental_w, + ! options->use_gradient_d); + gtk_object_set_data (GTK_OBJECT (options->use_gradient_w), "set_sensitive", + spinbutton); + gtk_object_set_data (GTK_OBJECT (spinbutton), "set_sensitive", + options->gradient_unit_w); + gtk_object_set_data (GTK_OBJECT (options->gradient_unit_w), "set_sensitive", + options->gradient_type_w); + gtk_object_set_data (GTK_OBJECT (options->gradient_type_w), "set_sensitive", + type_label); + gtk_object_set_data (GTK_OBJECT (options->use_gradient_w), "inverse_sensitive", + options->paint_options.incremental_w); + + return options; +} + +#define TIMED_BRUSH 0 + +static void +gimp_paintbrush_tool_paint_func (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + PaintState state) +{ + GDisplay *gdisp = gdisplay_active (); + double fade_out; + double gradient_length; + double unit_factor; + + g_return_if_fail (gdisp != NULL); + +#if TIMED_BRUSH + static GTimer *timer = NULL; +#endif + switch (state) + { + case INIT_PAINT: +#if TIMED_BRUSH + timer = g_timer_new(); + g_timer_start(timer); +#endif /* TIMED_BRUSH */ + break; + + case MOTION_PAINT: + switch (paintbrush_options->fade_unit) + { + case GIMP_UNIT_PIXEL: + fade_out = paintbrush_options->fade_out; + break; + case GIMP_UNIT_PERCENT: + fade_out = MAX (gdisp->gimage->width, gdisp->gimage->height) * + paintbrush_options->fade_out / 100; + break; + default: + unit_factor = gimp_unit_get_factor (paintbrush_options->fade_unit); + fade_out = paintbrush_options->fade_out * + MAX (gdisp->gimage->xresolution, gdisp->gimage->yresolution) / unit_factor; + break; + } + + switch (paintbrush_options->gradient_unit) + { + case GIMP_UNIT_PIXEL: + gradient_length = paintbrush_options->gradient_length; + break; + case GIMP_UNIT_PERCENT: + gradient_length = MAX (gdisp->gimage->width, gdisp->gimage->height) * + paintbrush_options->gradient_length / 100; + break; + default: + unit_factor = gimp_unit_get_factor (paintbrush_options->gradient_unit); + gradient_length = paintbrush_options->gradient_length * + MAX (gdisp->gimage->xresolution, gdisp->gimage->yresolution) / unit_factor; + break; + } + + gimp_paintbrush_tool_motion (paint_tool, drawable, + paintbrush_options->paint_options.pressure_options, + paintbrush_options->use_fade ? fade_out : 0, + paintbrush_options->use_gradient ? gradient_length : 0, + paintbrush_options->paint_options.incremental, + paintbrush_options->gradient_type); + break; + + case FINISH_PAINT : +#if TIMED_BRUSH + if (timer) + { + g_timer_stop(timer); + g_print ("painting took %f:\n", g_timer_elapsed(timer, NULL)); + g_timer_destroy(timer); + timer = NULL; + } +#endif /* TIMED_BRUSH */ + break; + + default : + break; + } +} + + +GimpTool * +gimp_paintbrush_tool_new (void) +{ + return gtk_type_new (GIMP_TYPE_PAINTBRUSH_TOOL); +} + +void +gimp_paintbrush_tool_initialize (GimpPaintTool *tool) +{ + tool->pick_colors = TRUE; + tool->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; +} + +void +gimp_paintbrush_tool_class_init (GimpPaintToolClass *klass) +{ + parent_class = gtk_type_class (GIMP_TYPE_PAINT_TOOL); + + klass->paint_func = gimp_paintbrush_tool_paint_func; +} + +void +gimp_paintbrush_tool_register (void) +{ + tool_manager_register_tool (GIMP_TYPE_PAINTBRUSH_TOOL, + "gimp:paintbrush_tool", + N_("Paintbrush"), + N_("Paint fuzzy brush strokes"), + N_("/Tools/Paint Tools/Paintbrush"), "P", + NULL, "tools/paintbrush.html", (const gchar **) paint_bits); +} + + + +static void +gimp_paintbrush_tool_motion (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + PaintPressureOptions *pressure_options, + double fade_out, + double gradient_length, + PaintApplicationMode incremental, + GradientPaintMode gradient_type) +{ + GImage *gimage; + TempBuf *area; + gdouble x, paint_left; + gdouble position; + guchar local_blend = OPAQUE_OPACITY; + guchar temp_blend = OPAQUE_OPACITY; + guchar col[MAX_CHANNELS]; + GimpRGB color; + gint mode; + gint opacity; + gdouble scale; + PaintApplicationMode paint_appl_mode = incremental ? INCREMENTAL : CONSTANT; + + position = 0.0; + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + if (pressure_options->size) + scale = paint_tool->curpressure; + else + scale = 1.0; + + if (pressure_options->color) + gradient_length = 1.0; /* not really used, only for if cases */ + + /* Get a region which can be used to paint to */ + if (! (area = gimp_paint_tool_get_paint_area (paint_tool, drawable, scale))) + return; + + /* factor in the fade out value */ + if (fade_out) + { + /* Model the amount of paint left as a gaussian curve */ + x = ((double) paint_tool->pixel_dist / fade_out); + paint_left = exp (- x * x * 5.541); /* ln (1/255) */ + local_blend = (int) (255 * paint_left); + } + + if (local_blend) + { + /* set the alpha channel */ + temp_blend = local_blend; + mode = gradient_type; + + if (gradient_length) + { + if (pressure_options->color) + gimp_gradient_get_color_at (gimp_context_get_gradient (NULL), + paint_tool->curpressure, &color); + else + gimp_paint_tool_get_color_from_gradient (paint_tool, gradient_length, + &color, mode); + + temp_blend = (gint) ((color.a * local_blend)); + + gimp_rgb_get_uchar (&color, + &col[RED_PIX], + &col[GREEN_PIX], + &col[BLUE_PIX]); + col[ALPHA_PIX] = OPAQUE_OPACITY; + + /* always use incremental mode with gradients */ + /* make the gui cool later */ + paint_appl_mode = INCREMENTAL; + color_pixels (temp_buf_data (area), col, + area->width * area->height, area->bytes); + } + /* we check to see if this is a pixmap, if so composite the + pixmap image into the are instead of the color */ + else if (paint_tool->brush && paint_tool->brush->pixmap) + { + gimp_paint_tool_color_area_with_pixmap (paint_tool, gimage, drawable, + area, + scale, SOFT); + paint_appl_mode = INCREMENTAL; + } + else + { + gimp_image_get_foreground (gimage, drawable, col); + col[area->bytes - 1] = OPAQUE_OPACITY; + color_pixels (temp_buf_data (area), col, + area->width * area->height, area->bytes); + } + + opacity = (gdouble)temp_blend; + if (pressure_options->opacity) + opacity = opacity * 2.0 * paint_tool->curpressure; + + gimp_paint_tool_paste_canvas (paint_tool, drawable, + MIN (opacity, 255), + gimp_context_get_opacity (NULL) * 255, + gimp_context_get_paint_mode (NULL), + pressure_options->pressure ? PRESSURE : SOFT, + scale, paint_appl_mode); + } +} + + +static gpointer +gimp_paintbrush_tool_non_gui_paint_func (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + PaintState state) +{ + GImage *gimage; + gdouble fade_out; + gdouble gradient_length; + gdouble unit_factor; + + if (! (gimage = gimp_drawable_gimage (drawable))) + return NULL; + + switch (non_gui_fade_unit) + { + case GIMP_UNIT_PIXEL: + fade_out = non_gui_fade_out; + break; + case GIMP_UNIT_PERCENT: + fade_out = MAX (gimage->width, gimage->height) * + non_gui_fade_out / 100; + break; + default: + unit_factor = gimp_unit_get_factor (non_gui_fade_unit); + fade_out = non_gui_fade_out * + MAX (gimage->xresolution, gimage->yresolution) / unit_factor; + break; + } + + switch (non_gui_gradient_unit) + { + case GIMP_UNIT_PIXEL: + gradient_length = non_gui_gradient_length; + break; + case GIMP_UNIT_PERCENT: + gradient_length = MAX (gimage->width, gimage->height) * + non_gui_gradient_length / 100; + break; + default: + unit_factor = gimp_unit_get_factor (non_gui_gradient_unit); + gradient_length = non_gui_gradient_length * + MAX (gimage->xresolution, gimage->yresolution) / unit_factor; + break; + } + + gimp_paintbrush_tool_motion (paint_tool,drawable, + &non_gui_pressure_options, + fade_out, + gradient_length, + non_gui_incremental, + non_gui_gradient_type); + + return NULL; +} + +gboolean +gimp_paintbrush_tool_non_gui_default (GimpDrawable *drawable, + int num_strokes, + double *stroke_array) +{ + PaintbrushOptions *options = paintbrush_options; + gdouble fade_out = PAINTBRUSH_DEFAULT_FADE_OUT; + gboolean incremental = PAINTBRUSH_DEFAULT_INCREMENTAL; + gboolean use_gradient = PAINTBRUSH_DEFAULT_USE_GRADIENT; + gboolean use_fade = PAINTBRUSH_DEFAULT_USE_FADE; + gdouble gradient_length = PAINTBRUSH_DEFAULT_GRADIENT_LENGTH; + gint gradient_type = PAINTBRUSH_DEFAULT_GRADIENT_TYPE; + GimpUnit fade_unit = PAINTBRUSH_DEFAULT_FADE_UNIT; + GimpUnit gradient_unit = PAINTBRUSH_DEFAULT_GRADIENT_UNIT; + gint i; + + if (options) + { + fade_out = options->fade_out; + incremental = options->paint_options.incremental; + use_gradient = options->use_gradient; + gradient_length = options->gradient_length; + gradient_type = options->gradient_type; + use_fade = options->use_fade; + fade_unit = options->fade_unit; + gradient_unit = options->gradient_unit; + } + + if (use_gradient == FALSE) + gradient_length = 0.0; + + if (use_fade == FALSE) + fade_out = 0.0; + + /* Hmmm... PDB paintbrush should have gradient type added to it! + * thats why the code below is duplicated. + */ + if (gimp_paint_tool_start (&non_gui_paint_tool, drawable, + stroke_array[0], stroke_array[1])) + { + non_gui_fade_out = fade_out; + non_gui_gradient_length = gradient_length; + non_gui_gradient_type = gradient_type; + non_gui_incremental = incremental; + non_gui_fade_unit = fade_unit; + non_gui_gradient_unit = gradient_unit; + + /* Set the paint core's paint func */ + non_gui_paint_tool_class->paint_func =(PaintFunc) gimp_paintbrush_tool_non_gui_paint_func; + + non_gui_paint_tool->startx = non_gui_paint_tool->lastx = stroke_array[0]; + non_gui_paint_tool->starty = non_gui_paint_tool->lasty = stroke_array[1]; + + non_gui_paint_tool->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; + + gimp_paintbrush_tool_non_gui_paint_func (&non_gui_paint_tool, drawable, 0); + + for (i = 1; i < num_strokes; i++) + { + non_gui_paint_tool->curx = stroke_array[i * 2 + 0]; + non_gui_paint_tool->cury = stroke_array[i * 2 + 1]; + + gimp_paint_tool_interpolate (&non_gui_paint_tool, drawable); + + non_gui_paint_tool->lastx = non_gui_paint_tool->curx; + non_gui_paint_tool->lasty = non_gui_paint_tool->cury; + } + + /* Finish the painting */ + gimp_paint_tool_finish (&non_gui_paint_tool, drawable); + + /* Cleanup */ + gimp_paint_tool_cleanup (); + return TRUE; + } + else + return FALSE; +} + +gboolean +gimp_paintbrush_tool_non_gui (GimpDrawable *drawable, + int num_strokes, + double *stroke_array, + double fade_out, + int method, + double gradient_length) +{ + int i; + + /* Code duplicated above */ + if (gimp_paint_tool_start (&non_gui_paint_tool, drawable, + stroke_array[0], stroke_array[1])) + { + non_gui_fade_out = fade_out; + non_gui_gradient_length = gradient_length; + non_gui_gradient_type = LOOP_TRIANGLE; + non_gui_incremental = method; + + /* Set the paint core's paint func */ + non_gui_paint_tool_class->paint_func = gimp_paintbrush_tool_non_gui_paint_func; + + non_gui_paint_tool->startx = non_gui_paint_tool->lastx = stroke_array[0]; + non_gui_paint_tool->starty = non_gui_paint_tool->lasty = stroke_array[1]; + + non_gui_paint_tool->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH; + + if (num_strokes == 1) + gimp_paintbrush_tool_non_gui_paint_func (&non_gui_paint_tool, drawable, 0); + + for (i = 1; i < num_strokes; i++) + { + non_gui_paint_tool->curx = stroke_array[i * 2 + 0]; + non_gui_paint_tool->cury = stroke_array[i * 2 + 1]; + + gimp_paint_tool_interpolate (&non_gui_paint_tool, drawable); + + non_gui_paint_tool->lastx = non_gui_paint_tool->curx; + non_gui_paint_tool->lasty = non_gui_paint_tool->cury; + } + + /* Finish the painting */ + gimp_paint_tool_finish (&non_gui_paint_tool, drawable); + + /* Cleanup */ + gimp_paint_tool_cleanup (); + return TRUE; + } + else + return FALSE; +} diff --git a/app/tools/gimppaintbrushtool.h b/app/tools/gimppaintbrushtool.h new file mode 100644 index 0000000000..95b3b20454 --- /dev/null +++ b/app/tools/gimppaintbrushtool.h @@ -0,0 +1,59 @@ +/* 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 __GIMP_PAINTBRUSH_TOOL_H__ +#define __GIMP_PAINTBRUSH_TOOL_H__ + +#include "gimppainttool.h" + +#define GIMP_TYPE_PAINTBRUSH_TOOL (gimp_paintbrush_tool_get_type ()) +#define GIMP_PAINTBRUSH_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_PAINTBRUSH_TOOL, GimpPaintbrushTool)) +#define GIMP_IS_PAINTBRUSH_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_PAINTBRUSH_TOOL)) +#define GIMP_PAINTBRUSH_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PAINTBRUSH_TOOL, GimpPaintbrushToolClass)) +#define GIMP_IS_PAINTBRUSH_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PAINTBRUSH_TOOL)) + +struct _GimpPaintbrushTool +{ + GimpPaintTool parent_instance; +}; + +struct _GimpPaintbrushToolClass +{ + GimpPaintToolClass parent_class; +}; + +typedef struct _GimpPaintbrushTool GimpPaintbrushTool; +typedef struct _GimpPaintbrushToolClass GimpPaintbrushToolClass; + +/* FIXME: this antique code doesn't follow the coding style */ + +gboolean gimp_paintbrush_tool_non_gui (GimpDrawable *, + gint , + gdouble *, + gdouble , + gint , + gdouble ); +gboolean gimp_paintbrush_tool_non_gui_default (GimpDrawable *, + gint , + gdouble *); + +GimpTool * gimp_paintbrush_tool_new (void); + +GtkType gimp_paintbrush_tool_get_type (void); + +#endif /* __GIMP_PAINTBRUSH_TOOL_H__ */ diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c index 55a2daf85e..ab84b9d869 100644 --- a/app/tools/gimppaintoptions-gui.c +++ b/app/tools/gimppaintoptions-gui.c @@ -33,6 +33,8 @@ #include "tool.h" #include "tool_manager.h" +#include "gimppaintbrushtool.h" + #include "libgimp/gimpintl.h" diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c new file mode 100644 index 0000000000..02a021b311 --- /dev/null +++ b/app/tools/gimppainttool.c @@ -0,0 +1,2225 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include + +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +#include "apptypes.h" + +#include "brush_scale.h" +#include "cursorutil.h" +#include "devices.h" +#include "gimpdrawtool.h" +#include "drawable.h" +#include "gdisplay.h" +#include "gimage_mask.h" +#include "gimpbrushpipe.h" +#include "gimpcontext.h" +#include "gimpgradient.h" +#include "gimpimage.h" +#include "gimprc.h" +#include "paint_funcs.h" +#include "gimppainttool.h" +#include "pixel_region.h" +#include "selection.h" +#include "temp_buf.h" +#include "tile.h" +#include "tile_manager.h" +#include "tool.h" +#include "undo.h" + +#include "libgimp/gimpintl.h" + +#include "gimppainttool_kernels.h" + + +/* target size */ +#define TARGET_HEIGHT 15 +#define TARGET_WIDTH 15 + +#define EPSILON 0.00001 + +#define STATUSBAR_SIZE 128 + +/* global variables--for use in the various paint tools */ +GimpPaintTool *non_gui_painting_tool; +GimpPaintToolClass *non_gui_painting_tool_class; + +/* local function prototypes */ +static void gimp_paint_tool_calculate_brush_size (MaskBuf *mask, + gdouble scale, + gint *width, + gint *height); +static MaskBuf * gimp_paint_tool_subsample_mask (MaskBuf *mask, + gdouble x, + gdouble y); +static MaskBuf * gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask, + gdouble x, + gdouble y, + gdouble pressure); +static MaskBuf * gimp_paint_tool_solidify_mask (MaskBuf *brush_mask); +static MaskBuf * gimp_paint_tool_scale_mask (MaskBuf *brush_mask, + gdouble scale); +static MaskBuf * gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask, + gdouble scale); + +static MaskBuf * gimp_paint_tool_get_brush_mask (GimpPaintTool *gimp_paint_tool, + BrushApplicationMode brush_hardness, + gdouble scale); +static void gimp_paint_tool_paste (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + PaintApplicationMode mode); +static void gimp_paint_tool_replace (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + PaintApplicationMode mode); + +static void brush_to_canvas_tiles (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + gint brush_opacity); +static void brush_to_canvas_buf (GimpPaintTool *gimp_paint_tool, + MaskBuf *brush_mask, + gint brush_opacity); +static void canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool); + +static void set_undo_tiles (GimpDrawable *drawable, + gint x, + gint y, + gint w, + gint h); +static void set_canvas_tiles (gint x, + gint y, + gint w, + gint h); +static void gimp_paint_tool_invalidate_cache (GimpBrush *brush, + gpointer data); + + +/* paint buffers utility functions */ +static void free_paint_buffers (void); + +/* brush pipe utility functions */ +static void paint_line_pixmap_mask (GimpImage *dest, + GimpDrawable *drawable, + TempBuf *pixmap_mask, + TempBuf *brush_mask, + guchar *d, + gint x, + gint y, + gint bytes, + gint width, + BrushApplicationMode mode); + +/***********************************************************************/ + + +/* undo blocks variables */ +static TileManager *undo_tiles = NULL; +static TileManager *canvas_tiles = NULL; + + +/***********************************************************************/ + + +/* paint buffers variables */ +static TempBuf *orig_buf = NULL; +static TempBuf *canvas_buf = NULL; + + +/* brush buffers */ +static MaskBuf *pressure_brush; +static MaskBuf *solid_brush; +static MaskBuf *scale_brush = NULL; +static MaskBuf *scale_pixmap = NULL; +static MaskBuf *kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1]; + +static MaskBuf *last_brush_mask = NULL; +static gboolean cache_invalid = FALSE; + +static void gimp_paint_tool_initialize (GimpPaintTool *); +static void gimp_paint_tool_class_init (GimpToolClass *); + +enum { /* signals */ + PAINT, + LAST_SIGNAL +}; + +static guint gimp_paint_tool_signals[LAST_SIGNAL] = { 0 }; + +static void standard_paint_func (GimpPaintTool *tool) +{ +} + +GtkType +gimp_paint_tool_get_type (void) +{ + static GtkType tool_type = 0; + + g_message ("sizeof GimpPaintTool = %i, GimpPaintToolClass = %i", sizeof(GimpPaintTool), sizeof (GimpPaintToolClass)); + g_message ("sizeof GimpDrawTool = %i, GimpDrawToolClass = %i", sizeof(GimpDrawTool), sizeof (GimpDrawToolClass)); + + if (! tool_type) + { + GtkTypeInfo tool_info = + { + "GimpPaintTool", + sizeof (GimpPaintTool), + sizeof (GimpPaintToolClass), + (GtkClassInitFunc) gimp_paint_tool_class_init, + (GtkObjectInitFunc) gimp_paint_tool_initialize, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + NULL + }; + + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); + } + + return tool_type; +} + +GimpPaintTool * +gimp_paint_tool_new (void) +{ + return gtk_type_new (GIMP_TYPE_PAINT_TOOL); +} + +/***********************************************************************/ + +static void +gimp_paint_tool_sample_color (GimpDrawable *drawable, + gint x, + gint y, + gint state) +{ + GimpRGB color; + guchar *col; + + if( x >= 0 && x < gimp_drawable_width (drawable) && + y >= 0 && y < gimp_drawable_height (drawable)) + { + if ((col = gimp_drawable_get_color_at (drawable, x, y))) + { + gimp_rgba_set_uchar (&color, + col[RED_PIX], + col[GREEN_PIX], + col[BLUE_PIX], + 255); + + if ((state & GDK_CONTROL_MASK)) + gimp_context_set_foreground (gimp_context_get_user (), &color); + else + gimp_context_set_background (gimp_context_get_user (), &color); + + g_free (col); + } + } +} + + +void +gimp_paint_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GimpPaintTool *paint_tool; + GimpBrush *current_brush; + gboolean draw_line; + gdouble x, y; + GimpDrawable *drawable; + + g_return_if_fail (gdisp != NULL); + g_return_if_fail (tool != NULL); + + paint_tool = GIMP_PAINT_TOOL(tool); + + gdisplay_untransform_coords_f (gdisp, (double) bevent->x, (double) bevent->y, + &x, &y, TRUE); + drawable = gimp_image_active_drawable (gdisp->gimage); + + if (! gimp_paint_tool_start (paint_tool, drawable, x, y)) + return; + + draw_line = FALSE; + + paint_tool->curpressure = bevent->pressure; + paint_tool->curxtilt = bevent->xtilt; + paint_tool->curytilt = bevent->ytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = bevent->wheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + paint_tool->state = bevent->state; + + if (gdisp != tool->gdisp || + paint_tool->context_id < 1) + { + /* initialize the statusbar display */ + paint_tool->context_id = + gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); + } + + /* if this is a new image, reinit the core vals */ + if ((gdisp != tool->gdisp) || ! (bevent->state & GDK_SHIFT_MASK)) + { + /* initialize some values */ + paint_tool->startx = paint_tool->lastx = paint_tool->curx = x; + paint_tool->starty = paint_tool->lasty = paint_tool->cury = y; + paint_tool->startpressure = paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->startytilt = paint_tool->lastytilt = paint_tool->curytilt; + paint_tool->startxtilt = paint_tool->lastxtilt = paint_tool->curxtilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->startwheel = paint_tool->lastwheel = paint_tool->curwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + } + + /* If shift is down and this is not the first paint + * stroke, then draw a line from the last coords to the pointer + */ + else if (bevent->state & GDK_SHIFT_MASK) + { + draw_line = TRUE; + paint_tool->startx = paint_tool->lastx; + paint_tool->starty = paint_tool->lasty; + paint_tool->startpressure = paint_tool->lastpressure; + paint_tool->startxtilt = paint_tool->lastxtilt; + paint_tool->startytilt = paint_tool->lastytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->startwheel = paint_tool->lastwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + + /* Restrict to multiples of 15 degrees if ctrl is pressed */ + if (bevent->state & GDK_CONTROL_MASK) + { + gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; + gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; + gint dx, dy, i, radius, frac; + + dx = paint_tool->curx - paint_tool->lastx; + dy = paint_tool->cury - paint_tool->lasty; + + if (dy) + { + radius = sqrt (SQR (dx) + SQR (dy)); + frac = abs ((dx << 8) / dy); + for (i = 0; i < 6; i++) + { + if (frac < tangens2[i]) + break; + } + dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); + dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); + } + paint_tool->curx = paint_tool->lastx + dx; + paint_tool->cury = paint_tool->lasty + dy; + } + } + + tool->state = ACTIVE; + tool->gdisp = gdisp; + tool->paused_count = 0; + + /* pause the current selection and grab the pointer */ + gdisplays_selection_visibility (gdisp->gimage, SelectionPause); + + /* add motion memory if perfectmouse is set */ + if (perfectmouse != 0) + gdk_pointer_grab (gdisp->canvas->window, FALSE, + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, NULL, bevent->time); + else + gdk_pointer_grab (gdisp->canvas->window, FALSE, + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, NULL, bevent->time); + + /* Let the specific painting function initialize itself */ + gimp_paint_tool_paint(paint_tool, drawable, INIT_PAINT); + + if (paint_tool->pick_colors + && !(bevent->state & GDK_SHIFT_MASK) + && (bevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) + { + gimp_paint_tool_sample_color (drawable, x, y, bevent->state); + paint_tool->pick_state = TRUE; + return; + } + else + paint_tool->pick_state = FALSE; + + /* store the current brush pointer */ + current_brush = paint_tool->brush; + + /* Paint to the image */ + if (draw_line) + { + gimp_draw_tool_pause (GIMP_DRAW_TOOL(paint_tool)); + gimp_paint_tool_interpolate (paint_tool, drawable); + + paint_tool->lastx = paint_tool->curx; + paint_tool->lasty = paint_tool->cury; + paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->lastxtilt = paint_tool->curxtilt; + paint_tool->lastytilt = paint_tool->curytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->lastwheel = paint_tool->curwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + } + else + { + /* If we current point == last point, check if the brush + * wants to be painted in that case. (Direction dependent + * pixmap brush pipes don't, as they don't know which + * pixmap to select.) + */ + if (paint_tool->lastx != paint_tool->curx + || paint_tool->lasty != paint_tool->cury + || (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->want_null_motion) (paint_tool)) + { + if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) + paint_tool->brush = + (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->select_brush) (paint_tool); + + gimp_paint_tool_paint(paint_tool, drawable, MOTION_PAINT); + } + } + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, drawable, PRETRACE_PAINT); + + gdisplay_flush_now (gdisp); + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, drawable, POSTTRACE_PAINT); + + /* restore the current brush pointer */ + paint_tool->brush = current_brush; +} + +void +gimp_paint_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp) +{ + GImage *gimage; + GimpPaintTool *paint_tool; + + gimage = gdisp->gimage; + paint_tool = GIMP_PAINT_TOOL(tool); + + /* resume the current selection and ungrab the pointer */ + gdisplays_selection_visibility (gdisp->gimage, SelectionResume); + + gdk_pointer_ungrab (bevent->time); + gdk_flush (); + + /* Let the specific painting function finish up */ + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), + FINISH_PAINT); + + /* Set tool state to inactive -- no longer painting */ + gimp_draw_tool_stop (GIMP_DRAW_TOOL(paint_tool)); + tool->state = INACTIVE; + + paint_tool->pick_state = FALSE; + + gimp_paint_tool_finish (paint_tool, gimp_image_active_drawable (gdisp->gimage)); + gdisplays_flush (); +} + +void +gimp_paint_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpPaintTool *paint_tool; + + paint_tool = GIMP_PAINT_TOOL(tool); + + gdisplay_untransform_coords_f (gdisp, (double) mevent->x, (double) mevent->y, + &paint_tool->curx, &paint_tool->cury, TRUE); + + if (paint_tool->pick_state) + { + gimp_paint_tool_sample_color (gimp_image_active_drawable (gdisp->gimage), + paint_tool->curx, paint_tool->cury, + mevent->state); + return; + } + + paint_tool->curpressure = mevent->pressure; + paint_tool->curxtilt = mevent->xtilt; + paint_tool->curytilt = mevent->ytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = mevent->wheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + paint_tool->state = mevent->state; + + gimp_paint_tool_interpolate (paint_tool, + gimp_image_active_drawable (gdisp->gimage)); + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), + PRETRACE_PAINT); + + gdisplay_flush_now (gdisp); + + if (paint_tool->flags & TOOL_TRACES_ON_WINDOW) + gimp_paint_tool_paint(paint_tool, + gimp_image_active_drawable (gdisp->gimage), + POSTTRACE_PAINT); + + paint_tool->lastx = paint_tool->curx; + paint_tool->lasty = paint_tool->cury; + paint_tool->lastpressure = paint_tool->curpressure; + paint_tool->lastxtilt = paint_tool->curxtilt; + paint_tool->lastytilt = paint_tool->curytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->lastwheel = paint_tool->curwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ +} + + +/* FIXME: this belongs in the individual tools */ +void +gimp_paint_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp) +{ + GimpLayer *layer; + GimpPaintTool *paint_tool; + GimpDrawTool *draw_tool; + gint x, y; + gchar status_str[STATUSBAR_SIZE]; + + GdkCursorType ctype = GDK_TOP_LEFT_ARROW; + GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE; + gboolean ctoggle = FALSE; + + paint_tool = GIMP_PAINT_TOOL(tool); + draw_tool = GIMP_DRAW_TOOL(tool); + +/* undraw the current tool */ + gimp_draw_tool_pause (draw_tool); + + if (gdisp != tool->gdisp || paint_tool->context_id < 1) + { + /* initialize the statusbar display */ + paint_tool->context_id = + gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "paint"); + } + + if (paint_tool->context_id) + gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), paint_tool->context_id); + + if ((layer = gimp_image_get_active_layer (gdisp->gimage))) + { + /* If shift is down and this is not the first paint stroke, draw a line */ + if (gdisp == tool->gdisp && (mevent->state & GDK_SHIFT_MASK)) + { + gdouble dx, dy, d; + + ctype = GDK_PENCIL; + /* Get the current coordinates */ + gdisplay_untransform_coords_f (gdisp, + (double) mevent->x, + (double) mevent->y, + &paint_tool->curx, + &paint_tool->cury, TRUE); + + dx = paint_tool->curx - paint_tool->lastx; + dy = paint_tool->cury - paint_tool->lasty; + + /* Restrict to multiples of 15 degrees if ctrl is pressed */ + if (mevent->state & GDK_CONTROL_MASK) + { + gint idx = dx; + gint idy = dy; + gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 }; + gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 }; + gint i, radius, frac; + + if (idy) + { + radius = sqrt (SQR (idx) + SQR (idy)); + frac = abs ((idx << 8) / idy); + for (i = 0; i < 6; i++) + { + if (frac < tangens2[i]) + break; + } + dx = idx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8); + dy = idy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8); + } + + paint_tool->curx = paint_tool->lastx + dx; + paint_tool->cury = paint_tool->lasty + dy; + } + + /* show distance in statusbar */ + if (gdisp->dot_for_dot) + { + d = sqrt (SQR (dx) + SQR (dy)); + g_snprintf (status_str, STATUSBAR_SIZE, "%.1f %s", d, _("pixels")); + } + else + { + gchar *format_str = + g_strdup_printf ("%%.%df %s", + gimp_unit_get_digits (gdisp->gimage->unit), + gimp_unit_get_symbol (gdisp->gimage->unit)); + d = (gimp_unit_get_factor (gdisp->gimage->unit) * + sqrt (SQR (dx / gdisp->gimage->xresolution) + + SQR (dy / gdisp->gimage->yresolution))); + + g_snprintf (status_str, STATUSBAR_SIZE, format_str, d); + g_free (format_str); + } + + gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), + paint_tool->context_id, status_str); + + if (draw_tool->gc == NULL) + { + gimp_draw_tool_start (draw_tool, gdisp->canvas->window); + } + else + { + /* is this a bad hack ? */ + draw_tool->paused_count = 0; + gimp_draw_tool_resume (draw_tool); + } + } + /* If Ctrl or Mod1 is pressed, pick colors */ + else if (paint_tool->pick_colors && + !(mevent->state & GDK_SHIFT_MASK) && + (mevent->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) + { + ctype = GIMP_COLOR_PICKER_CURSOR; + } +#warning this doesnt belong here +#if 0 + /* Set toggle cursors for various paint tools */ + else if (tool->toggled) + { + switch (tool->type) + { + case ERASER: + ctype = GIMP_MOUSE_CURSOR; + cmodifier = CURSOR_MODIFIER_MINUS; + break; + case CONVOLVE: + ctype = GIMP_MOUSE_CURSOR; + cmodifier = CURSOR_MODIFIER_MINUS; + break; + case DODGEBURN: + ctype = GIMP_MOUSE_CURSOR; + ctoggle = TRUE; + break; + default: + ctype = GIMP_MOUSE_CURSOR; + break; + } + } +#endif + /* Normal operation -- no modifier pressed or first stroke */ + else + { + gint off_x, off_y; + + gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); + gdisplay_untransform_coords (gdisp, + (double) mevent->x, (double) mevent->y, + &x, &y, TRUE, FALSE); + + if (x >= off_x && y >= off_y && + x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) && + y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)))) + { + /* One more test--is there a selected region? + * if so, is cursor inside? + */ + if (gimage_mask_is_empty (gdisp->gimage)) + ctype = GIMP_MOUSE_CURSOR; + else if (gimage_mask_value (gdisp->gimage, x, y)) + ctype = GIMP_MOUSE_CURSOR; + } + } + + /* FIXME: install correct cursor */ + /*gdisplay_install_tool_cursor (gdisp, ctype, + ctype == GIMP_COLOR_PICKER_CURSOR ? + COLOR_PICKER : tool->type, + cmodifier, + ctoggle); */ + } +} + +void +gimp_paint_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp) +{ + GimpPaintTool *paint_tool; + GimpDrawable *drawable; + + paint_tool = GIMP_PAINT_TOOL (tool); + drawable = gimp_image_active_drawable (gdisp->gimage); + + switch (action) + { + case PAUSE: + break; + + case RESUME: + break; + + case HALT: + gimp_paint_tool_paint(paint_tool, drawable, FINISH_PAINT); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(tool)); + gimp_paint_tool_cleanup (); + break; + + default: + break; + } +} + +void +gimp_paint_tool_draw (GimpTool *tool) +{ + GDisplay *gdisp; + GimpPaintTool *paint_tool; + GimpDrawTool *draw_tool; + gint tx1, ty1, tx2, ty2; + + + paint_tool = GIMP_PAINT_TOOL(tool); + draw_tool = GIMP_DRAW_TOOL(tool); + + /* if shift was never used, draw_tool->gc is NULL + and we don't care about a redraw */ + if (draw_tool->gc != NULL) + { + gdisp = tool->gdisp; + + gdisplay_transform_coords (gdisp, paint_tool->lastx, paint_tool->lasty, + &tx1, &ty1, 1); + gdisplay_transform_coords (gdisp, paint_tool->curx, paint_tool->cury, + &tx2, &ty2, 1); + + /* Only draw line if it's in the visible area + * thus preventing from drawing rubbish + */ + + if (tx2 > 0 && ty2 > 0) + { + gint offx, offy; + + /* Adjust coords to start drawing from center of pixel if zoom > 1 */ + offx = (int) SCALEFACTOR_X (gdisp) >> 1; + offy = (int) SCALEFACTOR_Y (gdisp) >> 1; + tx1 += offx; + ty1 += offy; + tx2 += offx; + ty2 += offy; + + /* Draw start target */ + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx1 - (TARGET_WIDTH >> 1), ty1, + tx1 + (TARGET_WIDTH >> 1), ty1); + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx1, ty1 - (TARGET_HEIGHT >> 1), + tx1, ty1 + (TARGET_HEIGHT >> 1)); + + /* Draw end target */ + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx2 - (TARGET_WIDTH >> 1), ty2, + tx2 + (TARGET_WIDTH >> 1), ty2); + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx2, ty2 - (TARGET_HEIGHT >> 1), + tx2, ty2 + (TARGET_HEIGHT >> 1)); + + /* Draw the line between the start and end coords */ + gdk_draw_line (gdisp->canvas->window, draw_tool->gc, + tx1, ty1, tx2, ty2); + } + } + return; +} + +static void +gimp_paint_tool_initialize (GimpPaintTool *tool) +{ + tool->pick_colors = FALSE; + tool->flags = 0; + tool->context_id = 0; +} + +static void +gimp_paint_tool_class_init (GimpToolClass *klass) +{ + GtkObjectClass * oc = GTK_OBJECT_CLASS (klass); + GimpPaintToolClass * pc = GIMP_PAINT_TOOL_CLASS (klass); + + g_message ("gimp_paint_tool_class_init"); + + klass->button_press = gimp_paint_tool_button_press; + klass->button_release = gimp_paint_tool_button_release; + klass->motion = gimp_paint_tool_motion; + klass->cursor_update = gimp_paint_tool_cursor_update; + klass->control = gimp_paint_tool_control; + + gimp_paint_tool_signals[PAINT] = + gtk_signal_new ("paint", + GTK_RUN_FIRST, + oc->type, + GTK_SIGNAL_OFFSET (GimpPaintToolClass, + paint_func), + gtk_marshal_NONE__POINTER_INT, + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, GTK_TYPE_INT); + + gtk_object_class_add_signals (oc, gimp_paint_tool_signals, LAST_SIGNAL); + + pc->paint_func = (PaintFunc) standard_paint_func; + +} + +void +gimp_paint_tool_paint (GimpPaintTool *tool, GimpDrawable *drawable, PaintState state) +{ + gtk_signal_emit (GTK_OBJECT(tool), gimp_paint_tool_signals[PAINT], drawable, state); +} + +void +gimp_paint_tool_destroy (GimpTool *tool) +{ + GimpPaintTool * paint_tool; + GimpDrawTool * draw_tool; + + + paint_tool = GIMP_PAINT_TOOL (tool); + draw_tool = GIMP_DRAW_TOOL (tool); + + /* Make sure the selection core is not visible */ + if (tool->state == ACTIVE) + gimp_draw_tool_stop (draw_tool); + + /* Cleanup memory */ + gimp_paint_tool_cleanup (); +} + +gboolean +gimp_paint_tool_start (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gdouble x, + gdouble y) +{ + static GimpBrush *brush = NULL; + + paint_tool->curx = x; + paint_tool->cury = y; + + /* Set up some defaults for non-gui use */ + if (paint_tool == &non_gui_paint_tool) + { + paint_tool->startpressure = paint_tool->lastpressure = paint_tool->curpressure = 0.5; + paint_tool->startxtilt = paint_tool->lastxtilt = paint_tool->curxtilt = 0; + paint_tool->startytilt = paint_tool->lastytilt = paint_tool->curytilt = 0; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->startwheel = paint_tool->lastwheel = paint_tool->curwheel = 0.5; +#endif /* GTK_HAVE_SIX_VALUATORS */ + } + + /* Each buffer is the same size as the maximum bounds of the active brush... */ + if (brush && brush != gimp_context_get_brush (NULL)) + { + gtk_signal_disconnect_by_func (GTK_OBJECT (brush), + GTK_SIGNAL_FUNC (gimp_paint_tool_invalidate_cache), + NULL); + gtk_object_unref (GTK_OBJECT (brush)); + } + if (!(brush = gimp_context_get_brush (NULL))) + { + g_message (_("No brushes available for use with this tool.")); + return FALSE; + } + + gtk_object_ref (GTK_OBJECT (brush)); + gtk_signal_connect (GTK_OBJECT (brush), "invalidate_preview", + GTK_SIGNAL_FUNC (gimp_paint_tool_invalidate_cache), + NULL); + + paint_tool->spacing = (double) gimp_brush_get_spacing (brush) / 100.0; + + paint_tool->brush = brush; + + /* free the block structures */ + if (undo_tiles) + tile_manager_destroy (undo_tiles); + if (canvas_tiles) + tile_manager_destroy (canvas_tiles); + + /* Allocate the undo structure */ + undo_tiles = tile_manager_new (gimp_drawable_width (drawable), + gimp_drawable_height (drawable), + gimp_drawable_bytes (drawable)); + + /* Allocate the canvas blocks structure */ + canvas_tiles = tile_manager_new (gimp_drawable_width (drawable), + gimp_drawable_height (drawable), 1); + + /* Get the initial undo extents */ + paint_tool->x1 = paint_tool->x2 = paint_tool->curx; + paint_tool->y1 = paint_tool->y2 = paint_tool->cury; + paint_tool->distance = 0.0; + paint_tool->pixel_dist = 0.0; + + return TRUE; +} + +void +gimp_paint_tool_interpolate (GimpPaintTool *paint_tool, + GimpDrawable *drawable) +{ + GimpBrush *current_brush; + GimpVector2 delta; + gdouble dpressure, dxtilt, dytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble dwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + /* double spacing; */ + /* double lastscale, curscale; */ + gdouble n; + gdouble left; + gdouble t; + gdouble initial; + gdouble dist; + gdouble total; + gdouble pixel_dist; + gdouble pixel_initial; + gdouble xd, yd; + gdouble mag; + + delta.x = paint_tool->curx - paint_tool->lastx; + delta.y = paint_tool->cury - paint_tool->lasty; + dpressure = paint_tool->curpressure - paint_tool->lastpressure; + dxtilt = paint_tool->curxtilt - paint_tool->lastxtilt; + dytilt = paint_tool->curytilt - paint_tool->lastytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + dwheel = paint_tool->curwheel - paint_tool->lastwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + +/* return if there has been no motion */ +#ifdef GTK_HAVE_SIX_VALUATORS + if (!delta.x && !delta.y && !dpressure && !dxtilt && !dytilt && !dwheel) +#else /* !GTK_HAVE_SIX_VALUATORS */ + if (!delta.x && !delta.y && !dpressure && !dxtilt && !dytilt) +#endif /* GTK_HAVE_SIX_VALUATORS */ + return; + + /* calculate the distance traveled in the coordinate space of the brush */ + mag = gimp_vector2_length (&(paint_tool->brush->x_axis)); + xd = gimp_vector2_inner_product (&delta, + &(paint_tool->brush->x_axis)) / (mag*mag); + + mag = gimp_vector2_length (&(paint_tool->brush->y_axis)); + yd = gimp_vector2_inner_product (&delta, + &(paint_tool->brush->y_axis)) / (mag*mag); + + dist = 0.5 * sqrt (xd*xd + yd*yd); + total = dist + paint_tool->distance; + initial = paint_tool->distance; + + pixel_dist = gimp_vector2_length (&delta); + pixel_initial = paint_tool->pixel_dist; + + /* FIXME: need to adapt the spacing to the size */ + /* lastscale = MIN (gimp_paint_tool->lastpressure, 1/256); */ + /* curscale = MIN (gimp_paint_tool->curpressure, 1/256); */ + /* spacing = gimp_paint_tool->spacing * sqrt (0.5 * (lastscale + curscale)); */ + + while (paint_tool->distance < total) + { + n = (gint) (paint_tool->distance / paint_tool->spacing + 1.0 + EPSILON); + left = n * paint_tool->spacing - paint_tool->distance; + + paint_tool->distance += left; + + if (paint_tool->distance <= (total+EPSILON)) + { + t = (paint_tool->distance - initial) / dist; + + paint_tool->curx = paint_tool->lastx + delta.x * t; + paint_tool->cury = paint_tool->lasty + delta.y * t; + paint_tool->pixel_dist = pixel_initial + pixel_dist * t; + paint_tool->curpressure = paint_tool->lastpressure + dpressure * t; + paint_tool->curxtilt = paint_tool->lastxtilt + dxtilt * t; + paint_tool->curytilt = paint_tool->lastytilt + dytilt * t; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = paint_tool->lastwheel + dwheel * t; +#endif /* GTK_HAVE_SIX_VALUATORS */ + + /* save the current brush */ + current_brush = paint_tool->brush; + + if (paint_tool->flags & TOOL_CAN_HANDLE_CHANGING_BRUSH) + paint_tool->brush = + (* GIMP_BRUSH_CLASS (GTK_OBJECT (paint_tool->brush) + ->klass)->select_brush) (paint_tool); + gimp_paint_tool_paint(paint_tool, drawable, MOTION_PAINT); + + /* restore the current brush pointer */ + paint_tool->brush = current_brush; + } + } + + paint_tool->distance = total; + paint_tool->pixel_dist = pixel_initial + pixel_dist; + paint_tool->curx = paint_tool->lastx + delta.x; + paint_tool->cury = paint_tool->lasty + delta.y; + paint_tool->curpressure = paint_tool->lastpressure + dpressure; + paint_tool->curxtilt = paint_tool->lastxtilt + dxtilt; + paint_tool->curytilt = paint_tool->lastytilt + dytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + paint_tool->curwheel = paint_tool->lastwheel + dwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ +} + +void +gimp_paint_tool_finish (GimpPaintTool *paint_tool, + GimpDrawable *drawable) +{ + GImage *gimage; + PaintUndo *pu; + + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + /* Determine if any part of the image has been altered-- + * if nothing has, then just return... + */ + + if ((paint_tool->x2 == paint_tool->x1) || + (paint_tool->y2 == paint_tool->y1)) + return; + + undo_push_group_start (gimage, PAINT_CORE_UNDO); + + pu = g_new (PaintUndo, 1); + pu->tool = paint_tool; + pu->lastx = paint_tool->startx; + pu->lasty = paint_tool->starty; + pu->lastpressure = paint_tool->startpressure; + pu->lastxtilt = paint_tool->startxtilt; + pu->lastytilt = paint_tool->startytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + pu->lastwheel = paint_tool->startwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ + + /* Push a paint undo */ + undo_push_paint (gimage, pu); + + /* push an undo */ + drawable_apply_image (drawable, paint_tool->x1, paint_tool->y1, + paint_tool->x2, paint_tool->y2, undo_tiles, TRUE); + undo_tiles = NULL; + + /* push the group end */ + undo_push_group_end (gimage); + + /* invalidate the drawable--have to do it here, because + * it is not done during the actual painting. + */ + gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable)); +} + +void +gimp_paint_tool_cleanup (void) +{ + /* CLEANUP */ + /* If the undo tiles exist, nuke them */ + if (undo_tiles) + { + tile_manager_destroy (undo_tiles); + undo_tiles = NULL; + } + + /* If the canvas blocks exist, nuke them */ + if (canvas_tiles) + { + tile_manager_destroy (canvas_tiles); + canvas_tiles = NULL; + } + + /* Free the temporary buffers if they exist */ + free_paint_buffers (); +} + +void +gimp_paint_tool_get_color_from_gradient (GimpPaintTool *paint_tool, + gdouble gradient_length, + GimpRGB *color, + GradientPaintMode mode) +{ + gdouble y; + gdouble distance; /* distance in current brush stroke */ + + distance = paint_tool->pixel_dist; + y = ((double) distance / gradient_length); + + /* for the once modes, set y close to 1.0 after the first chunk */ + if ( (mode == ONCE_FORWARD || mode == ONCE_BACKWARDS) && y >= 1.0 ) + y = 0.9999999; + + if ( (((int)y & 1) && mode != LOOP_SAWTOOTH) || mode == ONCE_BACKWARDS ) + y = 1.0 - (y - (int)y); + else + y = y - (int)y; + + gimp_gradient_get_color_at (gimp_context_get_gradient (NULL), y, color); +} + + +/************************/ +/* Painting functions */ +/************************/ + +TempBuf * +gimp_paint_tool_get_paint_area (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gdouble scale) +{ + gint x, y; + gint x1, y1, x2, y2; + gint bytes; + gint dwidth, dheight; + gint bwidth, bheight; + + bytes = gimp_drawable_has_alpha (drawable) ? + gimp_drawable_bytes (drawable) : gimp_drawable_bytes (drawable) + 1; + + gimp_paint_tool_calculate_brush_size (paint_tool->brush->mask, scale, + &bwidth, &bheight); + + /* adjust the x and y coordinates to the upper left corner of the brush */ + x = (gint) floor (paint_tool->curx) - (bwidth >> 1); + y = (gint) floor (paint_tool->cury) - (bheight >> 1); + + dwidth = gimp_drawable_width (drawable); + dheight = gimp_drawable_height (drawable); + + x1 = CLAMP (x - 1, 0, dwidth); + y1 = CLAMP (y - 1, 0, dheight); + x2 = CLAMP (x + bwidth + 1, 0, dwidth); + y2 = CLAMP (y + bheight + 1, 0, dheight); + + /* configure the canvas buffer */ + if ((x2 - x1) && (y2 - y1)) + canvas_buf = temp_buf_resize (canvas_buf, bytes, x1, y1, + (x2 - x1), (y2 - y1)); + else + return NULL; + + return canvas_buf; +} + +TempBuf * +gimp_paint_tool_get_orig_image (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint x1, + gint y1, + gint x2, + gint y2) +{ + PixelRegion srcPR; + PixelRegion destPR; + Tile *undo_tile; + gint h; + gint refd; + gint pixelwidth; + gint dwidth; + gint dheight; + guchar *s; + guchar *d; + gpointer pr; + + orig_buf = temp_buf_resize (orig_buf, gimp_drawable_bytes (drawable), + x1, y1, (x2 - x1), (y2 - y1)); + + dwidth = gimp_drawable_width (drawable); + dheight = gimp_drawable_height (drawable); + + x1 = CLAMP (x1, 0, dwidth); + y1 = CLAMP (y1, 0, dheight); + x2 = CLAMP (x2, 0, dwidth); + y2 = CLAMP (y2, 0, dheight); + + /* configure the pixel regions */ + pixel_region_init (&srcPR, gimp_drawable_data (drawable), x1, y1, + (x2 - x1), (y2 - y1), FALSE); + destPR.bytes = orig_buf->bytes; + destPR.x = 0; destPR.y = 0; + destPR.w = (x2 - x1); destPR.h = (y2 - y1); + destPR.rowstride = orig_buf->bytes * orig_buf->width; + destPR.data = temp_buf_data (orig_buf) + + (y1 - orig_buf->y) * destPR.rowstride + (x1 - orig_buf->x) * destPR.bytes; + + for (pr = pixel_regions_register (2, &srcPR, &destPR); + pr != NULL; + pr = pixel_regions_process (pr)) + { + /* If the undo tile corresponding to this location is valid, use it */ + undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y, + FALSE, FALSE); + if (tile_is_valid (undo_tile) == TRUE) + { + refd = 1; + undo_tile = tile_manager_get_tile (undo_tiles, srcPR.x, srcPR.y, + TRUE, FALSE); + s = (unsigned char*)tile_data_pointer (undo_tile, 0, 0) + + srcPR.rowstride * (srcPR.y % TILE_HEIGHT) + + srcPR.bytes * (srcPR.x % TILE_WIDTH); /* dubious... */ + } + else + { + refd = 0; + s = srcPR.data; + } + + d = destPR.data; + pixelwidth = srcPR.w * srcPR.bytes; + h = srcPR.h; + while (h --) + { + memcpy (d, s, pixelwidth); + s += srcPR.rowstride; + d += destPR.rowstride; + } + + if (refd) + tile_release (undo_tile, FALSE); + } + + return orig_buf; +} + +void +gimp_paint_tool_paste_canvas (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode) +{ + MaskBuf *brush_mask; + + /* get the brush mask */ + brush_mask = gimp_paint_tool_get_brush_mask (paint_tool, + brush_hardness, brush_scale); + + /* paste the canvas buf */ + gimp_paint_tool_paste (paint_tool, brush_mask, drawable, + brush_opacity, image_opacity, paint_mode, mode); +} + +/* Similar to gimp_paint_tool_paste_canvas, but replaces the alpha channel + rather than using it to composite (i.e. transparent over opaque + becomes transparent rather than opauqe. */ +void +gimp_paint_tool_replace_canvas (GimpPaintTool *paint_tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode) +{ + MaskBuf *brush_mask; + + /* get the brush mask */ + brush_mask = + gimp_paint_tool_get_brush_mask (paint_tool, brush_hardness, brush_scale); + + /* paste the canvas buf */ + gimp_paint_tool_replace (paint_tool, brush_mask, drawable, + brush_opacity, image_opacity, mode); +} + + +static void +gimp_paint_tool_invalidate_cache (GimpBrush *brush, + gpointer data) +{ + /* Make sure we don't cache data for a brush that has changed */ + if (last_brush_mask == brush->mask) + cache_invalid = TRUE; +} + +/************************************************************ + * LOCAL FUNCTION DEFINITIONS * + ************************************************************/ + +static void +gimp_paint_tool_calculate_brush_size (MaskBuf *mask, + gdouble scale, + gint *width, + gint *height) +{ + scale = CLAMP (scale, 0.0, 1.0); + + if (current_device == GDK_CORE_POINTER) + { + *width = mask->width; + *height = mask->height; + } + else + { + gdouble ratio; + + if (scale < 1 / 256) + ratio = 1 / 16; + else + ratio = sqrt (scale); + + *width = MAX ((gint) (mask->width * ratio + 0.5), 1); + *height = MAX ((gint) (mask->height * ratio + 0.5), 1); + } +} + +static MaskBuf * +gimp_paint_tool_subsample_mask (MaskBuf *mask, + gdouble x, + gdouble y) +{ + MaskBuf *dest; + gdouble left; + guchar *m; + guchar *d; + const gint *k; + gint index1; + gint index2; + const gint *kernel; + gint new_val; + gint i, j; + gint r, s; + + x += (x < 0) ? mask->width : 0; + left = x - floor (x); + index1 = (gint) (left * (gdouble) (SUBSAMPLE + 1)); + + y += (y < 0) ? mask->height : 0; + left = y - floor (y); + index2 = (gint) (left * (gdouble) (SUBSAMPLE + 1)); + + kernel = subsample[index2][index1]; + + if (mask == last_brush_mask && !cache_invalid) + { + if (kernel_brushes[index2][index1]) + return kernel_brushes[index2][index1]; + } + else + { + for (i = 0; i <= SUBSAMPLE; i++) + for (j = 0; j <= SUBSAMPLE; j++) + { + if (kernel_brushes[i][j]) + mask_buf_free (kernel_brushes[i][j]); + + kernel_brushes[i][j] = NULL; + } + + last_brush_mask = mask; + cache_invalid = FALSE; + } + + dest = kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, + mask->height + 2); + + m = mask_buf_data (mask); + for (i = 0; i < mask->height; i++) + { + for (j = 0; j < mask->width; j++) + { + k = kernel; + for (r = 0; r < KERNEL_HEIGHT; r++) + { + d = mask_buf_data (dest) + (i+r) * dest->width + j; + s = KERNEL_WIDTH; + while (s--) + { + new_val = *d + ((*m * *k++ + 128) >> 8); + *d++ = MIN (new_val, 255); + } + } + m++; + } + } + + return dest; +} + +/* #define FANCY_PRESSURE */ + +static MaskBuf * +gimp_paint_tool_pressurize_mask (MaskBuf *brush_mask, + gdouble x, + gdouble y, + gdouble pressure) +{ + static MaskBuf *last_brush = NULL; + static guchar mapi[256]; + guchar *source; + guchar *dest; + MaskBuf *subsample_mask; + gint i; +#ifdef FANCY_PRESSURE + static gdouble map[256]; + gdouble ds, s, c; +#endif + + /* Get the raw subsampled mask */ + subsample_mask = gimp_paint_tool_subsample_mask (brush_mask, x, y); + + /* Special case pressure = 0.5 */ + if ((int)(pressure * 100 + 0.5) == 50) + return subsample_mask; + + /* Make sure we have the right sized buffer */ + if (brush_mask != last_brush) + { + if (pressure_brush) + mask_buf_free (pressure_brush); + + pressure_brush = mask_buf_new (brush_mask->width + 2, + brush_mask->height + 2); + } + +#ifdef FANCY_PRESSURE + /* Create the pressure profile + + It is: I'(I) = tanh(20*(pressure-0.5)*I) : pressure > 0.5 + I'(I) = 1 - tanh(20*(0.5-pressure)*(1-I)) : pressure < 0.5 + + It looks like: + + low pressure medium pressure high pressure + + | / -- + | / / + / / | + -- / | + + */ + + ds = (pressure - 0.5)*(20./256.); + s = 0; + c = 1.0; + + if (ds > 0) + { + for (i=0;i<256;i++) + { + map[i] = s/c; + s += c*ds; + c += s*ds; + } + for (i=0;i<256;i++) + mapi[i] = (int)(255*map[i]/map[255]); + } + else + { + ds = -ds; + for (i=255;i>=0;i--) + { + map[i] = s/c; + s += c*ds; + c += s*ds; + } + for (i=0;i<256;i++) + mapi[i] = (int)(255*(1-map[i]/map[0])); + } +#else /* ! FANCY_PRESSURE */ + + for (i = 0; i < 256; i++) + { + gint tmp = (pressure / 0.5) * i; + + if (tmp > 255) + mapi[i] = 255; + else + mapi[i] = tmp; + } + +#endif /* FANCY_PRESSURE */ + + /* Now convert the brush */ + + source = mask_buf_data (subsample_mask); + dest = mask_buf_data (pressure_brush); + + i = subsample_mask->width * subsample_mask->height; + while (i--) + { + *dest++ = mapi[(*source++)]; + } + + return pressure_brush; +} + +static MaskBuf * +gimp_paint_tool_solidify_mask (MaskBuf *brush_mask) +{ + static MaskBuf *last_brush = NULL; + gint i; + gint j; + guchar *data; + guchar *src; + + if (brush_mask == last_brush && !cache_invalid) + return solid_brush; + + last_brush = brush_mask; + + if (solid_brush) + mask_buf_free (solid_brush); + + solid_brush = mask_buf_new (brush_mask->width + 2, brush_mask->height + 2); + + /* get the data and advance one line into it */ + data = mask_buf_data (solid_brush) + solid_brush->width; + src = mask_buf_data (brush_mask); + + for (i = 0; i < brush_mask->height; i++) + { + data++; + for (j = 0; j < brush_mask->width; j++) + { + *data++ = (*src++) ? OPAQUE_OPACITY : TRANSPARENT_OPACITY; + } + data++; + } + + return solid_brush; +} + +static MaskBuf * +gimp_paint_tool_scale_mask (MaskBuf *brush_mask, + gdouble scale) +{ + static MaskBuf *last_brush = NULL; + static gint last_width = 0.0; + static gint last_height = 0.0; + gint dest_width; + gint dest_height; + + scale = CLAMP (scale, 0.0, 1.0); + + if (scale == 0.0) + return NULL; + + if (scale == 1.0) + return brush_mask; + + gimp_paint_tool_calculate_brush_size (brush_mask, scale, + &dest_width, &dest_height); + + if (brush_mask == last_brush && !cache_invalid && + dest_width == last_width && dest_height == last_height) + return scale_brush; + + if (scale_brush) + mask_buf_free (scale_brush); + + last_brush = brush_mask; + last_width = dest_width; + last_height = dest_height; + + scale_brush = brush_scale_mask (brush_mask, dest_width, dest_height); + cache_invalid = TRUE; + + return scale_brush; +} + +static MaskBuf * +gimp_paint_tool_scale_pixmap (MaskBuf *brush_mask, + gdouble scale) +{ + static MaskBuf *last_brush = NULL; + static gint last_width = 0.0; + static gint last_height = 0.0; + gint dest_width; + gint dest_height; + + scale = CLAMP (scale, 0.0, 1.0); + + if (scale == 0.0) + return NULL; + + if (scale == 1.0) + return brush_mask; + + gimp_paint_tool_calculate_brush_size (brush_mask, scale, + &dest_width, &dest_height); + + if (brush_mask == last_brush && !cache_invalid && + dest_width == last_width && dest_height == last_height) + return scale_pixmap; + + if (scale_pixmap) + mask_buf_free (scale_pixmap); + + last_brush = brush_mask; + last_width = dest_width; + last_height = dest_height; + + scale_pixmap = brush_scale_pixmap (brush_mask, dest_width, dest_height); + cache_invalid = TRUE; + + return scale_pixmap; +} + +static MaskBuf * +gimp_paint_tool_get_brush_mask (GimpPaintTool *paint_tool, + BrushApplicationMode brush_hardness, + gdouble scale) +{ + MaskBuf *mask; + + if (current_device == GDK_CORE_POINTER) + mask = paint_tool->brush->mask; + else + mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale); + + switch (brush_hardness) + { + case SOFT: + mask = gimp_paint_tool_subsample_mask (mask, + paint_tool->curx, paint_tool->cury); + break; + case HARD: + mask = gimp_paint_tool_solidify_mask (mask); + break; + case PRESSURE: + mask = gimp_paint_tool_pressurize_mask (mask, + paint_tool->curx, paint_tool->cury, + paint_tool->curpressure); + break; + default: + break; + } + + return mask; +} + +static void +gimp_paint_tool_paste (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + PaintApplicationMode mode) +{ + GimpImage *gimage; + PixelRegion srcPR; + TileManager *alt = NULL; + gint offx; + gint offy; + + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + /* set undo blocks */ + set_undo_tiles (drawable, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + /* If the mode is CONSTANT: + * combine the canvas buf, the brush mask to the canvas tiles + */ + if (mode == CONSTANT) + { + /* initialize any invalid canvas tiles */ + set_canvas_tiles (canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity); + canvas_tiles_to_canvas_buf (paint_tool); + alt = undo_tiles; + } + /* Otherwise: + * combine the canvas buf and the brush mask to the canvas buf + */ + else + { + brush_to_canvas_buf (paint_tool, brush_mask, brush_opacity); + } + + /* intialize canvas buf source pixel regions */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + /* apply the paint area to the gimage */ + gimp_image_apply_image (gimage, drawable, &srcPR, + FALSE, image_opacity, paint_mode, + alt, /* specify an alternative src1 */ + canvas_buf->x, canvas_buf->y); + + /* Update the undo extents */ + paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x); + paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y); + paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width)); + paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height)); + + /* Update the gimage--it is important to call gdisplays_update_area + * instead of drawable_update because we don't want the drawable + * preview to be constantly invalidated + */ + gimp_drawable_offsets (drawable, &offx, &offy); + gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, + canvas_buf->width, canvas_buf->height); +} + +/* This works similarly to gimp_paint_tool_paste. However, instead of combining + the canvas to the paint core drawable using one of the combination + modes, it uses a "replace" mode (i.e. transparent pixels in the + canvas erase the paint core drawable). + + When not drawing on alpha-enabled images, it just paints using NORMAL + mode. +*/ +static void +gimp_paint_tool_replace (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + PaintApplicationMode mode) +{ + GimpImage *gimage; + PixelRegion srcPR; + PixelRegion maskPR; + TileManager *alt = NULL; + gint offx; + gint offy; + + if (! gimp_drawable_has_alpha (drawable)) + { + gimp_paint_tool_paste (paint_tool, brush_mask, drawable, + brush_opacity, image_opacity, NORMAL_MODE, + mode); + return; + } + + if (! (gimage = gimp_drawable_gimage (drawable))) + return; + + /* set undo blocks */ + set_undo_tiles (drawable, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + if (mode == CONSTANT) + { + /* initialize any invalid canvas tiles */ + set_canvas_tiles (canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height); + + /* combine the brush mask and the canvas tiles */ + brush_to_canvas_tiles (paint_tool, brush_mask, brush_opacity); + + /* set the alt source as the unaltered undo_tiles */ + alt = undo_tiles; + + /* initialize the maskPR from the canvas tiles */ + pixel_region_init (&maskPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, FALSE); + } + else + { + /* The mask is just the brush mask */ + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = canvas_buf->width; + maskPR.h = canvas_buf->height; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask); + } + + /* intialize canvas buf source pixel regions */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + /* apply the paint area to the gimage */ + gimp_image_replace_image (gimage, drawable, &srcPR, + FALSE, image_opacity, + &maskPR, + canvas_buf->x, canvas_buf->y); + + /* Update the undo extents */ + paint_tool->x1 = MIN (paint_tool->x1, canvas_buf->x); + paint_tool->y1 = MIN (paint_tool->y1, canvas_buf->y); + paint_tool->x2 = MAX (paint_tool->x2, (canvas_buf->x + canvas_buf->width)); + paint_tool->y2 = MAX (paint_tool->y2, (canvas_buf->y + canvas_buf->height)); + + /* Update the gimage--it is important to call gdisplays_update_area + * instead of drawable_update because we don't want the drawable + * preview to be constantly invalidated + */ + gimp_drawable_offsets (drawable, &offx, &offy); + gdisplays_update_area (gimage, canvas_buf->x + offx, canvas_buf->y + offy, + canvas_buf->width, canvas_buf->height); +} + +static void +canvas_tiles_to_canvas_buf (GimpPaintTool *gimp_paint_tool) +{ + PixelRegion srcPR; + PixelRegion maskPR; + + /* combine the canvas tiles and the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + pixel_region_init (&maskPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, FALSE); + + /* apply the canvas tiles to the canvas buf */ + apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); +} + +static void +brush_to_canvas_tiles (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + /* combine the brush mask and the canvas tiles */ + pixel_region_init (&srcPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, TRUE); + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* combine the mask to the canvas tiles */ + combine_mask_and_region (&srcPR, &maskPR, brush_opacity); +} + +static void +brush_to_canvas_buf (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + /* combine the canvas buf and the brush mask to the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* apply the mask */ + apply_mask_to_region (&srcPR, &maskPR, brush_opacity); +} + +#if 0 +static void +paint_to_canvas_tiles (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + /* combine the brush mask and the canvas tiles */ + pixel_region_init (&srcPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, TRUE); + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* combine the mask and canvas tiles */ + combine_mask_and_region (&srcPR, &maskPR, brush_opacity); + + /* combine the canvas tiles and the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + pixel_region_init (&maskPR, canvas_tiles, + canvas_buf->x, canvas_buf->y, + canvas_buf->width, canvas_buf->height, FALSE); + + /* apply the canvas tiles to the canvas buf */ + apply_mask_to_region (&srcPR, &maskPR, OPAQUE_OPACITY); +} + +static void +paint_to_canvas_buf (GimpPaintTool *paint_tool, + MaskBuf *brush_mask, + gint brush_opacity) +{ + PixelRegion srcPR; + PixelRegion maskPR; + gint x; + gint y; + gint xoff; + gint yoff; + + x = (gint) floor (paint_tool->curx) - (brush_mask->width >> 1); + y = (gint) floor (paint_tool->cury) - (brush_mask->height >> 1); + xoff = (x < 0) ? -x : 0; + yoff = (y < 0) ? -y : 0; + + + /* combine the canvas buf and the brush mask to the canvas buf */ + srcPR.bytes = canvas_buf->bytes; + srcPR.x = 0; + srcPR.y = 0; + srcPR.w = canvas_buf->width; + srcPR.h = canvas_buf->height; + srcPR.rowstride = canvas_buf->width * canvas_buf->bytes; + srcPR.data = temp_buf_data (canvas_buf); + + maskPR.bytes = 1; + maskPR.x = 0; + maskPR.y = 0; + maskPR.w = srcPR.w; + maskPR.h = srcPR.h; + maskPR.rowstride = maskPR.bytes * brush_mask->width; + maskPR.data = mask_buf_data (brush_mask) + yoff * maskPR.rowstride + xoff * maskPR.bytes; + + /* apply the mask */ + apply_mask_to_region (&srcPR, &maskPR, brush_opacity); +} +#endif + +static void +set_undo_tiles (GimpDrawable *drawable, + gint x, + gint y, + gint w, + gint h) +{ + gint i; + gint j; + Tile *src_tile; + Tile *dest_tile; + + if (undo_tiles == NULL) + { + g_warning ("set_undo_tiles: undo_tiles is null"); + return; + } + + for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) + { + for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) + { + dest_tile = tile_manager_get_tile (undo_tiles, j, i, FALSE, FALSE); + if (tile_is_valid (dest_tile) == FALSE) + { + src_tile = tile_manager_get_tile (gimp_drawable_data (drawable), + j, i, TRUE, FALSE); + tile_manager_map_tile (undo_tiles, j, i, src_tile); + tile_release (src_tile, FALSE); + } + } + } +} + +static void +set_canvas_tiles (gint x, + gint y, + gint w, + gint h) +{ + gint i; + gint j; + Tile *tile; + + for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) + { + for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) + { + tile = tile_manager_get_tile (canvas_tiles, j, i, FALSE, FALSE); + if (tile_is_valid (tile) == FALSE) + { + tile = tile_manager_get_tile (canvas_tiles, j, i, TRUE, TRUE); + memset (tile_data_pointer (tile, 0, 0), 0, tile_size (tile)); + tile_release (tile, TRUE); + } + } + } +} + + +/*****************************************************/ +/* Paint buffers utility functions */ +/*****************************************************/ + + +static void +free_paint_buffers (void) +{ + if (orig_buf) + temp_buf_free (orig_buf); + orig_buf = NULL; + + if (canvas_buf) + temp_buf_free (canvas_buf); + canvas_buf = NULL; +} + + +/**************************************************/ +/* Brush pipe utility functions */ +/**************************************************/ + +void +gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *paint_tool, + GimpImage *dest, + GimpDrawable *drawable, + TempBuf *area, + gdouble scale, + BrushApplicationMode mode) +{ + PixelRegion destPR; + void *pr; + guchar *d; + gint ulx; + gint uly; + gint offsetx; + gint offsety; + gint y; + TempBuf *pixmap_mask; + TempBuf *brush_mask; + + g_return_if_fail (GIMP_IS_BRUSH (paint_tool->brush)); + g_return_if_fail (paint_tool->brush->pixmap != NULL); + + /* scale the brushes */ + pixmap_mask = gimp_paint_tool_scale_pixmap (paint_tool->brush->pixmap, scale); + + if (mode == SOFT) + brush_mask = gimp_paint_tool_scale_mask (paint_tool->brush->mask, scale); + else + brush_mask = NULL; + + destPR.bytes = area->bytes; + destPR.x = 0; + destPR.y = 0; + destPR.w = area->width; + destPR.h = area->height; + destPR.rowstride = destPR.bytes * area->width; + destPR.data = temp_buf_data (area); + + pr = pixel_regions_register (1, &destPR); + + /* Calculate upper left corner of brush as in + * gimp_paint_tool_get_paint_area. Ugly to have to do this here, too. + */ + + ulx = (gint) floor (paint_tool->curx) - (pixmap_mask->width >> 1); + uly = (gint) floor (paint_tool->cury) - (pixmap_mask->height >> 1); + + offsetx = area->x - ulx; + offsety = area->y - uly; + + for (; pr != NULL; pr = pixel_regions_process (pr)) + { + d = destPR.data; + for (y = 0; y < destPR.h; y++) + { + paint_line_pixmap_mask (dest, drawable, pixmap_mask, brush_mask, + d, offsetx, y + offsety, + destPR.bytes, destPR.w, mode); + d += destPR.rowstride; + } + } +} + +static void +paint_line_pixmap_mask (GimpImage *dest, + GimpDrawable *drawable, + TempBuf *pixmap_mask, + TempBuf *brush_mask, + guchar *d, + gint x, + gint y, + gint bytes, + gint width, + BrushApplicationMode mode) +{ + guchar *b; + guchar *p; + guchar *mask; + gdouble alpha; + gdouble factor = 0.00392156986; /* 1.0 / 255.0 */ + gint x_index; + gint i,byte_loop; + + /* Make sure x, y are positive */ + while (x < 0) + x += pixmap_mask->width; + while (y < 0) + y += pixmap_mask->height; + + /* Point to the approriate scanline */ + b = temp_buf_data (pixmap_mask) + + (y % pixmap_mask->height) * pixmap_mask->width * pixmap_mask->bytes; + + if (mode == SOFT && brush_mask) + { + /* ditto, except for the brush mask, so we can pre-multiply the alpha value */ + mask = temp_buf_data (brush_mask) + + (y % brush_mask->height) * brush_mask->width; + for (i = 0; i < width; i++) + { + /* attempt to avoid doing this calc twice in the loop */ + x_index = ((i + x) % pixmap_mask->width); + p = b + x_index * pixmap_mask->bytes; + d[bytes-1] = mask[x_index]; + + /* multiply alpha into the pixmap data */ + /* maybe we could do this at tool creation or brush switch time? */ + /* and compute it for the whole brush at once and cache it? */ + alpha = d[bytes-1] * factor; + if(alpha) + for (byte_loop = 0; byte_loop < bytes - 1; byte_loop++) + d[byte_loop] *= alpha; + + /* printf("i: %i d->r: %i d->g: %i d->b: %i d->a: %i\n",i,(int)d[0], (int)d[1], (int)d[2], (int)d[3]); */ + gimp_image_transform_color (dest, drawable, p, d, RGB); + d += bytes; + } + } + else + { + for (i = 0; i < width; i++) + { + /* attempt to avoid doing this calc twice in the loop */ + x_index = ((i + x) % pixmap_mask->width); + p = b + x_index * pixmap_mask->bytes; + d[bytes-1] = 255; + + /* multiply alpha into the pixmap data */ + /* maybe we could do this at tool creation or brush switch time? */ + /* and compute it for the whole brush at once and cache it? */ + gimp_image_transform_color (dest, drawable, p, d, RGB); + d += bytes; + } + } +} diff --git a/app/tools/gimppainttool.h b/app/tools/gimppainttool.h new file mode 100644 index 0000000000..9b1fc62c81 --- /dev/null +++ b/app/tools/gimppainttool.h @@ -0,0 +1,219 @@ +/* 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 __GIMP_PAINT_TOOL_H__ +#define __GIMP_PAINT_TOOL_H__ + +#include "tools/gimpdrawtool.h" + +#define GIMP_TYPE_PAINT_TOOL (gimp_paint_tool_get_type ()) +#define GIMP_PAINT_TOOL(obj) (GTK_CHECK_CAST ((obj), GIMP_TYPE_PAINT_TOOL, GimpPaintTool)) +#define GIMP_IS_PAINT_TOOL(obj) (GTK_CHECK_TYPE ((obj), GIMP_TYPE_PAINT_TOOL)) +#define GIMP_PAINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PAINT_TOOL, GimpPaintToolClass)) +#define GIMP_IS_PAINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PAINT_TOOL)) + +GtkType gimp_paint_tool_get_type (void); + +/* the different states that the painting function can be called with */ + +typedef enum /*< skip >*/ +{ + INIT_PAINT, /* Setup PaintFunc internals */ + MOTION_PAINT, /* PaintFunc performs motion-related rendering */ + PAUSE_PAINT, /* Unused. Reserved */ + RESUME_PAINT, /* Unused. Reserved */ + FINISH_PAINT, /* Cleanup and/or reset PaintFunc operation */ + PRETRACE_PAINT, /* PaintFunc performs window tracing activity prior to rendering */ + POSTTRACE_PAINT /* PaintFunc performs window tracing activity following rendering */ +} PaintState; + +typedef enum /*< skip >*/ +{ + TOOL_CAN_HANDLE_CHANGING_BRUSH = 0x0001, /* Set for tools that don't mind + * if the brush changes while + * painting. + */ + + TOOL_TRACES_ON_WINDOW /* Set for tools that perform temporary + * rendering directly to the window. These + * require sequencing with gdisplay_flush() + * routines. See clone.c for example. + */ +} ToolFlags; + +typedef void (* PaintFunc) (GimpPaintTool *tool, + GimpDrawable *drawable, + PaintState paint_state); + +struct _GimpPaintTool +{ + GimpDrawTool parent_instance; + + gdouble startx; /* starting x coord */ + gdouble starty; /* starting y coord */ + gdouble startpressure; /* starting pressure */ + gdouble startxtilt; /* starting xtilt */ + gdouble startytilt; /* starting ytilt */ +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble startwheel; /* starting wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ + + gdouble curx; /* current x coord */ + gdouble cury; /* current y coord */ + gdouble curpressure; /* current pressure */ + gdouble curxtilt; /* current xtilt */ + gdouble curytilt; /* current ytilt */ +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble curwheel; /* current wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ + + gdouble lastx; /* last x coord */ + gdouble lasty; /* last y coord */ + gdouble lastpressure; /* last pressure */ + gdouble lastxtilt; /* last xtilt */ + gdouble lastytilt; /* last ytilt */ +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble lastwheel; /* last wheel */ +#endif /* GTK_HAVE_SIX_VALUATORS */ + + gint state; /* state of buttons and keys */ + + gdouble distance; /* distance traveled by brush */ + gdouble pixel_dist; /* distance in pixels */ + gdouble spacing; /* spacing */ + + gint x1, y1; /* image space coordinate */ + gint x2, y2; /* image space coords */ + + GimpBrush * brush; /* current brush */ + + gboolean pick_colors; /* pick color if ctrl or alt is pressed */ + gboolean pick_state; /* was ctrl or alt pressed when clicked? */ + ToolFlags flags; /* tool flags, see ToolFlags above */ + + guint context_id; /* for the statusbar */ +}; + +struct _GimpPaintToolClass +{ + GimpDrawToolClass parent_class; + + PaintFunc paint_func; /* painting function */ +}; + +typedef struct _GimpPaintToolClass GimpPaintToolClass; + + +/* this should change */ +extern GimpPaintTool *non_gui_paint_tool; +extern GimpPaintToolClass *non_gui_paint_tool_class; + +/* Special undo type */ +typedef struct _PaintUndo PaintUndo; + +struct _PaintUndo +{ + GimpPaintTool *tool; + + + gdouble lastx; + gdouble lasty; + gdouble lastpressure; + gdouble lastxtilt; + gdouble lastytilt; +#ifdef GTK_HAVE_SIX_VALUATORS + gdouble lastwheel; +#endif /* GTK_HAVE_SIX_VALUATORS */ +}; + +/* paint tool action functions */ +void gimp_paint_tool_button_press (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); +void gimp_paint_tool_button_release (GimpTool *tool, + GdkEventButton *bevent, + GDisplay *gdisp); +void gimp_paint_tool_motion (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); +void gimp_paint_tool_cursor_update (GimpTool *tool, + GdkEventMotion *mevent, + GDisplay *gdisp); + +void gimp_paint_tool_control (GimpTool *tool, + ToolAction action, + GDisplay *gdisp); + +void gimp_paint_tool_paint (GimpPaintTool *tool, + GimpDrawable *drawable, + PaintState state); + +/* paint tool functions */ +void gimp_paint_tool_no_draw (GimpPaintTool *tool); + +GimpPaintTool *gimp_paint_tool_new (void); +void gimp_paint_tool_destroy (GimpTool *tool); +int gimp_paint_tool_start (GimpPaintTool *tool, + GimpDrawable *drawable, + gdouble x, + gdouble y); +void gimp_paint_tool_interpolate (GimpPaintTool *tool, + GimpDrawable *drawable); +void gimp_paint_tool_finish (GimpPaintTool *tool, + GimpDrawable *drawable); +void gimp_paint_tool_cleanup (void); + +void gimp_paint_tool_get_color_from_gradient (GimpPaintTool *tool, + gdouble gradient_length, + GimpRGB *color, + GradientPaintMode mode); + +/* paint tool painting functions */ +TempBuf * gimp_paint_tool_get_paint_area (GimpPaintTool *tool, + GimpDrawable *drawable, + gdouble scale); +TempBuf * gimp_paint_tool_get_orig_image (GimpPaintTool *tool, + GimpDrawable *drawable, + gint x1, + gint y1, + gint x2, + gint y2); +void gimp_paint_tool_paste_canvas (GimpPaintTool *tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + LayerModeEffects paint_mode, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode); +void gimp_paint_tool_replace_canvas (GimpPaintTool *tool, + GimpDrawable *drawable, + gint brush_opacity, + gint image_opacity, + BrushApplicationMode brush_hardness, + gdouble brush_scale, + PaintApplicationMode mode); +void gimp_paint_tool_color_area_with_pixmap (GimpPaintTool *tool, + GimpImage *dest, + GimpDrawable *drawable, + TempBuf *area, + gdouble scale, + BrushApplicationMode mode); + + +#endif /* __GIMP_PAINT_TOOL_H__ */ diff --git a/app/tools/paint_core_kernels.h b/app/tools/gimppainttool_kernels.h similarity index 100% rename from app/tools/paint_core_kernels.h rename to app/tools/gimppainttool_kernels.h diff --git a/app/tools/gimptool.c b/app/tools/gimptool.c index edcd16b421..45bebbf0c8 100644 --- a/app/tools/gimptool.c +++ b/app/tools/gimptool.c @@ -466,6 +466,121 @@ gimp_tool_real_oper_update (GimpTool *tool, + +/* Function definitions */ + +/* Create a default tool object + */ + +GimpTool * +gimp_tool_new (void) +{ + GimpTool *tool; + + tool = gtk_type_new (GIMP_TYPE_TOOL); + + return tool; +} + + + + +void +gimp_tool_help_func (const gchar *help_data) +{ + gimp_standard_help_func (tool_manager_active_get_help_data()); +} + + +#define STUB(x) void * x (void){g_message ("stub function %s called",#x); return NULL;} + +#define QUIET_STUB(x) void * x (void){return NULL;} + +STUB(curves_free) +STUB(hue_saturation_free) +STUB(levels_free) +STUB(curves_calculate_curve) +STUB(curves_lut_func) +STUB(color_balance_create_lookup_tables) +STUB(color_balance) +STUB(hue_saturation_calculate_transfers) +STUB(hue_saturation) +STUB(threshold_2) +STUB(color_balance_dialog_hide) +STUB(hue_saturation_dialog_hide) +STUB(brightness_contrast_dialog_hide) +STUB(threshold_dialog_hide) +STUB(levels_dialog_hide) +STUB(curves_dialog_hide) +STUB(posterize_dialog_hide) +STUB(move_tool_start_hguide) +STUB(move_tool_start_vguide) +STUB(bucket_fill_region) +STUB(pathpoints_copy) +STUB(pathpoints_free) +STUB(bezier_stroke) +STUB(bezier_distance_along) +STUB(bezier_select_free) +STUB(paths_dialog_destroy_cb) +STUB(bezier_select_reset) +STUB(bezier_add_point) +STUB(path_set_path) +STUB(path_set_path_points) +STUB(path_delete_path) +STUB(by_color_select_initialize_by_image) +STUB(path_transform_start_undo) +STUB(path_transform_do_undo) +STUB(path_transform_free_undo) +STUB(undo_pop_paint) +STUB(histogram_tool_histogram_range) +STUB(paths_dialog_create) +STUB(paths_dialog_flush) +STUB(paths_dialog_update) +STUB(paths_dialog_new_path_callback) +STUB(paths_dialog_dup_path_callback) +STUB(paths_dialog_path_to_sel_callback) +STUB(paths_dialog_sel_to_path_callback) +STUB(paths_dialog_stroke_path_callback) +STUB(paths_dialog_delete_path_callback) +STUB(paths_dialog_copy_path_callback) +STUB(paths_dialog_paste_path_callback) +STUB(paths_dialog_import_path_callback) +STUB(paths_dialog_export_path_callback) +STUB(paths_dialog_edit_path_attributes_callback) +QUIET_STUB(GIMP_IS_FUZZY_SELECT) +STUB(crop_image) +STUB(dodgeburn_non_gui) +STUB(dodgeburn_non_gui_default) +STUB(ellipse_select) +STUB(eraser_non_gui) +STUB(eraser_non_gui_default) +STUB(transform_core_cut) +STUB(flip_tool_flip) +STUB(transform_core_paste) +STUB(free_select) +STUB(find_contiguous_region) +STUB(fuzzy_mask) +STUB(fuzzy_select) +STUB(pencil_non_gui) +STUB(perspective_find_transform) +STUB(perspective_tool_perspective) +STUB(rect_select) +STUB(rotate_tool_rotate) +STUB(scale_tool_scale) +STUB(shear_tool_shear) +STUB(smudge_non_gui) +STUB(smudge_non_gui_default) +STUB(transform_core_do) +STUB(airbrush_non_gui) +STUB(airbrush_non_gui_default) +STUB(blend) +STUB(bucket_fill) +STUB(by_color_select) +STUB(clone_non_gui) +STUB(clone_non_gui_default) +STUB(convolve_non_gui) +STUB(convolve_non_gui_default) + #warning obsolete crap #ifdef STONE_AGE ToolInfo tool_info[] = @@ -482,7 +597,7 @@ ToolInfo tool_info[] = "tools/rect_select.html", RECT_SELECT, tools_new_rect_select, - tools_free_rect_select, + tools_free_rect_select, NULL, NULL, NULL, @@ -527,8 +642,8 @@ ToolInfo tool_info[] = }, { - NULL, - N_("Free Select"), + NULL, + N_("Free Select"), N_("/Tools/Select Tools/Free Select"), "F", (char **) free_bits, @@ -538,7 +653,7 @@ ToolInfo tool_info[] = "tools/free_select.html", FREE_SELECT, tools_new_free_select, - tools_free_free_select, + tools_free_free_select, NULL, NULL, NULL, @@ -553,7 +668,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Fuzzy Select"), @@ -566,7 +681,7 @@ ToolInfo tool_info[] = "tools/fuzzy_select.html", FUZZY_SELECT, tools_new_fuzzy_select, - tools_free_fuzzy_select, + tools_free_fuzzy_select, NULL, NULL, NULL, @@ -581,7 +696,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Bezier Select"), @@ -609,7 +724,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Intelligent Scissors"), @@ -622,7 +737,7 @@ ToolInfo tool_info[] = "tools/intelligent_scissors.html", ISCISSORS, tools_new_iscissors, - tools_free_iscissors, + tools_free_iscissors, NULL, NULL, NULL, @@ -637,7 +752,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Move"), @@ -650,7 +765,7 @@ ToolInfo tool_info[] = "tools/move.html", MOVE, tools_new_move_tool, - tools_free_move_tool, + tools_free_move_tool, NULL, NULL, NULL, @@ -678,7 +793,7 @@ ToolInfo tool_info[] = "tools/magnify.html", MAGNIFY, tools_new_magnify, - tools_free_magnify, + tools_free_magnify, NULL, NULL, NULL, @@ -721,7 +836,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Transform"), @@ -749,7 +864,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* rotate */ - + { NULL, N_("Transform"), @@ -762,7 +877,7 @@ ToolInfo tool_info[] = "tools/transform.html", SCALE, tools_new_transform_tool, - tools_free_transform_tool, + tools_free_transform_tool, NULL, NULL, NULL, @@ -777,7 +892,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* scale */ - + { NULL, N_("Transform"), @@ -805,7 +920,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* shear */ - + { NULL, N_("Transform"), @@ -833,7 +948,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* perspective */ - + { NULL, N_("Flip"), @@ -861,7 +976,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Text"), @@ -889,8 +1004,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Bucket Fill"), N_("/Tools/Paint Tools/Bucket Fill"), @@ -918,7 +1033,7 @@ ToolInfo tool_info[] = } }, - { + { NULL, N_("Blend"), N_("/Tools/Paint Tools/Blend"), @@ -945,7 +1060,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Pencil"), @@ -973,36 +1088,9 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + + { - NULL, - N_("Paintbrush"), - N_("/Tools/Paint Tools/Paintbrush"), - "P", - (char **) paint_bits, - NULL, - NULL, - N_("Paint fuzzy brush strokes"), - "tools/paintbrush.html", - PAINTBRUSH, - tools_new_paintbrush, - tools_free_paintbrush, - NULL, - NULL, - NULL, - { - paintbrush_small_bits, paintbrush_small_mask_bits, - paintbrush_small_width, paintbrush_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { NULL, N_("Airbrush"), N_("/Tools/Paint Tools/Airbrush"), @@ -1029,7 +1117,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Ink"), @@ -1058,7 +1146,7 @@ ToolInfo tool_info[] = } }, - { + { NULL, N_("Clone"), N_("/Tools/Paint Tools/Clone"), @@ -1085,8 +1173,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Eraser"), N_("/Tools/Paint Tools/Eraser"), @@ -1141,8 +1229,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Convolve"), N_("/Tools/Paint Tools/Convolve"), @@ -1225,7 +1313,7 @@ ToolInfo tool_info[] = 0, 0, 0, 0, NULL, NULL, NULL } - }, + }, */ { @@ -1240,7 +1328,7 @@ ToolInfo tool_info[] = "tools/measure.html", MEASURE, tools_new_measure_tool, - tools_free_measure_tool, + tools_free_measure_tool, NULL, NULL, NULL, @@ -1269,7 +1357,7 @@ ToolInfo tool_info[] = "tools/path.html", PATH_TOOL, tools_new_path_tool, - tools_free_path_tool, + tools_free_path_tool, NULL, NULL, NULL, @@ -1287,7 +1375,7 @@ ToolInfo tool_info[] = */ /* Non-toolbox tools */ - { + { NULL, N_("By Color Select"), N_("/Select/By Color..."), @@ -1314,8 +1402,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Color Balance"), N_("/Image/Colors/Color Balance..."), @@ -1342,8 +1430,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Brightness-Contrast"), N_("/Image/Colors/Brightness-Contrast..."), @@ -1370,8 +1458,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Hue-Saturation"), N_("/Image/Colors/Hue-Saturation..."), @@ -1383,7 +1471,7 @@ ToolInfo tool_info[] = "tools/hue_saturation.html", HUE_SATURATION, tools_new_hue_saturation, - tools_free_hue_saturation, + tools_free_hue_saturation, hue_saturation_initialize, NULL, NULL, @@ -1399,7 +1487,7 @@ ToolInfo tool_info[] = } }, - { + { NULL, N_("Posterize"), N_("/Image/Colors/Posterize..."), @@ -1426,10 +1514,10 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, - N_("Threshold"), + N_("Threshold"), N_("/Image/Colors/Threshold..."), NULL, (char **) levels_bits, @@ -1454,8 +1542,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Curves"), N_("/Image/Colors/Curves..."), @@ -1466,7 +1554,7 @@ ToolInfo tool_info[] = N_("Adjust color curves"), "tools/curves.html", CURVES, - tools_new_curves, + tools_new_curves, tools_free_curves, curves_initialize, NULL, @@ -1482,8 +1570,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Levels"), N_("/Image/Colors/Levels..."), @@ -1494,7 +1582,7 @@ ToolInfo tool_info[] = N_("Adjust color levels"), "tools/levels.html", LEVELS, - tools_new_levels, + tools_new_levels, tools_free_levels, levels_initialize, NULL, @@ -1510,8 +1598,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Histogram"), N_("/Image/Histogram..."), @@ -1543,97 +1631,3 @@ ToolInfo tool_info[] = gint num_tools = sizeof (tool_info) / sizeof (tool_info[0]); #endif - - -#define STUB(x) void * x (void){g_message ("stub function %s called",#x); return NULL;} - -#define QUIET_STUB(x) void * x (void){return NULL;} - -STUB(curves_free) -STUB(hue_saturation_free) -STUB(levels_free) -STUB(curves_calculate_curve) -STUB(curves_lut_func) -STUB(color_balance_create_lookup_tables) -STUB(color_balance) -STUB(hue_saturation_calculate_transfers) -STUB(hue_saturation) -STUB(threshold_2) -STUB(color_balance_dialog_hide) -STUB(hue_saturation_dialog_hide) -STUB(brightness_contrast_dialog_hide) -STUB(threshold_dialog_hide) -STUB(levels_dialog_hide) -STUB(curves_dialog_hide) -STUB(posterize_dialog_hide) -STUB(move_tool_start_hguide) -STUB(move_tool_start_vguide) -STUB(bucket_fill_region) -STUB(pathpoints_copy) -STUB(pathpoints_free) -STUB(bezier_stroke) -STUB(bezier_distance_along) -STUB(bezier_select_free) -STUB(paths_dialog_destroy_cb) -STUB(bezier_select_reset) -STUB(bezier_add_point) -STUB(path_set_path) -STUB(path_set_path_points) -STUB(path_delete_path) -STUB(by_color_select_initialize_by_image) -STUB(path_transform_start_undo) -STUB(path_transform_do_undo) -STUB(path_transform_free_undo) -STUB(undo_pop_paint) -STUB(histogram_tool_histogram_range) -STUB(paths_dialog_create) -STUB(paths_dialog_flush) -STUB(paths_dialog_update) -STUB(paths_dialog_new_path_callback) -STUB(paths_dialog_dup_path_callback) -STUB(paths_dialog_path_to_sel_callback) -STUB(paths_dialog_sel_to_path_callback) -STUB(paths_dialog_stroke_path_callback) -STUB(paths_dialog_delete_path_callback) -STUB(paths_dialog_copy_path_callback) -STUB(paths_dialog_paste_path_callback) -STUB(paths_dialog_import_path_callback) -STUB(paths_dialog_export_path_callback) -STUB(paths_dialog_edit_path_attributes_callback) -STUB(tools_register) -QUIET_STUB(GIMP_IS_FUZZY_SELECT) -QUIET_STUB(GIMP_IS_MOVE_TOOL) -STUB(crop_image) -STUB(dodgeburn_non_gui) -STUB(dodgeburn_non_gui_default) -STUB(ellipse_select) -STUB(eraser_non_gui) -STUB(eraser_non_gui_default) -STUB(transform_core_cut) -STUB(flip_tool_flip) -STUB(transform_core_paste) -STUB(free_select) -STUB(find_contiguous_region) -STUB(fuzzy_mask) -STUB(fuzzy_select) -STUB(paintbrush_non_gui) -STUB(paintbrush_non_gui_default) -STUB(pencil_non_gui) -STUB(perspective_find_transform) -STUB(perspective_tool_perspective) -STUB(rect_select) -STUB(rotate_tool_rotate) -STUB(scale_tool_scale) -STUB(shear_tool_shear) -STUB(smudge_non_gui) -STUB(smudge_non_gui_default) -STUB(transform_core_do) -STUB(airbrush_non_gui) -STUB(airbrush_non_gui_default) -STUB(blend) -STUB(bucket_fill) -STUB(by_color_select) -STUB(clone_non_gui) -STUB(clone_non_gui_default) -STUB(convolve_non_gui) -STUB(convolve_non_gui_default) diff --git a/app/tools/gimptool.h b/app/tools/gimptool.h index 87c02d39a0..b76acd9fce 100644 --- a/app/tools/gimptool.h +++ b/app/tools/gimptool.h @@ -30,7 +30,6 @@ #define GIMP_TYPE_BY_COLOR_SELECT_TOOL GTK_TYPE_NONE #define GIMP_TYPE_BUCKET_FILL_TOOL GTK_TYPE_NONE #define GIMP_TYPE_BLEND_TOOL GTK_TYPE_NONE -#define GIMP_TYPE_PAINTBRUSH_TOOL GTK_TYPE_NONE #define GIMP_TYPE_PENCIL_TOOL GTK_TYPE_NONE #define GIMP_TYPE_ERASER_TOOL GTK_TYPE_NONE #define GIMP_TYPE_AIRBRUSH_TOOL GTK_TYPE_NONE @@ -79,7 +78,6 @@ struct _GimpTool gboolean toggled; /* Bad hack to let the paint_core show the * right toggle cursors */ - PaintCore *paintcore; }; struct _GimpToolClass @@ -118,10 +116,6 @@ struct _GimpToolClass GdkEventMotion *mevent, GDisplay *gdisp); }; - - -/* Function declarations */ - GtkType gimp_tool_get_type (void); void gimp_tool_initialize (GimpTool *tool, @@ -150,7 +144,6 @@ void gimp_tool_cursor_update (GimpTool *tool, void gimp_tool_oper_update (GimpTool *tool, GdkEventMotion *mevent, GDisplay *gdisp); - const gchar * gimp_tool_get_PDB_string (GimpTool *tool); diff --git a/app/tools/gimptoolinfo.c b/app/tools/gimptoolinfo.c index 9dc0122533..2af323300e 100644 --- a/app/tools/gimptoolinfo.c +++ b/app/tools/gimptoolinfo.c @@ -26,7 +26,7 @@ #include "temp_buf.h" /* FIXME: include rect_select.h here */ -#include "color_picker.h" +#include "gimpcolorpickertool.h" static void gimp_tool_info_class_init (GimpToolInfoClass *klass); @@ -236,7 +236,7 @@ gimp_tool_info_get_standard (void) if (! standard_tool_info) { standard_tool_info = - gimp_tool_info_new (GIMP_TYPE_COLOR_PICKER, + gimp_tool_info_new (GIMP_TYPE_COLOR_PICKER_TOOL, "gimp:standard_tool", "Standard Tool", "Well something must be broken", diff --git a/app/tools/measure.c b/app/tools/measure.c index 41914d477d..f48654eabf 100644 --- a/app/tools/measure.c +++ b/app/tools/measure.c @@ -31,7 +31,6 @@ #include "apptypes.h" #include "cursorutil.h" -#include "draw_core.h" #include "gdisplay.h" #include "gimpimage.h" #include "info_dialog.h" @@ -42,6 +41,8 @@ #include "tool_manager.h" #include "tool_options.h" +#include "tools/gimpdrawingtool.h" + #include "libgimp/gimpintl.h" #include "pixmaps2.h" @@ -143,7 +144,7 @@ gimp_measure_tool_get_type (void) (GtkClassInitFunc) NULL, }; - tool_type = gtk_type_unique (GIMP_TYPE_TOOL, &tool_info); + tool_type = gtk_type_unique (GIMP_TYPE_DRAW_TOOL, &tool_info); } return tool_type; @@ -185,24 +186,20 @@ gimp_measure_tool_init (GimpMeasureTool *measure_tool) (ToolOptions *) measure_tool_options); } - measure_tool->core = draw_core_new (measure_tool_draw); - tool->preserve = TRUE; /* Preserve on drawable change */ } static void gimp_measure_tool_destroy (GtkObject *object) { - GimpMeasureTool *measure_tool; + GimpDrawTool *draw_tool; GimpTool *tool; - measure_tool = GIMP_MEASURE_TOOL (object); + draw_tool = GIMP_DRAW_TOOL (object); tool = GIMP_TOOL (object); if (tool->state == ACTIVE) - draw_core_stop (measure_tool->core, tool); - - draw_core_free (measure_tool->core); + gimp_draw_tool_stop (draw_tool); if (GTK_OBJECT_CLASS (parent_class)->destroy) GTK_OBJECT_CLASS (parent_class)->destroy (object); @@ -388,7 +385,7 @@ measure_tool_button_press (GimpTool *tool, if (tool->state == ACTIVE) { /* reset everything */ - draw_core_stop (measure_tool->core, tool); + gimp_draw_tool_stop (GIMP_DRAW_TOOL(measure_tool)); gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), measure_tool->context_id); @@ -403,13 +400,13 @@ measure_tool_button_press (GimpTool *tool, else { /* initialize the statusbar display */ - measure_tool->context_id = + measure_tool->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "measure"); } - + /* set the first point and go into ADDING mode */ - gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, + gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &measure_tool->x[0], &measure_tool->y[0], TRUE, FALSE); measure_tool->point = 0; @@ -420,7 +417,7 @@ measure_tool_button_press (GimpTool *tool, tool->gdisp = gdisp; /* start drawing the measure tool */ - draw_core_start (measure_tool->core, gdisp->canvas->window, tool); + gimp_draw_tool_start (GIMP_DRAW_TOOL(measure_tool), gdisp->canvas->window); } /* create the info window if necessary */ @@ -441,14 +438,14 @@ measure_tool_button_press (GimpTool *tool, NULL); } - + gdk_pointer_grab (gdisp->canvas->window, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, bevent->time); tool->state = ACTIVE; - + /* set the pointer to the crosshair, * so one actually sees the cursor position */ @@ -466,7 +463,7 @@ measure_tool_button_release (GimpTool *tool, GimpMeasureTool *measure_tool; measure_tool = GIMP_MEASURE_TOOL (tool); - + measure_tool->function = FINISHED; gdk_pointer_ungrab (bevent->time); @@ -492,15 +489,15 @@ measure_tool_motion (GimpTool *tool, measure_tool = GIMP_MEASURE_TOOL (tool); /* undraw the current tool */ - draw_core_pause (measure_tool->core, tool); + gimp_draw_tool_pause (GIMP_DRAW_TOOL(measure_tool)); /* get the coordinates */ gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, FALSE); - /* + /* * A few comments here, because this routine looks quite weird at first ... * - * The goal is to keep point 0, called the start point, to be always the one + * The goal is to keep point 0, called the start point, to be always the one * in the middle or, if there are only two points, the one that is fixed. * The angle is then always measured at this point. */ @@ -510,7 +507,7 @@ measure_tool_motion (GimpTool *tool, case ADDING: switch (measure_tool->point) { - case 0: /* we are adding to the start point */ + case 0: /* we are adding to the start point */ break; case 1: /* we are adding to the end point, make it the new start point */ tmp = measure_tool->x[0]; @@ -533,8 +530,8 @@ measure_tool_motion (GimpTool *tool, measure_tool->point = measure_tool->num_points - 1; measure_tool->function = MOVING; /* no, don't break here! */ - - case MOVING: + + case MOVING: /* if we are moving the start point and only have two, make it the end point */ if (measure_tool->num_points == 2 && measure_tool->point == 0) { @@ -558,10 +555,10 @@ measure_tool_motion (GimpTool *tool, { dx = measure_tool->x[i] - measure_tool->x[0]; dy = measure_tool->y[i] - measure_tool->y[0]; - - measure_tool->x[i] = measure_tool->x[0] + + + measure_tool->x[i] = measure_tool->x[0] + (dx > 0 ? MAX (abs (dx), abs (dy)) : - MAX (abs (dx), abs (dy))); - measure_tool->y[i] = measure_tool->y[0] + + measure_tool->y[i] = measure_tool->y[0] + (dy > 0 ? MAX (abs (dx), abs (dy)) : - MAX (abs (dx), abs (dy))); } else @@ -592,7 +589,7 @@ measure_tool_motion (GimpTool *tool, /* calculate distance and angle */ ax = measure_tool->x[1] - measure_tool->x[0]; ay = measure_tool->y[1] - measure_tool->y[0]; - + if (measure_tool->num_points == 3) { bx = measure_tool->x[2] - measure_tool->x[0]; @@ -603,23 +600,23 @@ measure_tool_motion (GimpTool *tool, bx = 0; by = 0; } - + if (gdisp->dot_for_dot) { distance = sqrt (SQR (ax - bx) + SQR (ay - by)); - + if (measure_tool->num_points != 3) bx = ax > 0 ? 1 : -1; - + measure_tool->angle1 = measure_get_angle (ax, ay, 1.0, 1.0); measure_tool->angle2 = measure_get_angle (bx, by, 1.0, 1.0); angle = fabs (measure_tool->angle1 - measure_tool->angle2); if (angle > 180.0) angle = fabs (360.0 - angle); - + g_snprintf (status_str, STATUSBAR_SIZE, "%.1f %s, %.2f %s", distance, _("pixels"), angle, _("degrees")); - + if (measure_tool_options) { g_snprintf (distance_buf, MAX_INFO_BUF, "%.1f %s", distance, _("pixels")); @@ -634,20 +631,20 @@ measure_tool_motion (GimpTool *tool, gimp_unit_get_symbol (gdisp->gimage->unit), _("degrees")); - distance = gimp_unit_get_factor (gdisp->gimage->unit) * + distance = gimp_unit_get_factor (gdisp->gimage->unit) * sqrt (SQR ((gdouble)(ax - bx) / gdisp->gimage->xresolution) + SQR ((gdouble)(ay - by) / gdisp->gimage->yresolution)); if (measure_tool->num_points != 3) bx = ax > 0 ? 1 : -1; - measure_tool->angle1 = measure_get_angle (ax, ay, - gdisp->gimage->xresolution, - gdisp->gimage->yresolution); - measure_tool->angle2 = measure_get_angle (bx, by, - gdisp->gimage->xresolution, + measure_tool->angle1 = measure_get_angle (ax, ay, + gdisp->gimage->xresolution, gdisp->gimage->yresolution); - angle = fabs (measure_tool->angle1 - measure_tool->angle2); + measure_tool->angle2 = measure_get_angle (bx, by, + gdisp->gimage->xresolution, + gdisp->gimage->yresolution); + angle = fabs (measure_tool->angle1 - measure_tool->angle2); if (angle > 180.0) angle = fabs (360.0 - angle); @@ -680,7 +677,7 @@ measure_tool_motion (GimpTool *tool, } /* measure_tool->function == MOVING */ /* redraw the current tool */ - draw_core_resume (measure_tool->core, tool); + gimp_draw_tool_resume (GIMP_DRAW_TOOL(measure_tool)); } static void @@ -703,9 +700,9 @@ measure_tool_cursor_update (GimpTool *tool, { for (i = 0; i < measure_tool->num_points; i++) { - gdisplay_transform_coords (gdisp, measure_tool->x[i], measure_tool->y[i], - &x[i], &y[i], FALSE); - + gdisplay_transform_coords (gdisp, measure_tool->x[i], measure_tool->y[i], + &x[i], &y[i], FALSE); + if (mevent->x == CLAMP (mevent->x, x[i] - TARGET, x[i] + TARGET) && mevent->y == CLAMP (mevent->y, y[i] - TARGET, y[i] + TARGET)) { @@ -752,6 +749,7 @@ static void measure_tool_draw (GimpTool *tool) { GimpMeasureTool *measure_tool; + GimpDrawTool *draw_tool; gint x[3]; gint y[3]; gint i; @@ -767,22 +765,22 @@ measure_tool_draw (GimpTool *tool) &x[i], &y[i], FALSE); if (i == 0 && measure_tool->num_points == 3) { - gdk_draw_arc (measure_tool->core->win, measure_tool->core->gc, FALSE, + gdk_draw_arc (draw_tool->win, draw_tool->gc, FALSE, x[i] - (TARGET >> 1), y[i] - (TARGET >> 1), TARGET, TARGET, 0, 23040); } else { - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[i] - TARGET, y[i], + gdk_draw_line (draw_tool->win, draw_tool->gc, + x[i] - TARGET, y[i], x[i] + TARGET, y[i]); - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, - x[i], y[i] - TARGET, + gdk_draw_line (draw_tool->win, draw_tool->gc, + x[i], y[i] - TARGET, x[i], y[i] + TARGET); } if (i > 0) { - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, + gdk_draw_line (draw_tool->win, draw_tool->gc, x[0], y[0], x[i], y[i]); /* only draw the arc if the lines are long enough */ @@ -790,29 +788,29 @@ measure_tool_draw (GimpTool *tool) draw_arc++; } } - + if (measure_tool->num_points > 1 && draw_arc == measure_tool->num_points - 1) { angle1 = measure_tool->angle2 * 64.0; angle2 = (measure_tool->angle1 - measure_tool->angle2) * 64.0; - + if (angle2 > 11520) angle2 -= 23040; if (angle2 < -11520) angle2 += 23040; - + if (angle2 != 0) { - gdk_draw_arc (measure_tool->core->win, measure_tool->core->gc, FALSE, + gdk_draw_arc (draw_tool->win, draw_tool->gc, FALSE, x[0] - ARC_RADIUS, y[0] - ARC_RADIUS, - 2 * ARC_RADIUS, 2 * ARC_RADIUS, - angle1, angle2); + 2 * ARC_RADIUS, 2 * ARC_RADIUS, + angle1, angle2); if (measure_tool->num_points == 2) - gdk_draw_line (measure_tool->core->win, measure_tool->core->gc, + gdk_draw_line (draw_tool->win, draw_tool->gc, x[0], y[0], - x[1] - x[0] <= 0 ? x[0] - ARC_RADIUS - (TARGET >> 1) : - x[0] + ARC_RADIUS + (TARGET >> 1), + x[1] - x[0] <= 0 ? x[0] - ARC_RADIUS - (TARGET >> 1) : + x[0] + ARC_RADIUS + (TARGET >> 1), y[0]); } } @@ -823,24 +821,24 @@ measure_tool_control (GimpTool *tool, ToolAction action, GDisplay *gdisp) { - GimpMeasureTool *measure_tool; + GimpDrawTool *draw_tool; - measure_tool = GIMP_MEASURE_TOOL (tool); + draw_tool = GIMP_DRAW_TOOL (tool); switch (action) { case PAUSE: - draw_core_pause (measure_tool->core, tool); + gimp_draw_tool_pause (draw_tool); break; case RESUME: - draw_core_resume (measure_tool->core, tool); + gimp_draw_tool_resume (draw_tool); break; case HALT: gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), measure_tool->context_id); - draw_core_stop (measure_tool->core, tool); + gimp_draw_tool_stop (draw_tool); tool->state = INACTIVE; break; diff --git a/app/tools/measure.h b/app/tools/measure.h index de3e48abd0..6212003ea9 100644 --- a/app/tools/measure.h +++ b/app/tools/measure.h @@ -46,9 +46,7 @@ typedef struct _GimpMeasureToolClass GimpMeasureToolClass; struct _GimpMeasureTool { - GimpTool parent_instance; - - DrawCore *core; /* Core select object */ + GimpDrawTool parent_instance; /* Core select object */ MeasureFunction function; /* function we're performing */ gint last_x; /* last x coordinate */ diff --git a/app/tools/move.c b/app/tools/move.c index c26f2ba1bc..292540477c 100644 --- a/app/tools/move.c +++ b/app/tools/move.c @@ -25,7 +25,6 @@ #include "apptypes.h" #include "cursorutil.h" -#include "draw_core.h" #include "floating_sel.h" #include "gdisplay.h" #include "gdisplay_ops.h" diff --git a/app/tools/paint_options.c b/app/tools/paint_options.c index 55a2daf85e..ab84b9d869 100644 --- a/app/tools/paint_options.c +++ b/app/tools/paint_options.c @@ -33,6 +33,8 @@ #include "tool.h" #include "tool_manager.h" +#include "gimppaintbrushtool.h" + #include "libgimp/gimpintl.h" diff --git a/app/tools/paintbrush.h b/app/tools/paintbrush.h deleted file mode 100644 index 4ce8b274a9..0000000000 --- a/app/tools/paintbrush.h +++ /dev/null @@ -1,37 +0,0 @@ -/* The GIMP -- an image manipulation program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __PAINTBRUSH_H__ -#define __PAINTBRUSH_H__ - - -gboolean paintbrush_non_gui (GimpDrawable *, - gint , - gdouble *, - gdouble , - gint , - gdouble ); -gboolean paintbrush_non_gui_default (GimpDrawable *, - gint , - gdouble *); - -Tool * tools_new_paintbrush (void); -void tools_free_paintbrush (Tool *tool); - - -#endif /* __PAINTBRUSH_H__ */ diff --git a/app/tools/tool.c b/app/tools/tool.c index edcd16b421..45bebbf0c8 100644 --- a/app/tools/tool.c +++ b/app/tools/tool.c @@ -466,6 +466,121 @@ gimp_tool_real_oper_update (GimpTool *tool, + +/* Function definitions */ + +/* Create a default tool object + */ + +GimpTool * +gimp_tool_new (void) +{ + GimpTool *tool; + + tool = gtk_type_new (GIMP_TYPE_TOOL); + + return tool; +} + + + + +void +gimp_tool_help_func (const gchar *help_data) +{ + gimp_standard_help_func (tool_manager_active_get_help_data()); +} + + +#define STUB(x) void * x (void){g_message ("stub function %s called",#x); return NULL;} + +#define QUIET_STUB(x) void * x (void){return NULL;} + +STUB(curves_free) +STUB(hue_saturation_free) +STUB(levels_free) +STUB(curves_calculate_curve) +STUB(curves_lut_func) +STUB(color_balance_create_lookup_tables) +STUB(color_balance) +STUB(hue_saturation_calculate_transfers) +STUB(hue_saturation) +STUB(threshold_2) +STUB(color_balance_dialog_hide) +STUB(hue_saturation_dialog_hide) +STUB(brightness_contrast_dialog_hide) +STUB(threshold_dialog_hide) +STUB(levels_dialog_hide) +STUB(curves_dialog_hide) +STUB(posterize_dialog_hide) +STUB(move_tool_start_hguide) +STUB(move_tool_start_vguide) +STUB(bucket_fill_region) +STUB(pathpoints_copy) +STUB(pathpoints_free) +STUB(bezier_stroke) +STUB(bezier_distance_along) +STUB(bezier_select_free) +STUB(paths_dialog_destroy_cb) +STUB(bezier_select_reset) +STUB(bezier_add_point) +STUB(path_set_path) +STUB(path_set_path_points) +STUB(path_delete_path) +STUB(by_color_select_initialize_by_image) +STUB(path_transform_start_undo) +STUB(path_transform_do_undo) +STUB(path_transform_free_undo) +STUB(undo_pop_paint) +STUB(histogram_tool_histogram_range) +STUB(paths_dialog_create) +STUB(paths_dialog_flush) +STUB(paths_dialog_update) +STUB(paths_dialog_new_path_callback) +STUB(paths_dialog_dup_path_callback) +STUB(paths_dialog_path_to_sel_callback) +STUB(paths_dialog_sel_to_path_callback) +STUB(paths_dialog_stroke_path_callback) +STUB(paths_dialog_delete_path_callback) +STUB(paths_dialog_copy_path_callback) +STUB(paths_dialog_paste_path_callback) +STUB(paths_dialog_import_path_callback) +STUB(paths_dialog_export_path_callback) +STUB(paths_dialog_edit_path_attributes_callback) +QUIET_STUB(GIMP_IS_FUZZY_SELECT) +STUB(crop_image) +STUB(dodgeburn_non_gui) +STUB(dodgeburn_non_gui_default) +STUB(ellipse_select) +STUB(eraser_non_gui) +STUB(eraser_non_gui_default) +STUB(transform_core_cut) +STUB(flip_tool_flip) +STUB(transform_core_paste) +STUB(free_select) +STUB(find_contiguous_region) +STUB(fuzzy_mask) +STUB(fuzzy_select) +STUB(pencil_non_gui) +STUB(perspective_find_transform) +STUB(perspective_tool_perspective) +STUB(rect_select) +STUB(rotate_tool_rotate) +STUB(scale_tool_scale) +STUB(shear_tool_shear) +STUB(smudge_non_gui) +STUB(smudge_non_gui_default) +STUB(transform_core_do) +STUB(airbrush_non_gui) +STUB(airbrush_non_gui_default) +STUB(blend) +STUB(bucket_fill) +STUB(by_color_select) +STUB(clone_non_gui) +STUB(clone_non_gui_default) +STUB(convolve_non_gui) +STUB(convolve_non_gui_default) + #warning obsolete crap #ifdef STONE_AGE ToolInfo tool_info[] = @@ -482,7 +597,7 @@ ToolInfo tool_info[] = "tools/rect_select.html", RECT_SELECT, tools_new_rect_select, - tools_free_rect_select, + tools_free_rect_select, NULL, NULL, NULL, @@ -527,8 +642,8 @@ ToolInfo tool_info[] = }, { - NULL, - N_("Free Select"), + NULL, + N_("Free Select"), N_("/Tools/Select Tools/Free Select"), "F", (char **) free_bits, @@ -538,7 +653,7 @@ ToolInfo tool_info[] = "tools/free_select.html", FREE_SELECT, tools_new_free_select, - tools_free_free_select, + tools_free_free_select, NULL, NULL, NULL, @@ -553,7 +668,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Fuzzy Select"), @@ -566,7 +681,7 @@ ToolInfo tool_info[] = "tools/fuzzy_select.html", FUZZY_SELECT, tools_new_fuzzy_select, - tools_free_fuzzy_select, + tools_free_fuzzy_select, NULL, NULL, NULL, @@ -581,7 +696,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Bezier Select"), @@ -609,7 +724,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Intelligent Scissors"), @@ -622,7 +737,7 @@ ToolInfo tool_info[] = "tools/intelligent_scissors.html", ISCISSORS, tools_new_iscissors, - tools_free_iscissors, + tools_free_iscissors, NULL, NULL, NULL, @@ -637,7 +752,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Move"), @@ -650,7 +765,7 @@ ToolInfo tool_info[] = "tools/move.html", MOVE, tools_new_move_tool, - tools_free_move_tool, + tools_free_move_tool, NULL, NULL, NULL, @@ -678,7 +793,7 @@ ToolInfo tool_info[] = "tools/magnify.html", MAGNIFY, tools_new_magnify, - tools_free_magnify, + tools_free_magnify, NULL, NULL, NULL, @@ -721,7 +836,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Transform"), @@ -749,7 +864,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* rotate */ - + { NULL, N_("Transform"), @@ -762,7 +877,7 @@ ToolInfo tool_info[] = "tools/transform.html", SCALE, tools_new_transform_tool, - tools_free_transform_tool, + tools_free_transform_tool, NULL, NULL, NULL, @@ -777,7 +892,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* scale */ - + { NULL, N_("Transform"), @@ -805,7 +920,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* shear */ - + { NULL, N_("Transform"), @@ -833,7 +948,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, /* perspective */ - + { NULL, N_("Flip"), @@ -861,7 +976,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Text"), @@ -889,8 +1004,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Bucket Fill"), N_("/Tools/Paint Tools/Bucket Fill"), @@ -918,7 +1033,7 @@ ToolInfo tool_info[] = } }, - { + { NULL, N_("Blend"), N_("/Tools/Paint Tools/Blend"), @@ -945,7 +1060,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Pencil"), @@ -973,36 +1088,9 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + + { - NULL, - N_("Paintbrush"), - N_("/Tools/Paint Tools/Paintbrush"), - "P", - (char **) paint_bits, - NULL, - NULL, - N_("Paint fuzzy brush strokes"), - "tools/paintbrush.html", - PAINTBRUSH, - tools_new_paintbrush, - tools_free_paintbrush, - NULL, - NULL, - NULL, - { - paintbrush_small_bits, paintbrush_small_mask_bits, - paintbrush_small_width, paintbrush_small_height, - 0, 0, NULL, NULL, NULL - }, - { - NULL, NULL, - 0, 0, - 0, 0, NULL, NULL, NULL - } - }, - - { NULL, N_("Airbrush"), N_("/Tools/Paint Tools/Airbrush"), @@ -1029,7 +1117,7 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - + { NULL, N_("Ink"), @@ -1058,7 +1146,7 @@ ToolInfo tool_info[] = } }, - { + { NULL, N_("Clone"), N_("/Tools/Paint Tools/Clone"), @@ -1085,8 +1173,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Eraser"), N_("/Tools/Paint Tools/Eraser"), @@ -1141,8 +1229,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Convolve"), N_("/Tools/Paint Tools/Convolve"), @@ -1225,7 +1313,7 @@ ToolInfo tool_info[] = 0, 0, 0, 0, NULL, NULL, NULL } - }, + }, */ { @@ -1240,7 +1328,7 @@ ToolInfo tool_info[] = "tools/measure.html", MEASURE, tools_new_measure_tool, - tools_free_measure_tool, + tools_free_measure_tool, NULL, NULL, NULL, @@ -1269,7 +1357,7 @@ ToolInfo tool_info[] = "tools/path.html", PATH_TOOL, tools_new_path_tool, - tools_free_path_tool, + tools_free_path_tool, NULL, NULL, NULL, @@ -1287,7 +1375,7 @@ ToolInfo tool_info[] = */ /* Non-toolbox tools */ - { + { NULL, N_("By Color Select"), N_("/Select/By Color..."), @@ -1314,8 +1402,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Color Balance"), N_("/Image/Colors/Color Balance..."), @@ -1342,8 +1430,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Brightness-Contrast"), N_("/Image/Colors/Brightness-Contrast..."), @@ -1370,8 +1458,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Hue-Saturation"), N_("/Image/Colors/Hue-Saturation..."), @@ -1383,7 +1471,7 @@ ToolInfo tool_info[] = "tools/hue_saturation.html", HUE_SATURATION, tools_new_hue_saturation, - tools_free_hue_saturation, + tools_free_hue_saturation, hue_saturation_initialize, NULL, NULL, @@ -1399,7 +1487,7 @@ ToolInfo tool_info[] = } }, - { + { NULL, N_("Posterize"), N_("/Image/Colors/Posterize..."), @@ -1426,10 +1514,10 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, - N_("Threshold"), + N_("Threshold"), N_("/Image/Colors/Threshold..."), NULL, (char **) levels_bits, @@ -1454,8 +1542,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Curves"), N_("/Image/Colors/Curves..."), @@ -1466,7 +1554,7 @@ ToolInfo tool_info[] = N_("Adjust color curves"), "tools/curves.html", CURVES, - tools_new_curves, + tools_new_curves, tools_free_curves, curves_initialize, NULL, @@ -1482,8 +1570,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Levels"), N_("/Image/Colors/Levels..."), @@ -1494,7 +1582,7 @@ ToolInfo tool_info[] = N_("Adjust color levels"), "tools/levels.html", LEVELS, - tools_new_levels, + tools_new_levels, tools_free_levels, levels_initialize, NULL, @@ -1510,8 +1598,8 @@ ToolInfo tool_info[] = 0, 0, NULL, NULL, NULL } }, - - { + + { NULL, N_("Histogram"), N_("/Image/Histogram..."), @@ -1543,97 +1631,3 @@ ToolInfo tool_info[] = gint num_tools = sizeof (tool_info) / sizeof (tool_info[0]); #endif - - -#define STUB(x) void * x (void){g_message ("stub function %s called",#x); return NULL;} - -#define QUIET_STUB(x) void * x (void){return NULL;} - -STUB(curves_free) -STUB(hue_saturation_free) -STUB(levels_free) -STUB(curves_calculate_curve) -STUB(curves_lut_func) -STUB(color_balance_create_lookup_tables) -STUB(color_balance) -STUB(hue_saturation_calculate_transfers) -STUB(hue_saturation) -STUB(threshold_2) -STUB(color_balance_dialog_hide) -STUB(hue_saturation_dialog_hide) -STUB(brightness_contrast_dialog_hide) -STUB(threshold_dialog_hide) -STUB(levels_dialog_hide) -STUB(curves_dialog_hide) -STUB(posterize_dialog_hide) -STUB(move_tool_start_hguide) -STUB(move_tool_start_vguide) -STUB(bucket_fill_region) -STUB(pathpoints_copy) -STUB(pathpoints_free) -STUB(bezier_stroke) -STUB(bezier_distance_along) -STUB(bezier_select_free) -STUB(paths_dialog_destroy_cb) -STUB(bezier_select_reset) -STUB(bezier_add_point) -STUB(path_set_path) -STUB(path_set_path_points) -STUB(path_delete_path) -STUB(by_color_select_initialize_by_image) -STUB(path_transform_start_undo) -STUB(path_transform_do_undo) -STUB(path_transform_free_undo) -STUB(undo_pop_paint) -STUB(histogram_tool_histogram_range) -STUB(paths_dialog_create) -STUB(paths_dialog_flush) -STUB(paths_dialog_update) -STUB(paths_dialog_new_path_callback) -STUB(paths_dialog_dup_path_callback) -STUB(paths_dialog_path_to_sel_callback) -STUB(paths_dialog_sel_to_path_callback) -STUB(paths_dialog_stroke_path_callback) -STUB(paths_dialog_delete_path_callback) -STUB(paths_dialog_copy_path_callback) -STUB(paths_dialog_paste_path_callback) -STUB(paths_dialog_import_path_callback) -STUB(paths_dialog_export_path_callback) -STUB(paths_dialog_edit_path_attributes_callback) -STUB(tools_register) -QUIET_STUB(GIMP_IS_FUZZY_SELECT) -QUIET_STUB(GIMP_IS_MOVE_TOOL) -STUB(crop_image) -STUB(dodgeburn_non_gui) -STUB(dodgeburn_non_gui_default) -STUB(ellipse_select) -STUB(eraser_non_gui) -STUB(eraser_non_gui_default) -STUB(transform_core_cut) -STUB(flip_tool_flip) -STUB(transform_core_paste) -STUB(free_select) -STUB(find_contiguous_region) -STUB(fuzzy_mask) -STUB(fuzzy_select) -STUB(paintbrush_non_gui) -STUB(paintbrush_non_gui_default) -STUB(pencil_non_gui) -STUB(perspective_find_transform) -STUB(perspective_tool_perspective) -STUB(rect_select) -STUB(rotate_tool_rotate) -STUB(scale_tool_scale) -STUB(shear_tool_shear) -STUB(smudge_non_gui) -STUB(smudge_non_gui_default) -STUB(transform_core_do) -STUB(airbrush_non_gui) -STUB(airbrush_non_gui_default) -STUB(blend) -STUB(bucket_fill) -STUB(by_color_select) -STUB(clone_non_gui) -STUB(clone_non_gui_default) -STUB(convolve_non_gui) -STUB(convolve_non_gui_default) diff --git a/app/tools/tool.h b/app/tools/tool.h index 87c02d39a0..b76acd9fce 100644 --- a/app/tools/tool.h +++ b/app/tools/tool.h @@ -30,7 +30,6 @@ #define GIMP_TYPE_BY_COLOR_SELECT_TOOL GTK_TYPE_NONE #define GIMP_TYPE_BUCKET_FILL_TOOL GTK_TYPE_NONE #define GIMP_TYPE_BLEND_TOOL GTK_TYPE_NONE -#define GIMP_TYPE_PAINTBRUSH_TOOL GTK_TYPE_NONE #define GIMP_TYPE_PENCIL_TOOL GTK_TYPE_NONE #define GIMP_TYPE_ERASER_TOOL GTK_TYPE_NONE #define GIMP_TYPE_AIRBRUSH_TOOL GTK_TYPE_NONE @@ -79,7 +78,6 @@ struct _GimpTool gboolean toggled; /* Bad hack to let the paint_core show the * right toggle cursors */ - PaintCore *paintcore; }; struct _GimpToolClass @@ -118,10 +116,6 @@ struct _GimpToolClass GdkEventMotion *mevent, GDisplay *gdisp); }; - - -/* Function declarations */ - GtkType gimp_tool_get_type (void); void gimp_tool_initialize (GimpTool *tool, @@ -150,7 +144,6 @@ void gimp_tool_cursor_update (GimpTool *tool, void gimp_tool_oper_update (GimpTool *tool, GdkEventMotion *mevent, GDisplay *gdisp); - const gchar * gimp_tool_get_PDB_string (GimpTool *tool); diff --git a/app/tools/tools.c b/app/tools/tools.c index ce155f4db4..26ddb4fb19 100644 --- a/app/tools/tools.c +++ b/app/tools/tools.c @@ -30,7 +30,7 @@ #include "bucket_fill.h" #include "by_color_select.h" #include "clone.h" -#include "color_picker.h" +#include "gimpcolorpickertool.h" #include "convolve.h" #include "crop.h" #include "dodgeburn.h" @@ -43,7 +43,7 @@ #include "gimpimage.h" #include "measure.h" #include "move.h" -#include "paintbrush.h" +#include "gimppaintbrushtool.h" #include "pencil.h" #include "perspective_tool.h" #include "rect_select.h" @@ -52,16 +52,26 @@ #include "shear_tool.h" #include "smudge.h" +GimpPaintTool *non_gui_paint_tool; +GimpPaintToolClass *non_gui_paint_tool_class; + void register_tools (void) { - gimp_color_picker_register (); - gimp_measure_tool_register (); + gimp_color_picker_tool_register (); + gimp_paintbrush_tool_register (); + /*FIXME gimp_measure_tool_register (); */ gimp_move_tool_register (); - gimp_text_tool_register (); + /*FIXME gimp_text_tool_register (); */ + + /* EEEEEEK! */ + non_gui_paint_tool = gimp_paint_tool_new(); + non_gui_paint_tool_class = GIMP_PAINT_TOOL_CLASS(gtk_type_class(GIMP_TYPE_PAINT_TOOL)); /* + snatched from the pdb. For inspiration only. ;) + procedural_db_register (&airbrush_proc); procedural_db_register (&airbrush_default_proc); procedural_db_register (&blend_proc); @@ -81,8 +91,6 @@ register_tools (void) procedural_db_register (&flip_proc); procedural_db_register (&free_select_proc); procedural_db_register (&fuzzy_select_proc); - procedural_db_register (&paintbrush_proc); - procedural_db_register (&paintbrush_default_proc); procedural_db_register (&pencil_proc); procedural_db_register (&perspective_proc); procedural_db_register (&rect_select_proc); diff --git a/app/tools/transform_core.h b/app/tools/transform_core.h index bedc354368..62fbd7ef80 100644 --- a/app/tools/transform_core.h +++ b/app/tools/transform_core.h @@ -38,7 +38,7 @@ typedef TileManager * (* TransformFunc) (Tool *tool, struct _TransformCore { - DrawCore *core; /* Core select object */ + GimpDrawTool parent_instance; /* Core select object */ gint startx; /* starting x coord */ gint starty; /* starting y coord */ diff --git a/app/undo.c b/app/undo.c index 5e4b0760e1..1ea2784d84 100644 --- a/app/undo.c +++ b/app/undo.c @@ -25,7 +25,6 @@ #include "apptypes.h" -#include "draw_core.h" #include "drawable.h" #include "floating_sel.h" #include "gdisplay.h" @@ -47,7 +46,8 @@ #include "undo.h" #include "tools/by_color_select.h" -#include "tools/paint_core.h" +#include "tools/gimpdrawtool.h" +#include "tools/gimppainttool.h" #include "tools/tool.h" #include "tools/transform_core.h" diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am index 589f9b5563..37fd0f538f 100644 --- a/libgimp/Makefile.am +++ b/libgimp/Makefile.am @@ -115,7 +115,7 @@ libgimpi_a_SOURCES = \ if STATICLIBS ## Evil hack to insure all deps are satisfied on first-run make -libgimpi_a_DEPENDENCIES = libgimp.la +libgimpi_a_DEPENDENCIES = libgimp-1.3.la endif # help `make' along by giving another name for the file, which it knows diff --git a/tools/pdbgen/Makefile.am b/tools/pdbgen/Makefile.am index 5c8fdd7df7..26df3f78ab 100644 --- a/tools/pdbgen/Makefile.am +++ b/tools/pdbgen/Makefile.am @@ -66,7 +66,7 @@ enum_headers = \ ../../app/tools/convolve.h \ ../../app/tools/dodgeburn.h \ ../../app/tools/hue_saturation.h \ - ../../app/tools/paint_core.h \ + ../../app/tools/gimppainttool.h \ ../../app/tools/text_tool.h pdb_scripts = \