diff --git a/ChangeLog b/ChangeLog index 0613c52435..91a718dcaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,57 @@ +2006-09-02 Michael Natterer + + Merged the "soc-2006-healing-brush" branch. That branch is now + officially closed and all further fixes and changes have to be + applied to HEAD. + + Did some minor adjustments, mostly small indentation and spacing + fixes. Derive the tool from the newly introduced GimpBrushTool + which did not exist when the branch was created. + + Thanks a lot to Kevin Sookocheff for this nice contribution! + + * app/paint/paint-enums.[ch]: new enum GimpHealAlignMode. + + * app/paint/Makefile.am + * app/paint/makefile.msc + * app/paint/gimpheal.[ch] + * app/paint/gimphealoptions.[ch]: the heal core and its options. + + * app/paint/gimp-paint.c: register the heal core. + + * app/tools/Makefile.am + * app/tools/makefile.msc + * app/tools/gimphealtool.[ch]: the heal tool. + + * app/tools/gimp-tools.c: register the heal tool. + + * app/tools/gimppaintoptions-gui.c: show the widgets that are used + by heal. + + * app/widgets/gimphelp-ids.h: the heal help ID. + + * tools/pdbgen/stddefs.pdb + * tools/pdbgen/pdb/paint_tools.pdb: the heal PDB wrappers. + + * app/widgets/widgets-enums.h + * app/widgets/gimpcursor.c + * cursors/Makefile.am + * cursors/makefile.msc + * cursors/tool-heal.png + * cursors/xbm/tool-heal.xbm + * cursors/xbm/tool-heal-mask.xbm: a new cursor for the heal tool. + + * libgimpwidgets/gimpstock.[ch] + * themes/Default/images/Makefile.am + * themes/Default/images/makefile.msc + * themes/Default/images/tools/stock-tool-heal-16.png + * themes/Default/images/tools/stock-tool-heal-22.png: new stock + icons for the heal tool. + + * app/pdb/internal_procs.c + * app/pdb/paint_tools_cmds.c + * libgimp/gimppainttools_pdb.[ch]: regenerated. + 2006-09-02 Michael Natterer * app/paint/gimpclone.c diff --git a/app/paint/Makefile.am b/app/paint/Makefile.am index 1637ffaa1d..5b21a477e6 100644 --- a/app/paint/Makefile.am +++ b/app/paint/Makefile.am @@ -42,6 +42,10 @@ libapppaint_a_sources = \ gimperaser.h \ gimperaseroptions.c \ gimperaseroptions.h \ + gimpheal.c \ + gimpheal.h \ + gimphealoptions.c \ + gimphealoptions.h \ gimpink.c \ gimpink.h \ gimpink-blob.c \ diff --git a/app/paint/gimp-paint.c b/app/paint/gimp-paint.c index 820443f853..f0c2290904 100644 --- a/app/paint/gimp-paint.c +++ b/app/paint/gimp-paint.c @@ -32,6 +32,7 @@ #include "gimpconvolve.h" #include "gimpdodgeburn.h" #include "gimperaser.h" +#include "gimpheal.h" #include "gimpink.h" #include "gimppaintoptions.h" #include "gimppaintbrush.h" @@ -60,6 +61,7 @@ gimp_paint_init (Gimp *gimp) gimp_smudge_register, gimp_convolve_register, gimp_clone_register, + gimp_heal_register, gimp_ink_register, gimp_airbrush_register, gimp_eraser_register, diff --git a/app/paint/gimpheal.c b/app/paint/gimpheal.c index dcb1041aff..b342b9915a 100644 --- a/app/paint/gimpheal.c +++ b/app/paint/gimpheal.c @@ -44,6 +44,15 @@ #include "gimp-intl.h" +/* NOTES: + * + * I had the code working for healing from a pattern, but the results look + * terrible and I can't see a use for it right now. + * + * The support for registered alignment has been removed because it doesn't make + * sense for healing. + */ + enum { PROP_0, @@ -75,8 +84,10 @@ static void gimp_heal_motion (GimpPaintCore *paint_core, static void gimp_heal_set_src_drawable (GimpHeal *heal, GimpDrawable *drawable); + G_DEFINE_TYPE (GimpHeal, gimp_heal, GIMP_TYPE_BRUSH_CORE) + void gimp_heal_register (Gimp *gimp, GimpPaintRegisterCallback callback) @@ -92,9 +103,9 @@ gimp_heal_register (Gimp *gimp, static void gimp_heal_class_init (GimpHealClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass); - GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass); + GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass); object_class->set_property = gimp_heal_set_property; object_class->get_property = gimp_heal_get_property; @@ -131,9 +142,6 @@ gimp_heal_init (GimpHeal *heal) heal->src_x = 0.0; heal->src_y = 0.0; - heal->orig_src_x = 0.0; - heal->orig_src_y = 0.0; - heal->offset_x = 0.0; heal->offset_y = 0.0; heal->first_stroke = TRUE; @@ -196,8 +204,7 @@ gimp_heal_paint (GimpPaintCore *paint_core, GimpPaintState paint_state, guint32 time) { - GimpHeal *heal = GIMP_HEAL (paint_core); - GimpHealOptions *options = GIMP_HEAL_OPTIONS (paint_options); + GimpHeal *heal = GIMP_HEAL (paint_core); /* gimp passes the current state of the painting system to the function */ switch (paint_state) @@ -215,13 +222,6 @@ gimp_heal_paint (GimpPaintCore *paint_core, heal->src_y = paint_core->cur_coords.y; /* set first stroke to be true */ - heal->first_stroke = TRUE; - } - else if (options->align_mode == GIMP_HEAL_ALIGN_NO) - { - heal->orig_src_x = heal->src_x; - heal->orig_src_y = heal->src_y; - heal->first_stroke = TRUE; } break; @@ -243,13 +243,9 @@ gimp_heal_paint (GimpPaintCore *paint_core, gint dest_x = paint_core->cur_coords.x; gint dest_y = paint_core->cur_coords.y; - /* update the coordinates depending on the alignment mode */ - if (options->align_mode == GIMP_HEAL_ALIGN_FIXED) - { - heal->offset_x = heal->src_x - dest_x; - heal->offset_y = heal->src_y - dest_y; - } - else if (heal->first_stroke) + /* if this is the first stroke, record the offset of the destination + * relative to the source */ + if (heal->first_stroke) { heal->offset_x = heal->src_x - dest_x; heal->offset_y = heal->src_y - dest_y; @@ -257,22 +253,16 @@ gimp_heal_paint (GimpPaintCore *paint_core, heal->first_stroke = FALSE; } + /* if this is not the first stroke, set the source as + * destination + offset */ heal->src_x = dest_x + heal->offset_x; heal->src_y = dest_y + heal->offset_y; - /* defined later, does the actual healing */ + /* defined later, does the actual cloning */ gimp_heal_motion (paint_core, drawable, paint_options); } break; - case GIMP_PAINT_STATE_FINISH: - if ((options->align_mode == GIMP_HEAL_ALIGN_NO) && (! heal->first_stroke)) - { - heal->src_x = heal->orig_src_x; - heal->src_y = heal->orig_src_y; - } - break; - default: break; } @@ -283,9 +273,9 @@ gimp_heal_paint (GimpPaintCore *paint_core, } /* - * Substitute any zeros in the input PixelRegion for ones. This is needed by - * the algorithm to avoid division by zero, and to get a more realistic image - * since multiplying by zero is often incorrect (i.e., healing from a dark to + * Substitute any zeros in the input PixelRegion for ones. This is needed by + * the algorithm to avoid division by zero, and to get a more realistic image + * since multiplying by zero is often incorrect (i.e., healing from a dark to * a light region will have incorrect spots of zero) */ static void @@ -300,8 +290,8 @@ gimp_heal_substitute_0_for_1 (PixelRegion *pr) guchar *pr_data = pr->data; guchar *p; - - for (i = 0; i < height; i++) + + for (i = 0; i < height; i++) { p = pr_data; @@ -340,8 +330,8 @@ gimp_heal_divide (PixelRegion *topPR, guchar *t; guchar *b; gdouble *r = result; - - for (i = 0; i < height; i++) + + for (i = 0; i < height; i++) { t = t_data; b = b_data; @@ -363,8 +353,8 @@ gimp_heal_divide (PixelRegion *topPR, } } -/* - * multiply first by secondPR and store the result as a PixelRegion +/* + * multiply first by secondPR and store the result as a PixelRegion */ static void gimp_heal_multiply (gdouble *first, @@ -384,7 +374,7 @@ gimp_heal_multiply (gdouble *first, guchar *s; guchar *r; - for (i = 0; i < height; i++) + for (i = 0; i < height; i++) { s = s_data; r = r_data; @@ -468,20 +458,20 @@ gimp_heal_laplace_loop (gdouble *matrix, gdouble *solution) { #define EPSILON 0.0001 -#define MAX_ITER 500 +#define MAX_ITER 500 gint num_iter = 0; gdouble err; /* do one iteration and store the amount of error */ err = gimp_heal_laplace_iteration (matrix, height, depth, width, solution); - + /* copy solution to matrix */ memcpy (matrix, solution, width * height * depth * sizeof(double)); /* repeat until convergence or max iterations */ - while (err > EPSILON) - { + while (err > EPSILON) + { err = gimp_heal_laplace_iteration (matrix, height, depth, width, solution); memcpy (matrix, solution, width * height * depth * sizeof(double)); @@ -492,9 +482,9 @@ gimp_heal_laplace_loop (gdouble *matrix, } } -/* - * The healing brush algorithm. Heal tempPR and store the result in srcPR. +/* * Algorithm Design: + * * T. Georgiev, "Image Reconstruction Invariant to Relighting", EUROGRAPHICS * 2005, http://www.tgeorgiev.net/ */ @@ -517,33 +507,13 @@ gimp_heal_region (PixelRegion *tempPR, /* multiply a double by srcPR and store in tempPR */ gimp_heal_multiply (i_2, srcPR, tempPR); - + g_free (i_1); g_free (i_2); return tempPR; } -void print_uchar_matrix (guchar *matrix, gint width, gint height, gint depth, gint rowstride) -{ - gint i,j; - - guchar *temp; - - for (i = 0; i < height; i++) - { - temp = matrix; - for (j = 0; j < width; j++) - { - printf("%d\t", *temp); - temp += depth; - } - - printf("\n"); - matrix += rowstride; - } -} - static void gimp_heal_motion (GimpPaintCore *paint_core, GimpDrawable *drawable, @@ -566,17 +536,11 @@ gimp_heal_motion (GimpPaintCore *paint_core, gint offset_x; gint offset_y; - /* FIXME: Why doesn't the sample merged option work? It is set up exactly as - * in the clone tool, but nothing gets displayed properly. - * - * Currently merged is disabled in gimphealtool.c. If you want to try - * and get it working, enable it there. - */ - + /* get the image */ image = gimp_item_get_image (GIMP_ITEM (drawable)); - - /* FIXME: This test expects a GimpImageType variable, not GimpImage */ - if (GIMP_IMAGE_TYPE_IS_INDEXED (image)) + + /* display a warning about indexed images and return */ + if (GIMP_IMAGE_TYPE_IS_INDEXED (drawable->type)) { g_message (_("Indexed images are not currently supported.")); return; @@ -589,7 +553,7 @@ gimp_heal_motion (GimpPaintCore *paint_core, if (! heal->src_drawable) return; - + /* prepare the regions to get data from */ src_pickable = GIMP_PICKABLE (heal->src_drawable); src_image = gimp_pickable_get_image (src_pickable); @@ -611,8 +575,7 @@ gimp_heal_motion (GimpPaintCore *paint_core, offset_y += off_y; } - gimp_pickable_flush (src_pickable); - + /* get the canvas area */ area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options); if (!area) return; @@ -624,28 +587,28 @@ gimp_heal_motion (GimpPaintCore *paint_core, src_tiles = gimp_pickable_get_tiles (src_pickable); /* FIXME: the area under the cursor and the source area should be x% larger - * than the brush size so that we have seamless blending. Otherwise the brush - * must be a lot bigger than the area to heal in order to get good results. - * Having the user pick such a large brush is perhaps counter-intutitive? */ + * than the brush size. Otherwise the brush must be a lot bigger than the + * area to heal to get good results. Having the user pick such a large brush + * is perhaps counter-intutitive? */ /* Get the area underneath the cursor */ { TempBuf *orig; gint x1, x2, y1, y2; - x1 = CLAMP (area->x, + x1 = CLAMP (area->x, 0, tile_manager_width (src_tiles)); - y1 = CLAMP (area->y, + y1 = CLAMP (area->y, 0, tile_manager_height (src_tiles)); - x2 = CLAMP (area->x + area->width, + x2 = CLAMP (area->x + area->width, 0, tile_manager_width (src_tiles)); - y2 = CLAMP (area->y + area->height, + y2 = CLAMP (area->y + area->height, 0, tile_manager_height (src_tiles)); if (! (x2 - x1) || (! (y2 - y1))) return; - /* get the original image data */ + /* get the original image data at the cursor location */ if (options->sample_merged) orig = gimp_paint_core_get_orig_proj (paint_core, src_pickable, @@ -658,9 +621,9 @@ gimp_heal_motion (GimpPaintCore *paint_core, pixel_region_init_temp_buf (&srcPR, orig, 0, 0, x2 - x1, y2 - y1); } - temp = temp_buf_new (srcPR.w, srcPR.h, srcPR.bytes, 0, 0, NULL); + temp = temp_buf_new (srcPR.w, srcPR.h, srcPR.bytes, 0, 0, NULL); - pixel_region_init_temp_buf (&tempPR, temp, 0, 0, srcPR.w, srcPR.h); + pixel_region_init_temp_buf (&tempPR, temp, 0, 0, srcPR.w, srcPR.h); copy_region (&srcPR, &tempPR); @@ -671,42 +634,30 @@ gimp_heal_motion (GimpPaintCore *paint_core, TempBuf *orig; gint x1, x2, y1, y2; - x1 = CLAMP (area->x + offset_x, + x1 = CLAMP (area->x + offset_x, 0, tile_manager_width (src_tiles)); - y1 = CLAMP (area->y + offset_y, + y1 = CLAMP (area->y + offset_y, 0, tile_manager_height (src_tiles)); - x2 = CLAMP (area->x + offset_x + area->width, + x2 = CLAMP (area->x + offset_x + area->width, 0, tile_manager_width (src_tiles)); - y2 = CLAMP (area->y + offset_y + area->height, + y2 = CLAMP (area->y + offset_y + area->height, 0, tile_manager_height (src_tiles)); if (! (x2 - x1) || (! (y2 - y1))) return; - /* if we have a different source and destination image */ - if (( options->sample_merged && (src_image != image)) || - (! options->sample_merged && (heal->src_drawable != drawable))) - { - /* FIXME: Here we need to initialize srcPR using data from the other - * image. */ - g_message (_("Healing between images is not currently supported.")); - return; - } - /* if we don't have a different source and destination image */ + /* get the original image data at the sample location */ + if (options->sample_merged) + orig = gimp_paint_core_get_orig_proj (paint_core, + src_pickable, + x1, y1, x2, y2); else - { - if (options->sample_merged) - orig = gimp_paint_core_get_orig_proj (paint_core, - src_pickable, - x1, y1, x2, y2); - else - orig = gimp_paint_core_get_orig_image (paint_core, - GIMP_DRAWABLE (src_pickable), - x1, y1, x2, y2); + orig = gimp_paint_core_get_orig_image (paint_core, + GIMP_DRAWABLE (src_pickable), + x1, y1, x2, y2); + + pixel_region_init_temp_buf (&srcPR, orig, 0, 0, x2 - x1, y2 - y1); - pixel_region_init_temp_buf (&srcPR, orig, 0, 0, x2 - x1, y2 - y1); - } - /* set the proper offset */ offset_x = x1 - (area->x + offset_x); offset_y = y1 - (area->y + offset_y); @@ -717,11 +668,11 @@ gimp_heal_motion (GimpPaintCore *paint_core, /* get the destination to paint to */ pixel_region_init_temp_buf (&destPR, area, offset_x, offset_y, srcPR.w, srcPR.h); - /* FIXME: Can we ensure that this is true in the code above? + /* FIXME: Can we ensure that this is true in the code above? * Is it already guaranteed to be true before we get here? */ /* check that srcPR, tempPR, and destPR are the same size */ if ((srcPR.w != tempPR.w ) || (srcPR.w != destPR.w ) || - (srcPR.h != tempPR.h ) || (srcPR.h != destPR.h )) + (srcPR.h != tempPR.h ) || (srcPR.h != destPR.h )) { g_message (_("Source and destination regions are not the same size.")); return; @@ -734,15 +685,18 @@ gimp_heal_motion (GimpPaintCore *paint_core, pixel_region_init_data (&tempPR, tempPR.data, tempPR.bytes, tempPR.rowstride, 0, 0, tempPR.w, tempPR.h); - /* add an alpha region to the area if necessary */ - if (! gimp_drawable_has_alpha (drawable)) + /* add an alpha region to the area if necessary. + * sample_merged doesn't need an alpha because its always 4 bpp */ + if ((! gimp_drawable_has_alpha (drawable)) && (! options->sample_merged)) add_alpha_region (&tempPR, &destPR); - else + else copy_region (&tempPR, &destPR); + /* check the brush pressure */ if (pressure_options->opacity) opacity *= PRESSURE_SCALE * paint_core->cur_coords.pressure; + /* replace the canvas with our healed data */ gimp_brush_core_replace_canvas (GIMP_BRUSH_CORE (paint_core), drawable, MIN (opacity, GIMP_OPACITY_OPAQUE), @@ -750,7 +704,7 @@ gimp_heal_motion (GimpPaintCore *paint_core, gimp_paint_options_get_brush_mode (paint_options), GIMP_PAINT_CONSTANT); } - + static void gimp_heal_src_drawable_removed (GimpDrawable *drawable, GimpHeal *heal) diff --git a/app/paint/gimpheal.h b/app/paint/gimpheal.h index 9e1b475bea..7dace3994e 100644 --- a/app/paint/gimpheal.h +++ b/app/paint/gimpheal.h @@ -19,8 +19,10 @@ #ifndef __GIMP_HEAL_H__ #define __GIMP_HEAL_H__ + #include "gimpbrushcore.h" + #define GIMP_TYPE_HEAL (gimp_heal_get_type ()) #define GIMP_HEAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_HEAL, GimpHeal)) #define GIMP_HEAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_HEAL, GimpHealClass)) @@ -28,30 +30,31 @@ #define GIMP_IS_HEAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_HEAL)) #define GIMP_HEAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_HEAL, GimpHealClass)) + typedef struct _GimpHeal GimpHeal; typedef struct _GimpHealClass GimpHealClass; struct _GimpHeal { - GimpBrushCore parent_instance; + GimpBrushCore parent_instance; - gboolean set_source; + gboolean set_source; - GimpDrawable *src_drawable; - gdouble src_x; - gdouble src_y; + GimpDrawable *src_drawable; + gdouble src_x; + gdouble src_y; - gdouble orig_src_x; - gdouble orig_src_y; + gdouble orig_src_x; + gdouble orig_src_y; - gdouble offset_x; - gdouble offset_y; - gboolean first_stroke; + gdouble offset_x; + gdouble offset_y; + gboolean first_stroke; }; struct _GimpHealClass { - GimpBrushCoreClass parent_class; + GimpBrushCoreClass parent_class; }; diff --git a/app/paint/gimphealoptions.c b/app/paint/gimphealoptions.c index 9891d9cfdf..303cd43917 100644 --- a/app/paint/gimphealoptions.c +++ b/app/paint/gimphealoptions.c @@ -23,8 +23,10 @@ #include "libgimpconfig/gimpconfig.h" #include "paint-types.h" + #include "gimphealoptions.h" + enum { PROP_0, @@ -32,6 +34,7 @@ enum PROP_SAMPLE_MERGED }; + static void gimp_heal_options_set_property (GObject *object, guint property_id, const GValue *value, @@ -41,8 +44,10 @@ static void gimp_heal_options_get_property (GObject *object, GValue *value, GParamSpec *pspec); + G_DEFINE_TYPE (GimpHealOptions, gimp_heal_options, GIMP_TYPE_PAINT_OPTIONS) + static void gimp_heal_options_class_init (GimpHealOptionsClass *klass) { @@ -61,7 +66,6 @@ gimp_heal_options_class_init (GimpHealOptionsClass *klass) "sample-merged", NULL, FALSE, GIMP_PARAM_STATIC_STRINGS); - } static void diff --git a/app/paint/gimphealoptions.h b/app/paint/gimphealoptions.h index 9bdf5724e0..1ade24695c 100644 --- a/app/paint/gimphealoptions.h +++ b/app/paint/gimphealoptions.h @@ -31,8 +31,8 @@ #define GIMP_HEAL_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_HEAL_OPTIONS, GimpHealOptionsClass)) -typedef struct _GimpHealOptions GimpHealOptions; -typedef struct _GimpPaintOptionsClass GimpHealOptionsClass; +typedef struct _GimpHealOptions GimpHealOptions; +typedef struct _GimpPaintOptionsClass GimpHealOptionsClass; struct _GimpHealOptions { @@ -41,8 +41,9 @@ struct _GimpHealOptions GimpHealAlignMode align_mode; gboolean sample_merged; }; - + GType gimp_heal_options_get_type (void) G_GNUC_CONST; + #endif /* __GIMP_HEAL_OPTIONS_H__ */ diff --git a/app/paint/makefile.msc b/app/paint/makefile.msc index 91184a7e10..46bfbf3426 100644 --- a/app/paint/makefile.msc +++ b/app/paint/makefile.msc @@ -42,6 +42,8 @@ OBJECTS = \ gimpink-blob.obj \ gimpink-undo.obj \ gimpinkoptions.obj \ + gimpheal.obj \ + gimphealoptions.obj \ gimppaintbrush.obj \ gimppaintcore.obj \ gimppaintcore-stroke.obj \ diff --git a/app/paint/paint-enums.c b/app/paint/paint-enums.c index c4de84881a..1f61f23982 100644 --- a/app/paint/paint-enums.c +++ b/app/paint/paint-enums.c @@ -126,6 +126,36 @@ gimp_ink_blob_type_get_type (void) return type; } +GType +gimp_heal_align_mode_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_HEAL_ALIGN_NO, "GIMP_HEAL_ALIGN_NO", "no" }, + { GIMP_HEAL_ALIGN_YES, "GIMP_HEAL_ALIGN_YES", "yes" }, + { GIMP_HEAL_ALIGN_FIXED, "GIMP_HEAL_ALIGN_FIXED", "fixed" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_HEAL_ALIGN_NO, N_("None"), NULL }, + { GIMP_HEAL_ALIGN_YES, N_("Aligned"), NULL }, + { GIMP_HEAL_ALIGN_FIXED, N_("Fixed"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (! type) + { + type = g_enum_register_static ("GimpHealAlignMode", values); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + /* Generated data ends here */ diff --git a/app/paint/paint-enums.h b/app/paint/paint-enums.h index 0776ab7990..13da3c9ba8 100644 --- a/app/paint/paint-enums.h +++ b/app/paint/paint-enums.h @@ -84,6 +84,18 @@ typedef enum /*< pdb-skip >*/ } GimpInkBlobType; +#define GIMP_TYPE_HEAL_ALIGN_MODE (gimp_heal_align_mode_get_type ()) + +GType gimp_heal_align_mode_get_type (void) G_GNUC_CONST; + +typedef enum /*< pdb-skip >*/ +{ + GIMP_HEAL_ALIGN_NO, /*< desc="None" >*/ + GIMP_HEAL_ALIGN_YES, /*< desc="Aligned" >*/ + GIMP_HEAL_ALIGN_FIXED /*< desc="Fixed" >*/ +} GimpHealAlignMode; + + /* * non-registered enums; register them if needed */ diff --git a/app/pdb/internal_procs.c b/app/pdb/internal_procs.c index 4bd9e55b2c..1c7af5cd03 100644 --- a/app/pdb/internal_procs.c +++ b/app/pdb/internal_procs.c @@ -75,7 +75,7 @@ void register_undo_procs (GimpPDB *pdb); void register_unit_procs (GimpPDB *pdb); void register_vectors_procs (GimpPDB *pdb); -/* 530 procedures registered total */ +/* 532 procedures registered total */ void internal_procs_init (GimpPDB *pdb) diff --git a/app/pdb/paint_tools_cmds.c b/app/pdb/paint_tools_cmds.c index 5202fe9d56..2e92548e32 100644 --- a/app/pdb/paint_tools_cmds.c +++ b/app/pdb/paint_tools_cmds.c @@ -494,6 +494,86 @@ eraser_default_invoker (GimpProcedure *procedure, return gimp_procedure_get_return_values (procedure, success); } +static GValueArray * +heal_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GValueArray *args) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + GimpDrawable *src_drawable; + gdouble src_x; + gdouble src_y; + gint32 num_strokes; + const gdouble *strokes; + + drawable = gimp_value_get_drawable (&args->values[0], gimp); + src_drawable = gimp_value_get_drawable (&args->values[1], gimp); + src_x = g_value_get_double (&args->values[2]); + src_y = g_value_get_double (&args->values[3]); + num_strokes = g_value_get_int (&args->values[4]); + strokes = gimp_value_get_floatarray (&args->values[5]); + + if (success) + { + GimpPaintInfo *info = (GimpPaintInfo *) + gimp_container_get_child_by_name (gimp->paint_info_list, "gimp-heal"); + + success = (info && gimp_item_is_attached (GIMP_ITEM (drawable))); + + if (success) + { + GimpPaintOptions *options = gimp_paint_options_new (info); + + success = paint_tools_stroke (gimp, context, options, drawable, + num_strokes, strokes, + "src-drawable", src_drawable, + "src-x", src_x, + "src-y", src_y, + NULL); + } + } + + return gimp_procedure_get_return_values (procedure, success); +} + +static GValueArray * +heal_default_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GValueArray *args) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + gint32 num_strokes; + const gdouble *strokes; + + drawable = gimp_value_get_drawable (&args->values[0], gimp); + num_strokes = g_value_get_int (&args->values[1]); + strokes = gimp_value_get_floatarray (&args->values[2]); + + if (success) + { + GimpPaintInfo *info = (GimpPaintInfo *) + gimp_container_get_child_by_name (gimp->paint_info_list, "gimp-heal"); + + success = (info && gimp_item_is_attached (GIMP_ITEM (drawable))); + + if (success) + { + GimpPaintOptions *options = gimp_paint_options_new (info); + + success = paint_tools_stroke (gimp, context, options, drawable, + num_strokes, strokes, NULL); + } + } + + return gimp_procedure_get_return_values (procedure, success); +} + static GValueArray * paintbrush_invoker (GimpProcedure *procedure, Gimp *gimp, @@ -1102,6 +1182,90 @@ register_paint_tools_procs (GimpPDB *pdb) gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + /* + * gimp-heal + */ + procedure = gimp_procedure_new (heal_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-heal"); + gimp_procedure_set_static_strings (procedure, + "gimp-heal", + "Heal from the source to the dest drawable using the current brush", + "This tool heals the source drawable starting at the specified source coordinates to the dest drawable. For image healing, if the sum of the src coordinates and subsequent stroke offsets exceeds the extents of the src drawable, then no paint is transferred. The healing tool is capable of transforming between any image types except RGB->Indexed.", + "Kevin Sookocheff", + "Kevin Sookocheff", + "2006", + NULL); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "drawable", + "The affected drawable", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("src-drawable", + "src drawable", + "The source drawable", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("src-x", + "src x", + "The x coordinate in the source image", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("src-y", + "src y", + "The y coordinate in the source image", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("num-strokes", + "num strokes", + "Number of stroke control points (count each coordinate as 2 points)", + 2, G_MAXINT32, 2, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_float_array ("strokes", + "strokes", + "Array of stroke coordinates: { s1.x, s1.y, s2.x, s2.y, ..., sn.x, sn.y }", + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-heal-default + */ + procedure = gimp_procedure_new (heal_default_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-heal-default"); + gimp_procedure_set_static_strings (procedure, + "gimp-heal-default", + "Heal from the source to the dest drawable using the current brush", + "This tool heals from the source drawable starting at the specified source coordinates to the dest drawable. This function performs exactly the same as the 'gimp-heal' function except that the tools arguments are obtained from the healing option dialog. It this dialog has not been activated then the dialogs default values will be used.", + "Kevin Sookocheff", + "Kevin Sookocheff", + "2006", + NULL); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "drawable", + "The affected drawable", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("num-strokes", + "num strokes", + "Number of stroke control points (count each coordinate as 2 points)", + 2, G_MAXINT32, 2, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_float_array ("strokes", + "strokes", + "Array of stroke coordinates: { s1.x, s1.y, s2.x, s2.y, ..., sn.x, sn.y }", + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + /* * gimp-paintbrush */ diff --git a/app/tools/Makefile.am b/app/tools/Makefile.am index 4caa35d3f5..196f850e4b 100644 --- a/app/tools/Makefile.am +++ b/app/tools/Makefile.am @@ -78,6 +78,8 @@ libapptools_a_sources = \ gimpforegroundselecttool-undo.h \ gimpfuzzyselecttool.c \ gimpfuzzyselecttool.h \ + gimphealtool.c \ + gimphealtool.h \ gimphistogramoptions.c \ gimphistogramoptions.h \ gimphuesaturationtool.c \ diff --git a/app/tools/gimp-tools.c b/app/tools/gimp-tools.c index 04004a8d72..cf3b11b429 100644 --- a/app/tools/gimp-tools.c +++ b/app/tools/gimp-tools.c @@ -63,6 +63,7 @@ #include "gimpfreeselecttool.h" #include "gimpforegroundselecttool.h" #include "gimpfuzzyselecttool.h" +#include "gimphealtool.h" #include "gimphuesaturationtool.h" #include "gimpinktool.h" #include "gimpiscissorstool.h" @@ -132,6 +133,7 @@ gimp_tools_init (Gimp *gimp) gimp_dodge_burn_tool_register, gimp_smudge_tool_register, gimp_convolve_tool_register, + gimp_heal_tool_register, gimp_clone_tool_register, gimp_ink_tool_register, gimp_airbrush_tool_register, @@ -512,6 +514,10 @@ gimp_tools_register (GType tool_type, { paint_core_name = "gimp-clone"; } + else if (tool_type == GIMP_TYPE_HEAL_TOOL) + { + paint_core_name = "gimp-heal"; + } else if (tool_type == GIMP_TYPE_CONVOLVE_TOOL) { paint_core_name = "gimp-convolve"; diff --git a/app/tools/gimphealtool.c b/app/tools/gimphealtool.c index df78bad9a6..7fb1c55ac1 100644 --- a/app/tools/gimphealtool.c +++ b/app/tools/gimphealtool.c @@ -24,13 +24,13 @@ #include "tools-types.h" -#include "core/gimpchannel.h" +#include "core/gimpchannel.h" #include "core/gimpimage.h" #include "core/gimppickable.h" #include "core/gimptoolinfo.h" #include "paint/gimpheal.h" -#include "paint/gimphealoptions.h" +#include "paint/gimphealoptions.h" #include "widgets/gimphelp-ids.h" #include "widgets/gimpviewablebox.h" @@ -41,15 +41,17 @@ #include "gimphealtool.h" #include "gimppaintoptions-gui.h" #include "gimptoolcontrol.h" - + #include "gimp-intl.h" + #define TARGET_WIDTH 15 #define TARGET_HEIGHT 15 + static gboolean gimp_heal_tool_has_display (GimpTool *tool, GimpDisplay *display); -static GimpDisplay *gimp_heal_tool_has_image (GimpTool *tool, +static GimpDisplay * gimp_heal_tool_has_image (GimpTool *tool, GimpImage *image); static void gimp_heal_tool_button_press (GimpTool *tool, @@ -79,39 +81,39 @@ static void gimp_heal_tool_oper_update (GimpTool *tool, gboolean proximity, GimpDisplay *display); -static void gimp_heal_tool_draw (GimpDrawTool *draw_tool); +static void gimp_heal_tool_draw (GimpDrawTool *draw_tool); -static GtkWidget *gimp_heal_options_gui (GimpToolOptions *tool_options); +static GtkWidget * gimp_heal_options_gui (GimpToolOptions *tool_options); + + +G_DEFINE_TYPE (GimpHealTool, gimp_heal_tool, GIMP_TYPE_BRUSH_TOOL) -G_DEFINE_TYPE (GimpHealTool, gimp_heal_tool, GIMP_TYPE_PAINT_TOOL) void gimp_heal_tool_register (GimpToolRegisterCallback callback, gpointer data) { - (* callback) (GIMP_TYPE_HEAL_TOOL, /* tool type */ - GIMP_TYPE_HEAL_OPTIONS, /* tool option type */ - gimp_heal_options_gui, /* options gui */ - GIMP_PAINT_OPTIONS_CONTEXT_MASK, /* context properties */ - "gimp-heal-tool", /* identifier */ - _("Heal"), /* blurb */ - _("Heal image irregularities"), /* help */ - N_("_Heal"), /* menu path */ - "H", /* menu accelerator */ - NULL, /* help domain */ - GIMP_HELP_TOOL_HEAL, /* help data */ - GIMP_STOCK_TOOL_HEAL, /* stock id */ - data); /* register */ + (* callback) (GIMP_TYPE_HEAL_TOOL, + GIMP_TYPE_HEAL_OPTIONS, + gimp_heal_options_gui, + GIMP_PAINT_OPTIONS_CONTEXT_MASK, + "gimp-heal-tool", + _("Heal"), + _("Heal image irregularities"), + N_("_Heal"), + "H", + NULL, + GIMP_HELP_TOOL_HEAL, + GIMP_STOCK_TOOL_HEAL, + data); } static void gimp_heal_tool_class_init (GimpHealToolClass *klass) { - /* get parent classes where we override methods */ GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass); GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass); - /* override the methods */ tool_class->has_display = gimp_heal_tool_has_display; tool_class->has_image = gimp_heal_tool_has_image; tool_class->control = gimp_heal_tool_control; @@ -129,8 +131,7 @@ gimp_heal_tool_init (GimpHealTool *heal) GimpTool *tool = GIMP_TOOL (heal); GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); - gimp_tool_control_set_tool_cursor (tool->control, - GIMP_TOOL_CURSOR_HEAL); + gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_HEAL); paint_tool->status = _("Click to heal."); paint_tool->status_ctrl = _("%s to set a new heal source"); @@ -143,7 +144,8 @@ gimp_heal_tool_has_display (GimpTool *tool, GimpHealTool *heal_tool = GIMP_HEAL_TOOL (tool); return (display == heal_tool->src_display || - GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->has_display (tool, display)); + GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->has_display (tool, + display)); } static GimpDisplay * @@ -153,7 +155,8 @@ gimp_heal_tool_has_image (GimpTool *tool, GimpHealTool *heal_tool = GIMP_HEAL_TOOL (tool); GimpDisplay *display; - display = GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->has_image (tool, image); + display = GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->has_image (tool, + image); if (! display && heal_tool->src_display) { @@ -200,9 +203,9 @@ gimp_heal_tool_button_press (GimpTool *tool, GdkModifierType state, GimpDisplay *display) { - GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); - GimpHealTool *heal_tool = GIMP_HEAL_TOOL (tool); - GimpHeal *heal = GIMP_HEAL (paint_tool->core); + GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); + GimpHealTool *heal_tool = GIMP_HEAL_TOOL (tool); + GimpHeal *heal = GIMP_HEAL (paint_tool->core); GimpHealOptions *options; options = GIMP_HEAL_OPTIONS (tool->tool_info->tool_options); @@ -216,9 +219,9 @@ gimp_heal_tool_button_press (GimpTool *tool, /* state holds a set of bit-flags to indicate the state of modifier keys and * mouse buttons in various event types. Typical modifier keys are Shift, - * Control, Meta, Super, Hyper, Alt, Compose, Apple, CapsLock or ShiftLock. + * Control, Meta, Super, Hyper, Alt, Compose, Apple, CapsLock or ShiftLock. * Part of gtk -> GdkModifierType */ - if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK) + if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK) /* we enter here only if CTRL is pressed */ { /* mark that the source display has been set. defined in gimpheal.h */ @@ -256,10 +259,10 @@ gimp_heal_tool_button_press (GimpTool *tool, /* chain up to call the parents functions */ GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->button_press (tool, coords, - time, state, + time, state, display); - /* set the tool display's source position to match the current heal + /* set the tool display's source position to match the current heal * implementation source position */ heal_tool->src_x = heal->src_x; heal_tool->src_y = heal->src_y; @@ -275,9 +278,9 @@ gimp_heal_tool_motion (GimpTool *tool, GdkModifierType state, GimpDisplay *display) { - GimpHealTool *heal_tool = GIMP_HEAL_TOOL (tool); - GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); - GimpHeal *heal = GIMP_HEAL (paint_tool->core); + GimpHealTool *heal_tool = GIMP_HEAL_TOOL (tool); + GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); + GimpHeal *heal = GIMP_HEAL (paint_tool->core); /* pause drawing */ gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); @@ -309,9 +312,9 @@ gimp_heal_tool_cursor_update (GimpTool *tool, GdkModifierType state, GimpDisplay *display) { - GimpHealOptions *options; - GimpCursorType cursor = GIMP_CURSOR_MOUSE; - GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE; + GimpHealOptions *options; + GimpCursorType cursor = GIMP_CURSOR_MOUSE; + GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE; options = GIMP_HEAL_OPTIONS (tool->tool_info->tool_options); @@ -340,8 +343,7 @@ gimp_heal_tool_cursor_update (GimpTool *tool, /* chain up to the parent class */ GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->cursor_update (tool, coords, - state, display); - + state, display); } static void @@ -365,7 +367,7 @@ gimp_heal_tool_oper_update (GimpTool *tool, /* chain up to the parent class */ GIMP_TOOL_CLASS (gimp_heal_tool_parent_class)->oper_update (tool, coords, - state, proximity, + state, proximity, display); if (proximity) @@ -461,16 +463,12 @@ gimp_heal_tool_draw (GimpDrawTool *draw_tool) static GtkWidget * gimp_heal_options_gui (GimpToolOptions *tool_options) { - GObject *config; - GtkWidget *vbox; + GObject *config = G_OBJECT (tool_options); + GtkWidget *vbox = gimp_paint_options_gui (tool_options); GtkWidget *button; GtkWidget *table; GtkWidget *combo; - config = G_OBJECT (tool_options); - - vbox = gimp_paint_options_gui (tool_options); - /* create and attach the sample merged checkbox */ button = gimp_prop_check_button_new (config, "sample-merged", _("Sample merged")); diff --git a/app/tools/gimphealtool.h b/app/tools/gimphealtool.h index 63ca48449d..f40432ee8e 100644 --- a/app/tools/gimphealtool.h +++ b/app/tools/gimphealtool.h @@ -19,7 +19,9 @@ #ifndef __GIMP_HEAL_TOOL_H__ #define __GIMP_HEAL_TOOL_H__ -#include "gimppainttool.h" + +#include "gimpbrushtool.h" + #define GIMP_TYPE_HEAL_TOOL (gimp_heal_tool_get_type ()) #define GIMP_HEAL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_HEAL_TOOL, GimpHealTool)) @@ -28,12 +30,14 @@ #define GIMP_IS_HEAL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_HEAL_TOOL)) #define GIMP_HEAL_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_HEAL_TOOL, GimpHealToolClass)) + typedef struct _GimpHealTool GimpHealTool; typedef struct _GimpHealToolClass GimpHealToolClass; + struct _GimpHealTool { - GimpPaintTool parent_instance; + GimpBrushTool parent_instance; GimpDisplay *src_display; /* Detail about the source location to paint from */ gint src_x; @@ -42,13 +46,14 @@ struct _GimpHealTool struct _GimpHealToolClass { - GimpPaintToolClass parent_class; + GimpBrushToolClass parent_class; }; void gimp_heal_tool_register (GimpToolRegisterCallback callback, - gpointer data); + gpointer data); GType gimp_heal_tool_get_type (void) G_GNUC_CONST; + #endif /* __GIMP_HEAL_TOOL_H__ */ diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c index 7aa09ccc71..add5f3e52c 100644 --- a/app/tools/gimppaintoptions-gui.c +++ b/app/tools/gimppaintoptions-gui.c @@ -44,6 +44,7 @@ #include "gimpdodgeburntool.h" #include "gimpdodgeburntool.h" #include "gimperasertool.h" +#include "gimphealtool.h" #include "gimpinktool.h" #include "gimppaintbrushtool.h" #include "gimppaintoptions-gui.h" @@ -182,6 +183,7 @@ gimp_paint_options_gui (GimpToolOptions *tool_options) /* the "hard edge" toggle */ if (tool_type == GIMP_TYPE_ERASER_TOOL || tool_type == GIMP_TYPE_CLONE_TOOL || + tool_type == GIMP_TYPE_HEAL_TOOL || tool_type == GIMP_TYPE_CONVOLVE_TOOL || tool_type == GIMP_TYPE_DODGE_BURN_TOOL || tool_type == GIMP_TYPE_SMUDGE_TOOL) @@ -237,6 +239,7 @@ pressure_options_gui (GimpPressureOptions *pressure, /* the opacity toggle */ if (g_type_is_a (tool_type, GIMP_TYPE_PAINTBRUSH_TOOL) || tool_type == GIMP_TYPE_CLONE_TOOL || + tool_type == GIMP_TYPE_HEAL_TOOL || tool_type == GIMP_TYPE_DODGE_BURN_TOOL || tool_type == GIMP_TYPE_ERASER_TOOL) { @@ -249,6 +252,7 @@ pressure_options_gui (GimpPressureOptions *pressure, /* the pressure toggle */ if (tool_type == GIMP_TYPE_AIRBRUSH_TOOL || tool_type == GIMP_TYPE_CLONE_TOOL || + tool_type == GIMP_TYPE_HEAL_TOOL || tool_type == GIMP_TYPE_CONVOLVE_TOOL || tool_type == GIMP_TYPE_DODGE_BURN_TOOL || tool_type == GIMP_TYPE_PAINTBRUSH_TOOL || @@ -273,6 +277,7 @@ pressure_options_gui (GimpPressureOptions *pressure, /* the size toggle */ if (tool_type == GIMP_TYPE_CLONE_TOOL || + tool_type == GIMP_TYPE_HEAL_TOOL || tool_type == GIMP_TYPE_CONVOLVE_TOOL || tool_type == GIMP_TYPE_DODGE_BURN_TOOL || tool_type == GIMP_TYPE_ERASER_TOOL || diff --git a/app/tools/makefile.msc b/app/tools/makefile.msc index 0c555b64bc..6bf4e279a6 100644 --- a/app/tools/makefile.msc +++ b/app/tools/makefile.msc @@ -57,6 +57,7 @@ OBJECTS = \ gimpforegroundselecttool.obj \ gimpfreeselecttool.obj \ gimpfuzzyselecttool.obj \ + gimphealtool.obj \ gimphistogramoptions.obj \ gimphuesaturationtool.obj \ gimpimagemapoptions.obj \ diff --git a/app/widgets/gimpcursor.c b/app/widgets/gimpcursor.c index 885fcdef84..6efe6d1600 100644 --- a/app/widgets/gimpcursor.c +++ b/app/widgets/gimpcursor.c @@ -112,6 +112,8 @@ #include "cursors/xbm/tool-airbrush-mask.xbm" #include "cursors/xbm/tool-clone.xbm" #include "cursors/xbm/tool-clone-mask.xbm" +#include "cursors/xbm/tool-heal.xbm" +#include "cursors/xbm/tool-heal-mask.xbm" #include "cursors/xbm/tool-blur.xbm" #include "cursors/xbm/tool-blur-mask.xbm" #include "cursors/xbm/tool-ink.xbm" @@ -438,6 +440,12 @@ static GimpCursor gimp_tool_cursors[] = 0, 0, tool_clone, NULL, NULL, NULL }, + { + tool_heal_bits, tool_heal_mask_bits, + tool_heal_width, tool_heal_height, + 0, 0, + tool_heal, NULL, NULL, NULL + }, { tool_eraser_bits, tool_eraser_mask_bits, tool_eraser_width, tool_eraser_height, diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index 4c8fddf817..1b41a38101 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -253,6 +253,7 @@ #define GIMP_HELP_TOOL_FREE_SELECT "gimp-tool-free-select" #define GIMP_HELP_TOOL_FOREGROUND_SELECT "gimp-tool-foreground-select" #define GIMP_HELP_TOOL_FUZZY_SELECT "gimp-tool-fuzzy-select" +#define GIMP_HELP_TOOL_HEAL "gimp-tool-heal" #define GIMP_HELP_TOOL_HUE_SATURATION "gimp-tool-hue-saturation" #define GIMP_HELP_TOOL_INK "gimp-tool-ink" #define GIMP_HELP_TOOL_ISCISSORS "gimp-tool-iscissors" diff --git a/app/widgets/widgets-enums.h b/app/widgets/widgets-enums.h index fb465b2f25..2714c7da12 100644 --- a/app/widgets/widgets-enums.h +++ b/app/widgets/widgets-enums.h @@ -251,6 +251,7 @@ typedef enum /*< skip >*/ GIMP_TOOL_CURSOR_AIRBRUSH, GIMP_TOOL_CURSOR_INK, GIMP_TOOL_CURSOR_CLONE, + GIMP_TOOL_CURSOR_HEAL, GIMP_TOOL_CURSOR_ERASER, GIMP_TOOL_CURSOR_SMUDGE, GIMP_TOOL_CURSOR_BLUR, diff --git a/cursors/Makefile.am b/cursors/Makefile.am index fc4f2f55db..cf413a6ace 100644 --- a/cursors/Makefile.am +++ b/cursors/Makefile.am @@ -46,6 +46,7 @@ CURSOR_IMAGES = \ tool-free-select.png \ tool-fuzzy-select.png \ tool-hand.png \ + tool-heal.png \ tool-ink.png \ tool-iscissors.png \ tool-measure.png \ @@ -193,7 +194,9 @@ EXTRA_DIST = \ xbm/tool-measure.xbm \ xbm/tool-measure-mask.xbm \ xbm/tool-hand.xbm \ - xbm/tool-hand-mask.xbm + xbm/tool-hand-mask.xbm \ + xbm/tool-heal.xbm \ + xbm/tool-heal-mask.xbm noinst_DATA = gimp-tool-cursors.h diff --git a/cursors/makefile.msc b/cursors/makefile.msc index 940094b7ca..ef7dc0f366 100644 --- a/cursors/makefile.msc +++ b/cursors/makefile.msc @@ -46,6 +46,7 @@ CURSOR_LIST = \ tool_free_select tool-free-select.png \ tool_fuzzy_select tool-fuzzy-select.png \ tool_hand tool-hand.png \ + tool_heal tool-heal.png \ tool_ink tool-ink.png \ tool_iscissors tool-iscissors.png \ tool_measure tool-measure.png \ diff --git a/libgimp/gimppainttools_pdb.c b/libgimp/gimppainttools_pdb.c index c6bd88c229..715a7e7271 100644 --- a/libgimp/gimppainttools_pdb.c +++ b/libgimp/gimppainttools_pdb.c @@ -453,6 +453,99 @@ gimp_eraser_default (gint32 drawable_ID, return success; } +/** + * gimp_heal: + * @drawable_ID: The affected drawable. + * @src_drawable_ID: The source drawable. + * @src_x: The x coordinate in the source image. + * @src_y: The y coordinate in the source image. + * @num_strokes: Number of stroke control points (count each coordinate as 2 points). + * @strokes: Array of stroke coordinates: { s1.x, s1.y, s2.x, s2.y, ..., sn.x, sn.y }. + * + * Heal from the source to the dest drawable using the current brush + * + * This tool heals the source drawable starting at the specified source + * coordinates to the dest drawable. For image healing, if the sum of + * the src coordinates and subsequent stroke offsets exceeds the + * extents of the src drawable, then no paint is transferred. The + * healing tool is capable of transforming between any image types + * except RGB->Indexed. + * + * Returns: TRUE on success. + * + * Since: GIMP 2.4 + */ +gboolean +gimp_heal (gint32 drawable_ID, + gint32 src_drawable_ID, + gdouble src_x, + gdouble src_y, + gint num_strokes, + const gdouble *strokes) +{ + GimpParam *return_vals; + gint nreturn_vals; + gboolean success = TRUE; + + return_vals = gimp_run_procedure ("gimp-heal", + &nreturn_vals, + GIMP_PDB_DRAWABLE, drawable_ID, + GIMP_PDB_DRAWABLE, src_drawable_ID, + GIMP_PDB_FLOAT, src_x, + GIMP_PDB_FLOAT, src_y, + GIMP_PDB_INT32, num_strokes, + GIMP_PDB_FLOATARRAY, strokes, + GIMP_PDB_END); + + success = return_vals[0].data.d_status == GIMP_PDB_SUCCESS; + + gimp_destroy_params (return_vals, nreturn_vals); + + return success; +} + +/** + * gimp_heal_default: + * @drawable_ID: The affected drawable. + * @num_strokes: Number of stroke control points (count each coordinate as 2 points). + * @strokes: Array of stroke coordinates: { s1.x, s1.y, s2.x, s2.y, ..., sn.x, sn.y }. + * + * Heal from the source to the dest drawable using the current brush + * + * This tool heals from the source drawable starting at the specified + * source coordinates to the dest drawable. This function performs + * exactly the same as the gimp_heal() function except that the tools + * arguments are obtained from the healing option dialog. It this + * dialog has not been activated then the dialogs default values will + * be used. + * + * Returns: TRUE on success. + * + * Since: GIMP 2.4 + */ +gboolean +gimp_heal_default (gint32 drawable_ID, + gint num_strokes, + const gdouble *strokes) +{ + GimpParam *return_vals; + gint nreturn_vals; + gboolean success = TRUE; + + return_vals = gimp_run_procedure ("gimp-heal-default", + &nreturn_vals, + GIMP_PDB_DRAWABLE, drawable_ID, + GIMP_PDB_INT32, num_strokes, + GIMP_PDB_FLOATARRAY, strokes, + GIMP_PDB_END); + + success = return_vals[0].data.d_status == GIMP_PDB_SUCCESS; + + gimp_destroy_params (return_vals, nreturn_vals); + + return success; +} + /** * gimp_paintbrush: * @drawable_ID: The affected drawable. diff --git a/libgimp/gimppainttools_pdb.h b/libgimp/gimppainttools_pdb.h index 25a120ae3a..c70232f214 100644 --- a/libgimp/gimppainttools_pdb.h +++ b/libgimp/gimppainttools_pdb.h @@ -71,6 +71,15 @@ gboolean gimp_eraser (gint32 drawable_ID, gboolean gimp_eraser_default (gint32 drawable_ID, gint num_strokes, const gdouble *strokes); +gboolean gimp_heal (gint32 drawable_ID, + gint32 src_drawable_ID, + gdouble src_x, + gdouble src_y, + gint num_strokes, + const gdouble *strokes); +gboolean gimp_heal_default (gint32 drawable_ID, + gint num_strokes, + const gdouble *strokes); gboolean gimp_paintbrush (gint32 drawable_ID, gdouble fade_out, gint num_strokes, diff --git a/libgimpwidgets/gimpstock.c b/libgimpwidgets/gimpstock.c index 151ea325ed..39a3c49be2 100644 --- a/libgimpwidgets/gimpstock.c +++ b/libgimpwidgets/gimpstock.c @@ -287,6 +287,7 @@ static const GtkStockItem gimp_stock_items[] = { GIMP_STOCK_TOOL_FOREGROUND_SELECT, NULL, 0, 0, LIBGIMP_DOMAIN }, { GIMP_STOCK_TOOL_FUZZY_SELECT, NULL, 0, 0, LIBGIMP_DOMAIN }, { GIMP_STOCK_TOOL_HUE_SATURATION, NULL, 0, 0, LIBGIMP_DOMAIN }, + { GIMP_STOCK_TOOL_HEAL, NULL, 0, 0, LIBGIMP_DOMAIN }, { GIMP_STOCK_TOOL_INK, NULL, 0, 0, LIBGIMP_DOMAIN }, { GIMP_STOCK_TOOL_ISCISSORS, NULL, 0, 0, LIBGIMP_DOMAIN }, { GIMP_STOCK_TOOL_LEVELS, NULL, 0, 0, LIBGIMP_DOMAIN }, @@ -422,6 +423,7 @@ gimp_stock_button_pixbufs[] = { GIMP_STOCK_TOOL_FREE_SELECT, stock_tool_free_select_22 }, { GIMP_STOCK_TOOL_FOREGROUND_SELECT, stock_tool_foreground_select_22 }, { GIMP_STOCK_TOOL_FUZZY_SELECT, stock_tool_fuzzy_select_22 }, + { GIMP_STOCK_TOOL_HEAL, stock_tool_heal_22 }, { GIMP_STOCK_TOOL_HUE_SATURATION, stock_tool_hue_saturation_22 }, { GIMP_STOCK_TOOL_INK, stock_tool_ink_22 }, { GIMP_STOCK_TOOL_ISCISSORS, stock_tool_iscissors_22 }, @@ -568,6 +570,7 @@ gimp_stock_menu_pixbufs[] = { GIMP_STOCK_TOOL_FREE_SELECT, stock_tool_free_select_16 }, { GIMP_STOCK_TOOL_FOREGROUND_SELECT, stock_tool_foreground_select_16 }, { GIMP_STOCK_TOOL_FUZZY_SELECT, stock_tool_fuzzy_select_16 }, + { GIMP_STOCK_TOOL_HEAL, stock_tool_heal_16 }, { GIMP_STOCK_TOOL_HUE_SATURATION, stock_tool_hue_saturation_16 }, { GIMP_STOCK_TOOL_INK, stock_tool_ink_16 }, { GIMP_STOCK_TOOL_ISCISSORS, stock_tool_iscissors_16 }, diff --git a/libgimpwidgets/gimpstock.h b/libgimpwidgets/gimpstock.h index e4c50c85b4..cfa963e6b8 100644 --- a/libgimpwidgets/gimpstock.h +++ b/libgimpwidgets/gimpstock.h @@ -118,6 +118,7 @@ G_BEGIN_DECLS #define GIMP_STOCK_TOOL_FREE_SELECT "gimp-tool-free-select" #define GIMP_STOCK_TOOL_FOREGROUND_SELECT "gimp-tool-foreground-select" #define GIMP_STOCK_TOOL_FUZZY_SELECT "gimp-tool-fuzzy-select" +#define GIMP_STOCK_TOOL_HEAL "gimp-tool-heal" #define GIMP_STOCK_TOOL_HUE_SATURATION "gimp-tool-hue-saturation" #define GIMP_STOCK_TOOL_INK "gimp-tool-ink" #define GIMP_STOCK_TOOL_ISCISSORS "gimp-tool-iscissors" diff --git a/themes/Default/images/Makefile.am b/themes/Default/images/Makefile.am index 3a6c9e3c5f..66748180b3 100644 --- a/themes/Default/images/Makefile.am +++ b/themes/Default/images/Makefile.am @@ -272,6 +272,8 @@ STOCK_TOOL_IMAGES = \ tools/stock-tool-fuzzy-select-22.png \ tools/stock-tool-hue-saturation-16.png \ tools/stock-tool-hue-saturation-22.png \ + tools/stock-tool-heal-16.png \ + tools/stock-tool-heal-22.png \ tools/stock-tool-ink-16.png \ tools/stock-tool-ink-22.png \ tools/stock-tool-iscissors-16.png \ diff --git a/themes/Default/images/makefile.msc b/themes/Default/images/makefile.msc index e2b7627ea9..2b8a94295c 100644 --- a/themes/Default/images/makefile.msc +++ b/themes/Default/images/makefile.msc @@ -251,6 +251,8 @@ STOCK_TOOL_VARIABLES = \ stock_tool_free_select_22 tools/stock-tool-free-select-22.png \ stock_tool_fuzzy_select_16 tools/stock-tool-fuzzy-select-16.png \ stock_tool_fuzzy_select_22 tools/stock-tool-fuzzy-select-22.png \ + stock_tool_heal_16 tools/stock-tool-heal-16.png \ + stock_tool_heal_22 tools/stock-tool-heal-22.png \ stock_tool_hue_saturation_16 tools/stock-tool-hue-saturation-16.png \ stock_tool_hue_saturation_22 tools/stock-tool-hue-saturation-22.png \ stock_tool_ink_16 tools/stock-tool-ink-16.png \ diff --git a/themes/Default/images/tools/stock-tool-heal-16.png b/themes/Default/images/tools/stock-tool-heal-16.png new file mode 100644 index 0000000000..69fe110f2c Binary files /dev/null and b/themes/Default/images/tools/stock-tool-heal-16.png differ diff --git a/themes/Default/images/tools/stock-tool-heal-22.png b/themes/Default/images/tools/stock-tool-heal-22.png new file mode 100644 index 0000000000..b0a42b00da Binary files /dev/null and b/themes/Default/images/tools/stock-tool-heal-22.png differ diff --git a/tools/pdbgen/pdb/paint_tools.pdb b/tools/pdbgen/pdb/paint_tools.pdb index 9d7b2a738c..db3ced6b47 100644 --- a/tools/pdbgen/pdb/paint_tools.pdb +++ b/tools/pdbgen/pdb/paint_tools.pdb @@ -440,6 +440,98 @@ CODE ); } +sub heal { + $blurb = <<'BLURB'; +Heal from the source to the dest drawable using the current brush +BLURB + + $help = <<'HELP'; +This tool heals the source drawable starting at the specified +source coordinates to the dest drawable. For image healing, if the sum of the +src coordinates and subsequent stroke offsets exceeds the extents of the src +drawable, then no paint is transferred. The healing tool is capable of +transforming between any image types except RGB->Indexed. +HELP + + &kevins_pdb_misc('2006', '2.4'); + + @inargs = ( + { name => 'drawable', type => 'drawable', + desc => 'The affected drawable' }, + { name => 'src_drawable', type => 'drawable', + desc => 'The source drawable' }, + { name => 'src_x', type => 'float', + desc => 'The x coordinate in the source image' }, + { name => 'src_y', type => 'float', + desc => 'The y coordinate in the source image' }, + &stroke_arg + ); + + %invoke = ( + code => <<'CODE' +{ + GimpPaintInfo *info = (GimpPaintInfo *) + gimp_container_get_child_by_name (gimp->paint_info_list, "gimp-heal"); + + success = (info && gimp_item_is_attached (GIMP_ITEM (drawable))); + + if (success) + { + GimpPaintOptions *options = gimp_paint_options_new (info); + + success = paint_tools_stroke (gimp, context, options, drawable, + num_strokes, strokes, + "src-drawable", src_drawable, + "src-x", src_x, + "src-y", src_y, + NULL); + } +} +CODE + ); +} + +sub heal_default { + $blurb = <<'BLURB'; +Heal from the source to the dest drawable using the current brush +BLURB + + $help = <<'HELP'; +This tool heals from the source drawable starting at the specified +source coordinates to the dest drawable. This function performs exactly +the same as the gimp_heal() function except that the tools arguments are +obtained from the healing option dialog. It this dialog has not been activated +then the dialogs default values will be used. +HELP + + &kevins_pdb_misc('2006', '2.4'); + + @inargs = ( + { name => 'drawable', type => 'drawable', + desc => 'The affected drawable' }, + &stroke_arg + ); + + %invoke = ( + code => <<'CODE' +{ + GimpPaintInfo *info = (GimpPaintInfo *) + gimp_container_get_child_by_name (gimp->paint_info_list, "gimp-heal"); + + success = (info && gimp_item_is_attached (GIMP_ITEM (drawable))); + + if (success) + { + GimpPaintOptions *options = gimp_paint_options_new (info); + + success = paint_tools_stroke (gimp, context, options, drawable, + num_strokes, strokes, NULL); + } +} +CODE + ); +} + sub paintbrush { $blurb = <<'BLURB'; Paint in the current brush with optional fade out parameter and pull colors @@ -844,6 +936,7 @@ CODE convolve convolve_default dodgeburn dodgeburn_default eraser eraser_default + heal heal_default paintbrush paintbrush_default pencil smudge smudge_default); diff --git a/tools/pdbgen/stddefs.pdb b/tools/pdbgen/stddefs.pdb index b4b8f05cb0..d76d2819b0 100644 --- a/tools/pdbgen/stddefs.pdb +++ b/tools/pdbgen/stddefs.pdb @@ -82,6 +82,10 @@ sub josh_pdb_misc { contrib_pdb_misc('Josh MacDonald', '', @_); } +sub kevins_pdb_misc { + contrib_pdb_misc('Kevin Sookocheff', '', @_); +} + sub larry_pdb_misc { contrib_pdb_misc('Larry Ewing', '', @_); }