mirror of https://github.com/GNOME/gimp.git
Immplement "Sample Merged" for the clone tool. Fixes bug #123627.
2005-08-28 Michael Natterer <mitch@gimp.org> Immplement "Sample Merged" for the clone tool. Fixes bug #123627. * app/paint/gimppaintcore.[ch] (struct GimpPaintCore): added members "saved_proj_tiles" which stores the unmodified projection, "orig_proj_buf" which stores the unmodified temp paint application buf and "use_saved_proj" which controls if all the additional stuff should be allocated and managed. (gimp_paint_core_start): allocate the saved_proj_tiles if needed. (gimp_paint_core_get_orig_proj): new function like gimp_paint_core_get_orig_image() which returns unmodified projection pixels for paint application. (gimp_paint_core_validate_saved_proj_tiles): new function like gimp_paint_core_validate_undo_tiles() which copies the tiles that will be dirtied to saved_proj_tiles. (gimp_paint_core_paste): call above save_proj_tiles() so projection tiles are saved before dirtying them. * app/paint/gimpclone.[ch]: replaced member src_drawable by src_pickable and use the image's projection if sample_merged it TRUE. Adjust src offsets accordingly and use GimpPaintCore's new get_orig_proj() API to get the src pixels. * app/paint/gimpcloneoptions.[ch]: added boolean "sample_merged" property. * app/tools/gimpclonetool.c: follow GimpClone's src_drawable -> src_pickable change. (gimp_clone_tool_button_press): set the paint_core's "use_saved_proj" boolean before chaining up. (gimp_clone_options_gui): add a "Sample Merged" toggle button.
This commit is contained in:
parent
19ea886842
commit
26374e814e
39
ChangeLog
39
ChangeLog
|
@ -1,3 +1,42 @@
|
|||
2005-08-28 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
Immplement "Sample Merged" for the clone tool. Fixes bug #123627.
|
||||
|
||||
* app/paint/gimppaintcore.[ch] (struct GimpPaintCore): added
|
||||
members "saved_proj_tiles" which stores the unmodified projection,
|
||||
"orig_proj_buf" which stores the unmodified temp paint application
|
||||
buf and "use_saved_proj" which controls if all the additional
|
||||
stuff should be allocated and managed.
|
||||
|
||||
(gimp_paint_core_start): allocate the saved_proj_tiles if needed.
|
||||
|
||||
(gimp_paint_core_get_orig_proj): new function like
|
||||
gimp_paint_core_get_orig_image() which returns unmodified
|
||||
projection pixels for paint application.
|
||||
|
||||
(gimp_paint_core_validate_saved_proj_tiles): new function like
|
||||
gimp_paint_core_validate_undo_tiles() which copies the tiles that
|
||||
will be dirtied to saved_proj_tiles.
|
||||
|
||||
(gimp_paint_core_paste): call above save_proj_tiles() so
|
||||
projection tiles are saved before dirtying them.
|
||||
|
||||
* app/paint/gimpclone.[ch]: replaced member src_drawable by
|
||||
src_pickable and use the image's projection if sample_merged it
|
||||
TRUE. Adjust src offsets accordingly and use GimpPaintCore's new
|
||||
get_orig_proj() API to get the src pixels.
|
||||
|
||||
* app/paint/gimpcloneoptions.[ch]: added boolean "sample_merged"
|
||||
property.
|
||||
|
||||
* app/tools/gimpclonetool.c: follow GimpClone's src_drawable ->
|
||||
src_pickable change.
|
||||
|
||||
(gimp_clone_tool_button_press): set the paint_core's
|
||||
"use_saved_proj" boolean before chaining up.
|
||||
|
||||
(gimp_clone_options_gui): add a "Sample Merged" toggle button.
|
||||
|
||||
2005-08-28 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* m4macros/pythondev.m4: python headers on Win32 don't live in a
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "base/pixel-region.h"
|
||||
#include "base/temp-buf.h"
|
||||
#include "base/tile-manager.h"
|
||||
|
||||
#include "paint-funcs/paint-funcs.h"
|
||||
|
||||
|
@ -34,6 +35,8 @@
|
|||
#include "core/gimpdrawable.h"
|
||||
#include "core/gimpimage.h"
|
||||
#include "core/gimppattern.h"
|
||||
#include "core/gimppickable.h"
|
||||
#include "core/gimpprojection.h"
|
||||
|
||||
#include "gimpclone.h"
|
||||
#include "gimpcloneoptions.h"
|
||||
|
@ -56,10 +59,9 @@ static void gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
static void gimp_clone_line_image (GimpImage *dest,
|
||||
GimpImage *src,
|
||||
GimpDrawable *d_drawable,
|
||||
GimpDrawable *s_drawable,
|
||||
GimpPickable *s_pickable,
|
||||
guchar *s,
|
||||
guchar *d,
|
||||
gint has_alpha,
|
||||
gint src_bytes,
|
||||
gint dest_bytes,
|
||||
gint width);
|
||||
|
@ -72,8 +74,8 @@ static void gimp_clone_line_pattern (GimpImage *dest,
|
|||
gint bytes,
|
||||
gint width);
|
||||
|
||||
static void gimp_clone_set_src_drawable (GimpClone *clone,
|
||||
GimpDrawable *drawable);
|
||||
static void gimp_clone_set_src_pickable (GimpClone *clone,
|
||||
GimpPickable *pickable);
|
||||
|
||||
|
||||
static GimpBrushCoreClass *parent_class = NULL;
|
||||
|
@ -135,7 +137,7 @@ gimp_clone_init (GimpClone *clone)
|
|||
{
|
||||
clone->set_source = FALSE;
|
||||
|
||||
clone->src_drawable = NULL;
|
||||
clone->src_pickable = NULL;
|
||||
clone->src_x = 0.0;
|
||||
clone->src_y = 0.0;
|
||||
|
||||
|
@ -163,11 +165,28 @@ gimp_clone_paint (GimpPaintCore *paint_core,
|
|||
case GIMP_PAINT_STATE_INIT:
|
||||
if (clone->set_source)
|
||||
{
|
||||
gimp_clone_set_src_drawable (clone, drawable);
|
||||
|
||||
clone->src_x = paint_core->cur_coords.x;
|
||||
clone->src_y = paint_core->cur_coords.y;
|
||||
|
||||
if (options->sample_merged)
|
||||
{
|
||||
GimpItem *item = GIMP_ITEM (drawable);
|
||||
GimpImage *gimage = gimp_item_get_image (item);
|
||||
gint off_x, off_y;
|
||||
|
||||
gimp_item_offsets (item, &off_x, &off_y);
|
||||
|
||||
clone->src_x += off_x;
|
||||
clone->src_y += off_y;
|
||||
|
||||
gimp_clone_set_src_pickable (clone,
|
||||
GIMP_PICKABLE (gimage->projection));
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_clone_set_src_pickable (clone, GIMP_PICKABLE (drawable));
|
||||
}
|
||||
|
||||
clone->first_stroke = TRUE;
|
||||
}
|
||||
else if (options->align_mode == GIMP_CLONE_ALIGN_NO)
|
||||
|
@ -191,6 +210,16 @@ gimp_clone_paint (GimpPaintCore *paint_core,
|
|||
clone->src_x = paint_core->cur_coords.x;
|
||||
clone->src_y = paint_core->cur_coords.y;
|
||||
|
||||
if (options->sample_merged)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
clone->src_x += off_x;
|
||||
clone->src_y += off_y;
|
||||
}
|
||||
|
||||
clone->first_stroke = TRUE;
|
||||
}
|
||||
else
|
||||
|
@ -253,7 +282,7 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
gpointer pr = NULL;
|
||||
gint y;
|
||||
gint x1, y1, x2, y2;
|
||||
gint has_alpha = -1;
|
||||
TileManager *src_tiles;
|
||||
PixelRegion srcPR, destPR;
|
||||
GimpPattern *pattern = NULL;
|
||||
gdouble opacity;
|
||||
|
@ -274,14 +303,13 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
/* Make sure we still have a source if we are doing image cloning */
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE)
|
||||
{
|
||||
if (! clone->src_drawable)
|
||||
if (! clone->src_pickable)
|
||||
return;
|
||||
|
||||
if (! (src_gimage = gimp_item_get_image (GIMP_ITEM (clone->src_drawable))))
|
||||
return;
|
||||
src_gimage = gimp_pickable_get_image (clone->src_pickable);
|
||||
|
||||
/* Determine whether the source image has an alpha channel */
|
||||
has_alpha = gimp_drawable_has_alpha (clone->src_drawable);
|
||||
if (! src_gimage)
|
||||
return;
|
||||
}
|
||||
|
||||
area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
|
||||
|
@ -294,14 +322,16 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
/* Set the paint area to transparent */
|
||||
temp_buf_data_clear (area);
|
||||
|
||||
src_tiles = gimp_pickable_get_tiles (clone->src_pickable);
|
||||
|
||||
x1 = CLAMP (area->x + offset_x,
|
||||
0, gimp_item_width (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_width (src_tiles));
|
||||
y1 = CLAMP (area->y + offset_y,
|
||||
0, gimp_item_height (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_height (src_tiles));
|
||||
x2 = CLAMP (area->x + offset_x + area->width,
|
||||
0, gimp_item_width (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_width (src_tiles));
|
||||
y2 = CLAMP (area->y + offset_y + area->height,
|
||||
0, gimp_item_height (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_height (src_tiles));
|
||||
|
||||
if (!(x2 - x1) || !(y2 - y1))
|
||||
return;
|
||||
|
@ -312,9 +342,11 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
* Otherwise, we need a call to get_orig_image to make sure
|
||||
* we get a copy of the unblemished (offset) image
|
||||
*/
|
||||
if (clone->src_drawable != drawable)
|
||||
if (( options->sample_merged && (gimage != src_gimage)) ||
|
||||
(! options->sample_merged && (clone->src_pickable !=
|
||||
(GimpPickable *) drawable)))
|
||||
{
|
||||
pixel_region_init (&srcPR, gimp_drawable_data (clone->src_drawable),
|
||||
pixel_region_init (&srcPR, src_tiles,
|
||||
x1, y1, (x2 - x1), (y2 - y1), FALSE);
|
||||
}
|
||||
else
|
||||
|
@ -322,8 +354,14 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
TempBuf *orig;
|
||||
|
||||
/* get the original image */
|
||||
orig = gimp_paint_core_get_orig_image (paint_core, clone->src_drawable,
|
||||
x1, y1, x2, y2);
|
||||
if (options->sample_merged)
|
||||
orig = gimp_paint_core_get_orig_proj (paint_core,
|
||||
clone->src_pickable,
|
||||
x1, y1, x2, y2);
|
||||
else
|
||||
orig = gimp_paint_core_get_orig_image (paint_core,
|
||||
GIMP_DRAWABLE (clone->src_pickable),
|
||||
x1, y1, x2, y2);
|
||||
|
||||
srcPR.bytes = orig->bytes;
|
||||
srcPR.x = 0;
|
||||
|
@ -381,8 +419,8 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
{
|
||||
case GIMP_IMAGE_CLONE:
|
||||
gimp_clone_line_image (gimage, src_gimage,
|
||||
drawable, clone->src_drawable,
|
||||
s, d, has_alpha,
|
||||
drawable, clone->src_pickable,
|
||||
s, d,
|
||||
srcPR.bytes, destPR.bytes, destPR.w);
|
||||
s += srcPR.rowstride;
|
||||
break;
|
||||
|
@ -415,10 +453,9 @@ static void
|
|||
gimp_clone_line_image (GimpImage *dest,
|
||||
GimpImage *src,
|
||||
GimpDrawable *d_drawable,
|
||||
GimpDrawable *s_drawable,
|
||||
GimpPickable *s_pickable,
|
||||
guchar *s,
|
||||
guchar *d,
|
||||
gint has_alpha,
|
||||
gint src_bytes,
|
||||
gint dest_bytes,
|
||||
gint width)
|
||||
|
@ -430,7 +467,8 @@ gimp_clone_line_image (GimpImage *dest,
|
|||
|
||||
while (width--)
|
||||
{
|
||||
gimp_image_get_color (src, gimp_drawable_type (s_drawable), s, rgba);
|
||||
gimp_image_get_color (src, gimp_pickable_get_image_type (s_pickable),
|
||||
s, rgba);
|
||||
gimp_image_transform_color (dest, d_drawable, d, GIMP_RGB, rgba);
|
||||
|
||||
d[alpha] = rgba[ALPHA_PIX];
|
||||
|
@ -489,33 +527,31 @@ gimp_clone_line_pattern (GimpImage *dest,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_clone_src_drawable_disconnect_cb (GimpDrawable *drawable,
|
||||
gimp_clone_src_pickable_disconnect_cb (GimpPickable *pickable,
|
||||
GimpClone *clone)
|
||||
{
|
||||
if (drawable == clone->src_drawable)
|
||||
if (pickable == clone->src_pickable)
|
||||
{
|
||||
clone->src_drawable = NULL;
|
||||
clone->src_pickable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_clone_set_src_drawable (GimpClone *clone,
|
||||
GimpDrawable *drawable)
|
||||
gimp_clone_set_src_pickable (GimpClone *clone,
|
||||
GimpPickable *pickable)
|
||||
{
|
||||
if (clone->src_drawable == drawable)
|
||||
if (clone->src_pickable == pickable)
|
||||
return;
|
||||
|
||||
if (clone->src_drawable)
|
||||
g_signal_handlers_disconnect_by_func (clone->src_drawable,
|
||||
gimp_clone_src_drawable_disconnect_cb,
|
||||
if (clone->src_pickable)
|
||||
g_signal_handlers_disconnect_by_func (clone->src_pickable,
|
||||
gimp_clone_src_pickable_disconnect_cb,
|
||||
clone);
|
||||
|
||||
clone->src_drawable = drawable;
|
||||
clone->src_pickable = pickable;
|
||||
|
||||
if (clone->src_drawable)
|
||||
{
|
||||
g_signal_connect (clone->src_drawable, "disconnect",
|
||||
G_CALLBACK (gimp_clone_src_drawable_disconnect_cb),
|
||||
clone);
|
||||
}
|
||||
if (clone->src_pickable)
|
||||
g_signal_connect (clone->src_pickable, "disconnect",
|
||||
G_CALLBACK (gimp_clone_src_pickable_disconnect_cb),
|
||||
clone);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ struct _GimpClone
|
|||
|
||||
gboolean set_source;
|
||||
|
||||
GimpDrawable *src_drawable;
|
||||
GimpPickable *src_pickable;
|
||||
gint src_x;
|
||||
gint src_y;
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_CLONE_TYPE,
|
||||
PROP_ALIGN_MODE
|
||||
PROP_ALIGN_MODE,
|
||||
PROP_SAMPLE_MERGED
|
||||
};
|
||||
|
||||
|
||||
|
@ -103,6 +104,10 @@ gimp_clone_options_class_init (GimpCloneOptionsClass *klass)
|
|||
GIMP_TYPE_CLONE_ALIGN_MODE,
|
||||
CLONE_DEFAULT_ALIGN_MODE,
|
||||
0);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SAMPLE_MERGED,
|
||||
"sample-merged", NULL,
|
||||
FALSE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -121,6 +126,9 @@ gimp_clone_options_set_property (GObject *object,
|
|||
case PROP_ALIGN_MODE:
|
||||
options->align_mode = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_SAMPLE_MERGED:
|
||||
options->sample_merged = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -143,6 +151,9 @@ gimp_clone_options_get_property (GObject *object,
|
|||
case PROP_ALIGN_MODE:
|
||||
g_value_set_enum (value, options->align_mode);
|
||||
break;
|
||||
case PROP_SAMPLE_MERGED:
|
||||
g_value_set_boolean (value, options->sample_merged);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct _GimpCloneOptions
|
|||
|
||||
GimpCloneType clone_type;
|
||||
GimpCloneAlignMode align_mode;
|
||||
gboolean sample_merged;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "core/gimpimage.h"
|
||||
#include "core/gimpimage-undo.h"
|
||||
#include "core/gimppaintinfo.h"
|
||||
#include "core/gimppickable.h"
|
||||
|
||||
#include "gimppaintcore.h"
|
||||
#include "gimppaintcore-undo.h"
|
||||
|
@ -144,22 +145,25 @@ gimp_paint_core_class_init (GimpPaintCoreClass *klass)
|
|||
static void
|
||||
gimp_paint_core_init (GimpPaintCore *core)
|
||||
{
|
||||
core->ID = global_core_ID++;
|
||||
core->ID = global_core_ID++;
|
||||
|
||||
core->distance = 0.0;
|
||||
core->pixel_dist = 0.0;
|
||||
core->x1 = 0;
|
||||
core->y1 = 0;
|
||||
core->x2 = 0;
|
||||
core->y2 = 0;
|
||||
core->distance = 0.0;
|
||||
core->pixel_dist = 0.0;
|
||||
core->x1 = 0;
|
||||
core->y1 = 0;
|
||||
core->x2 = 0;
|
||||
core->y2 = 0;
|
||||
|
||||
core->use_pressure = FALSE;
|
||||
core->use_pressure = FALSE;
|
||||
core->use_saved_proj = FALSE;
|
||||
|
||||
core->undo_tiles = NULL;
|
||||
core->canvas_tiles = NULL;
|
||||
core->undo_tiles = NULL;
|
||||
core->saved_proj_tiles = NULL;
|
||||
core->canvas_tiles = NULL;
|
||||
|
||||
core->orig_buf = NULL;
|
||||
core->canvas_buf = NULL;
|
||||
core->orig_buf = NULL;
|
||||
core->orig_proj_buf = NULL;
|
||||
core->canvas_buf = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -299,6 +303,23 @@ gimp_paint_core_start (GimpPaintCore *core,
|
|||
gimp_item_height (item),
|
||||
gimp_drawable_bytes (drawable));
|
||||
|
||||
/* Allocate the saved proj structure */
|
||||
if (core->saved_proj_tiles)
|
||||
tile_manager_unref (core->saved_proj_tiles);
|
||||
|
||||
if (core->use_saved_proj)
|
||||
{
|
||||
GimpPickable *pickable;
|
||||
TileManager *tiles;
|
||||
|
||||
pickable = GIMP_PICKABLE (gimp_item_get_image (item)->projection);
|
||||
tiles = gimp_pickable_get_tiles (pickable);
|
||||
|
||||
core->saved_proj_tiles = tile_manager_new (tile_manager_width (tiles),
|
||||
tile_manager_height (tiles),
|
||||
tile_manager_bpp (tiles));
|
||||
}
|
||||
|
||||
/* Allocate the canvas blocks structure */
|
||||
if (core->canvas_tiles)
|
||||
tile_manager_unref (core->canvas_tiles);
|
||||
|
@ -357,6 +378,12 @@ gimp_paint_core_finish (GimpPaintCore *core,
|
|||
|
||||
gimp_image_undo_group_end (gimage);
|
||||
|
||||
if (core->saved_proj_tiles)
|
||||
{
|
||||
tile_manager_unref (core->saved_proj_tiles);
|
||||
core->saved_proj_tiles = NULL;
|
||||
}
|
||||
|
||||
/* invalidate the previews -- have to do it here, because
|
||||
* it is not done during the actual painting.
|
||||
*/
|
||||
|
@ -418,6 +445,12 @@ gimp_paint_core_cancel (GimpPaintCore *core,
|
|||
tile_manager_unref (core->undo_tiles);
|
||||
core->undo_tiles = NULL;
|
||||
|
||||
if (core->saved_proj_tiles)
|
||||
{
|
||||
tile_manager_unref (core->saved_proj_tiles);
|
||||
core->saved_proj_tiles = NULL;
|
||||
}
|
||||
|
||||
gimp_drawable_update (drawable,
|
||||
core->x1, core->y1,
|
||||
core->x2 - core->x1, core->y2 - core->y1);
|
||||
|
@ -434,6 +467,12 @@ gimp_paint_core_cleanup (GimpPaintCore *core)
|
|||
core->undo_tiles = NULL;
|
||||
}
|
||||
|
||||
if (core->saved_proj_tiles)
|
||||
{
|
||||
tile_manager_unref (core->saved_proj_tiles);
|
||||
core->saved_proj_tiles = NULL;
|
||||
}
|
||||
|
||||
if (core->canvas_tiles)
|
||||
{
|
||||
tile_manager_unref (core->canvas_tiles);
|
||||
|
@ -446,6 +485,12 @@ gimp_paint_core_cleanup (GimpPaintCore *core)
|
|||
core->orig_buf = NULL;
|
||||
}
|
||||
|
||||
if (core->orig_proj_buf)
|
||||
{
|
||||
temp_buf_free (core->orig_proj_buf);
|
||||
core->orig_proj_buf = NULL;
|
||||
}
|
||||
|
||||
if (core->canvas_buf)
|
||||
{
|
||||
temp_buf_free (core->canvas_buf);
|
||||
|
@ -562,11 +607,14 @@ gimp_paint_core_get_orig_image (GimpPaintCore *core,
|
|||
}
|
||||
|
||||
d = destPR.data;
|
||||
|
||||
pixelwidth = srcPR.w * srcPR.bytes;
|
||||
|
||||
h = srcPR.h;
|
||||
while (h --)
|
||||
{
|
||||
memcpy (d, s, pixelwidth);
|
||||
|
||||
s += srcPR.rowstride;
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
|
@ -578,6 +626,105 @@ gimp_paint_core_get_orig_image (GimpPaintCore *core,
|
|||
return core->orig_buf;
|
||||
}
|
||||
|
||||
TempBuf *
|
||||
gimp_paint_core_get_orig_proj (GimpPaintCore *core,
|
||||
GimpPickable *pickable,
|
||||
gint x1,
|
||||
gint y1,
|
||||
gint x2,
|
||||
gint y2)
|
||||
{
|
||||
TileManager *src_tiles;
|
||||
PixelRegion srcPR;
|
||||
PixelRegion destPR;
|
||||
Tile *saved_tile;
|
||||
gboolean release_tile;
|
||||
gint h;
|
||||
gint pixelwidth;
|
||||
gint pickable_width;
|
||||
gint pickable_height;
|
||||
guchar *s;
|
||||
guchar *d;
|
||||
gpointer pr;
|
||||
|
||||
src_tiles = gimp_pickable_get_tiles (pickable);
|
||||
|
||||
core->orig_proj_buf = temp_buf_resize (core->orig_proj_buf,
|
||||
tile_manager_bpp (src_tiles),
|
||||
x1, y1,
|
||||
(x2 - x1), (y2 - y1));
|
||||
|
||||
pickable_width = tile_manager_width (src_tiles);
|
||||
pickable_height = tile_manager_height (src_tiles);
|
||||
|
||||
x1 = CLAMP (x1, 0, pickable_width);
|
||||
y1 = CLAMP (y1, 0, pickable_height);
|
||||
x2 = CLAMP (x2, 0, pickable_width);
|
||||
y2 = CLAMP (y2, 0, pickable_height);
|
||||
|
||||
/* configure the pixel regions */
|
||||
pixel_region_init (&srcPR, src_tiles,
|
||||
x1, y1,
|
||||
(x2 - x1), (y2 - y1),
|
||||
FALSE);
|
||||
|
||||
destPR.bytes = core->orig_proj_buf->bytes;
|
||||
destPR.x = 0;
|
||||
destPR.y = 0;
|
||||
destPR.w = (x2 - x1);
|
||||
destPR.h = (y2 - y1);
|
||||
destPR.rowstride = core->orig_proj_buf->bytes * core->orig_proj_buf->width;
|
||||
destPR.data = (temp_buf_data (core->orig_proj_buf) +
|
||||
(y1 - core->orig_proj_buf->y) * destPR.rowstride +
|
||||
(x1 - core->orig_proj_buf->x) * destPR.bytes);
|
||||
|
||||
for (pr = pixel_regions_register (2, &srcPR, &destPR);
|
||||
pr != NULL;
|
||||
pr = pixel_regions_process (pr))
|
||||
{
|
||||
/* If the saved tile corresponding to this location is valid, use it */
|
||||
saved_tile = tile_manager_get_tile (core->saved_proj_tiles,
|
||||
srcPR.x, srcPR.y,
|
||||
FALSE, FALSE);
|
||||
|
||||
if (tile_is_valid (saved_tile))
|
||||
{
|
||||
release_tile = TRUE;
|
||||
|
||||
saved_tile = tile_manager_get_tile (core->saved_proj_tiles,
|
||||
srcPR.x, srcPR.y,
|
||||
TRUE, FALSE);
|
||||
s = ((guchar *) tile_data_pointer (saved_tile, 0, 0) +
|
||||
srcPR.rowstride * (srcPR.y % TILE_HEIGHT) +
|
||||
srcPR.bytes * (srcPR.x % TILE_WIDTH)); /* dubious... */
|
||||
}
|
||||
else
|
||||
{
|
||||
release_tile = FALSE;
|
||||
|
||||
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 (release_tile)
|
||||
tile_release (saved_tile, FALSE);
|
||||
}
|
||||
|
||||
return core->orig_proj_buf;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_paint_core_paste (GimpPaintCore *core,
|
||||
PixelRegion *paint_maskPR,
|
||||
|
@ -602,6 +749,21 @@ gimp_paint_core_paste (GimpPaintCore *core,
|
|||
core->canvas_buf->width,
|
||||
core->canvas_buf->height);
|
||||
|
||||
if (core->use_saved_proj)
|
||||
{
|
||||
GimpPickable *pickable = GIMP_PICKABLE (gimage->projection);
|
||||
gint off_x;
|
||||
gint off_y;
|
||||
|
||||
gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
gimp_paint_core_validate_saved_proj_tiles (core, pickable,
|
||||
core->canvas_buf->x + off_x,
|
||||
core->canvas_buf->y + off_y,
|
||||
core->canvas_buf->width,
|
||||
core->canvas_buf->height);
|
||||
}
|
||||
|
||||
/* If the mode is CONSTANT:
|
||||
* combine the canvas buf, the paint mask to the canvas tiles
|
||||
*/
|
||||
|
@ -876,6 +1038,51 @@ gimp_paint_core_validate_undo_tiles (GimpPaintCore *core,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
gimp_paint_core_validate_saved_proj_tiles (GimpPaintCore *core,
|
||||
GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h)
|
||||
{
|
||||
gint i;
|
||||
gint j;
|
||||
Tile *src_tile;
|
||||
Tile *dest_tile;
|
||||
|
||||
if (! core->saved_proj_tiles)
|
||||
{
|
||||
g_warning ("set_saved_proj_tiles: saved_proj_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 (core->saved_proj_tiles, j, i,
|
||||
FALSE, FALSE);
|
||||
|
||||
if (! tile_is_valid (dest_tile))
|
||||
{
|
||||
dest_tile = tile_manager_get_tile (core->saved_proj_tiles, j, i,
|
||||
TRUE, TRUE);
|
||||
src_tile = tile_manager_get_tile (gimp_pickable_get_tiles (pickable),
|
||||
j, i, TRUE, FALSE);
|
||||
/* copy the pixels instead of mapping the tile because
|
||||
* copy-on-write from the projection is broken
|
||||
*/
|
||||
memcpy (tile_data_pointer (dest_tile, 0, 0),
|
||||
tile_data_pointer (src_tile, 0, 0),
|
||||
tile_size (src_tile));
|
||||
tile_release (dest_tile, TRUE);
|
||||
tile_release (src_tile, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gimp_paint_core_validate_canvas_tiles (GimpPaintCore *core,
|
||||
gint x,
|
||||
|
|
|
@ -37,28 +37,31 @@ struct _GimpPaintCore
|
|||
{
|
||||
GimpObject parent_instance;
|
||||
|
||||
gint ID; /* unique instance ID */
|
||||
gint ID; /* unique instance ID */
|
||||
|
||||
GimpCoords start_coords; /* starting coords (for undo only) */
|
||||
GimpCoords start_coords; /* starting coords (for undo only) */
|
||||
|
||||
GimpCoords cur_coords; /* current coords */
|
||||
GimpCoords last_coords; /* last coords */
|
||||
GimpCoords cur_coords; /* current coords */
|
||||
GimpCoords last_coords; /* last coords */
|
||||
|
||||
GimpVector2 last_paint; /* last point that was painted */
|
||||
GimpVector2 last_paint; /* last point that was painted */
|
||||
|
||||
gdouble distance; /* distance traveled by brush */
|
||||
gdouble pixel_dist; /* distance in pixels */
|
||||
gdouble distance; /* distance traveled by brush */
|
||||
gdouble pixel_dist; /* distance in pixels */
|
||||
|
||||
gint x1, y1; /* undo extents in image coords */
|
||||
gint x2, y2; /* undo extents in image coords */
|
||||
gint x1, y1; /* undo extents in image coords */
|
||||
gint x2, y2; /* undo extents in image coords */
|
||||
|
||||
gboolean use_pressure; /* look at coords->pressure */
|
||||
gboolean use_pressure; /* look at coords->pressure */
|
||||
gboolean use_saved_proj; /* keep the unmodified proj around */
|
||||
|
||||
TileManager *undo_tiles; /* tiles which have been modified */
|
||||
TileManager *canvas_tiles; /* the buffer to paint the mask to */
|
||||
TileManager *undo_tiles; /* tiles which have been modified */
|
||||
TileManager *saved_proj_tiles; /* proj tiles which have been modified */
|
||||
TileManager *canvas_tiles; /* the buffer to paint the mask to */
|
||||
|
||||
TempBuf *orig_buf; /* the unmodified drawable pixels */
|
||||
TempBuf *canvas_buf; /* the buffer to paint pixels to */
|
||||
TempBuf *orig_buf; /* the unmodified drawable pixels */
|
||||
TempBuf *orig_proj_buf; /* the unmodified projection pixels */
|
||||
TempBuf *canvas_buf; /* the buffer to paint pixels to */
|
||||
|
||||
};
|
||||
|
||||
|
@ -138,6 +141,12 @@ TempBuf * gimp_paint_core_get_orig_image (GimpPaintCore *core,
|
|||
gint y1,
|
||||
gint x2,
|
||||
gint y2);
|
||||
TempBuf * gimp_paint_core_get_orig_proj (GimpPaintCore *core,
|
||||
GimpPickable *pickable,
|
||||
gint x1,
|
||||
gint y1,
|
||||
gint x2,
|
||||
gint y2);
|
||||
|
||||
void gimp_paint_core_paste (GimpPaintCore *core,
|
||||
PixelRegion *paint_maskPR,
|
||||
|
@ -153,17 +162,23 @@ void gimp_paint_core_replace (GimpPaintCore *core,
|
|||
gdouble image_opacity,
|
||||
GimpPaintApplicationMode mode);
|
||||
|
||||
void gimp_paint_core_validate_undo_tiles (GimpPaintCore *core,
|
||||
GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h);
|
||||
void gimp_paint_core_validate_canvas_tiles (GimpPaintCore *core,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h);
|
||||
void gimp_paint_core_validate_undo_tiles (GimpPaintCore *core,
|
||||
GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h);
|
||||
void gimp_paint_core_validate_saved_proj_tiles (GimpPaintCore *core,
|
||||
GimpPickable *pickable,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h);
|
||||
void gimp_paint_core_validate_canvas_tiles (GimpPaintCore *core,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h);
|
||||
|
||||
|
||||
#endif /* __GIMP_PAINT_CORE_H__ */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "base/pixel-region.h"
|
||||
#include "base/temp-buf.h"
|
||||
#include "base/tile-manager.h"
|
||||
|
||||
#include "paint-funcs/paint-funcs.h"
|
||||
|
||||
|
@ -34,6 +35,8 @@
|
|||
#include "core/gimpdrawable.h"
|
||||
#include "core/gimpimage.h"
|
||||
#include "core/gimppattern.h"
|
||||
#include "core/gimppickable.h"
|
||||
#include "core/gimpprojection.h"
|
||||
|
||||
#include "gimpclone.h"
|
||||
#include "gimpcloneoptions.h"
|
||||
|
@ -56,10 +59,9 @@ static void gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
static void gimp_clone_line_image (GimpImage *dest,
|
||||
GimpImage *src,
|
||||
GimpDrawable *d_drawable,
|
||||
GimpDrawable *s_drawable,
|
||||
GimpPickable *s_pickable,
|
||||
guchar *s,
|
||||
guchar *d,
|
||||
gint has_alpha,
|
||||
gint src_bytes,
|
||||
gint dest_bytes,
|
||||
gint width);
|
||||
|
@ -72,8 +74,8 @@ static void gimp_clone_line_pattern (GimpImage *dest,
|
|||
gint bytes,
|
||||
gint width);
|
||||
|
||||
static void gimp_clone_set_src_drawable (GimpClone *clone,
|
||||
GimpDrawable *drawable);
|
||||
static void gimp_clone_set_src_pickable (GimpClone *clone,
|
||||
GimpPickable *pickable);
|
||||
|
||||
|
||||
static GimpBrushCoreClass *parent_class = NULL;
|
||||
|
@ -135,7 +137,7 @@ gimp_clone_init (GimpClone *clone)
|
|||
{
|
||||
clone->set_source = FALSE;
|
||||
|
||||
clone->src_drawable = NULL;
|
||||
clone->src_pickable = NULL;
|
||||
clone->src_x = 0.0;
|
||||
clone->src_y = 0.0;
|
||||
|
||||
|
@ -163,11 +165,28 @@ gimp_clone_paint (GimpPaintCore *paint_core,
|
|||
case GIMP_PAINT_STATE_INIT:
|
||||
if (clone->set_source)
|
||||
{
|
||||
gimp_clone_set_src_drawable (clone, drawable);
|
||||
|
||||
clone->src_x = paint_core->cur_coords.x;
|
||||
clone->src_y = paint_core->cur_coords.y;
|
||||
|
||||
if (options->sample_merged)
|
||||
{
|
||||
GimpItem *item = GIMP_ITEM (drawable);
|
||||
GimpImage *gimage = gimp_item_get_image (item);
|
||||
gint off_x, off_y;
|
||||
|
||||
gimp_item_offsets (item, &off_x, &off_y);
|
||||
|
||||
clone->src_x += off_x;
|
||||
clone->src_y += off_y;
|
||||
|
||||
gimp_clone_set_src_pickable (clone,
|
||||
GIMP_PICKABLE (gimage->projection));
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_clone_set_src_pickable (clone, GIMP_PICKABLE (drawable));
|
||||
}
|
||||
|
||||
clone->first_stroke = TRUE;
|
||||
}
|
||||
else if (options->align_mode == GIMP_CLONE_ALIGN_NO)
|
||||
|
@ -191,6 +210,16 @@ gimp_clone_paint (GimpPaintCore *paint_core,
|
|||
clone->src_x = paint_core->cur_coords.x;
|
||||
clone->src_y = paint_core->cur_coords.y;
|
||||
|
||||
if (options->sample_merged)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
clone->src_x += off_x;
|
||||
clone->src_y += off_y;
|
||||
}
|
||||
|
||||
clone->first_stroke = TRUE;
|
||||
}
|
||||
else
|
||||
|
@ -253,7 +282,7 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
gpointer pr = NULL;
|
||||
gint y;
|
||||
gint x1, y1, x2, y2;
|
||||
gint has_alpha = -1;
|
||||
TileManager *src_tiles;
|
||||
PixelRegion srcPR, destPR;
|
||||
GimpPattern *pattern = NULL;
|
||||
gdouble opacity;
|
||||
|
@ -274,14 +303,13 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
/* Make sure we still have a source if we are doing image cloning */
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE)
|
||||
{
|
||||
if (! clone->src_drawable)
|
||||
if (! clone->src_pickable)
|
||||
return;
|
||||
|
||||
if (! (src_gimage = gimp_item_get_image (GIMP_ITEM (clone->src_drawable))))
|
||||
return;
|
||||
src_gimage = gimp_pickable_get_image (clone->src_pickable);
|
||||
|
||||
/* Determine whether the source image has an alpha channel */
|
||||
has_alpha = gimp_drawable_has_alpha (clone->src_drawable);
|
||||
if (! src_gimage)
|
||||
return;
|
||||
}
|
||||
|
||||
area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
|
||||
|
@ -294,14 +322,16 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
/* Set the paint area to transparent */
|
||||
temp_buf_data_clear (area);
|
||||
|
||||
src_tiles = gimp_pickable_get_tiles (clone->src_pickable);
|
||||
|
||||
x1 = CLAMP (area->x + offset_x,
|
||||
0, gimp_item_width (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_width (src_tiles));
|
||||
y1 = CLAMP (area->y + offset_y,
|
||||
0, gimp_item_height (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_height (src_tiles));
|
||||
x2 = CLAMP (area->x + offset_x + area->width,
|
||||
0, gimp_item_width (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_width (src_tiles));
|
||||
y2 = CLAMP (area->y + offset_y + area->height,
|
||||
0, gimp_item_height (GIMP_ITEM (clone->src_drawable)));
|
||||
0, tile_manager_height (src_tiles));
|
||||
|
||||
if (!(x2 - x1) || !(y2 - y1))
|
||||
return;
|
||||
|
@ -312,9 +342,11 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
* Otherwise, we need a call to get_orig_image to make sure
|
||||
* we get a copy of the unblemished (offset) image
|
||||
*/
|
||||
if (clone->src_drawable != drawable)
|
||||
if (( options->sample_merged && (gimage != src_gimage)) ||
|
||||
(! options->sample_merged && (clone->src_pickable !=
|
||||
(GimpPickable *) drawable)))
|
||||
{
|
||||
pixel_region_init (&srcPR, gimp_drawable_data (clone->src_drawable),
|
||||
pixel_region_init (&srcPR, src_tiles,
|
||||
x1, y1, (x2 - x1), (y2 - y1), FALSE);
|
||||
}
|
||||
else
|
||||
|
@ -322,8 +354,14 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
TempBuf *orig;
|
||||
|
||||
/* get the original image */
|
||||
orig = gimp_paint_core_get_orig_image (paint_core, clone->src_drawable,
|
||||
x1, y1, x2, y2);
|
||||
if (options->sample_merged)
|
||||
orig = gimp_paint_core_get_orig_proj (paint_core,
|
||||
clone->src_pickable,
|
||||
x1, y1, x2, y2);
|
||||
else
|
||||
orig = gimp_paint_core_get_orig_image (paint_core,
|
||||
GIMP_DRAWABLE (clone->src_pickable),
|
||||
x1, y1, x2, y2);
|
||||
|
||||
srcPR.bytes = orig->bytes;
|
||||
srcPR.x = 0;
|
||||
|
@ -381,8 +419,8 @@ gimp_clone_motion (GimpPaintCore *paint_core,
|
|||
{
|
||||
case GIMP_IMAGE_CLONE:
|
||||
gimp_clone_line_image (gimage, src_gimage,
|
||||
drawable, clone->src_drawable,
|
||||
s, d, has_alpha,
|
||||
drawable, clone->src_pickable,
|
||||
s, d,
|
||||
srcPR.bytes, destPR.bytes, destPR.w);
|
||||
s += srcPR.rowstride;
|
||||
break;
|
||||
|
@ -415,10 +453,9 @@ static void
|
|||
gimp_clone_line_image (GimpImage *dest,
|
||||
GimpImage *src,
|
||||
GimpDrawable *d_drawable,
|
||||
GimpDrawable *s_drawable,
|
||||
GimpPickable *s_pickable,
|
||||
guchar *s,
|
||||
guchar *d,
|
||||
gint has_alpha,
|
||||
gint src_bytes,
|
||||
gint dest_bytes,
|
||||
gint width)
|
||||
|
@ -430,7 +467,8 @@ gimp_clone_line_image (GimpImage *dest,
|
|||
|
||||
while (width--)
|
||||
{
|
||||
gimp_image_get_color (src, gimp_drawable_type (s_drawable), s, rgba);
|
||||
gimp_image_get_color (src, gimp_pickable_get_image_type (s_pickable),
|
||||
s, rgba);
|
||||
gimp_image_transform_color (dest, d_drawable, d, GIMP_RGB, rgba);
|
||||
|
||||
d[alpha] = rgba[ALPHA_PIX];
|
||||
|
@ -489,33 +527,31 @@ gimp_clone_line_pattern (GimpImage *dest,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_clone_src_drawable_disconnect_cb (GimpDrawable *drawable,
|
||||
gimp_clone_src_pickable_disconnect_cb (GimpPickable *pickable,
|
||||
GimpClone *clone)
|
||||
{
|
||||
if (drawable == clone->src_drawable)
|
||||
if (pickable == clone->src_pickable)
|
||||
{
|
||||
clone->src_drawable = NULL;
|
||||
clone->src_pickable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_clone_set_src_drawable (GimpClone *clone,
|
||||
GimpDrawable *drawable)
|
||||
gimp_clone_set_src_pickable (GimpClone *clone,
|
||||
GimpPickable *pickable)
|
||||
{
|
||||
if (clone->src_drawable == drawable)
|
||||
if (clone->src_pickable == pickable)
|
||||
return;
|
||||
|
||||
if (clone->src_drawable)
|
||||
g_signal_handlers_disconnect_by_func (clone->src_drawable,
|
||||
gimp_clone_src_drawable_disconnect_cb,
|
||||
if (clone->src_pickable)
|
||||
g_signal_handlers_disconnect_by_func (clone->src_pickable,
|
||||
gimp_clone_src_pickable_disconnect_cb,
|
||||
clone);
|
||||
|
||||
clone->src_drawable = drawable;
|
||||
clone->src_pickable = pickable;
|
||||
|
||||
if (clone->src_drawable)
|
||||
{
|
||||
g_signal_connect (clone->src_drawable, "disconnect",
|
||||
G_CALLBACK (gimp_clone_src_drawable_disconnect_cb),
|
||||
clone);
|
||||
}
|
||||
if (clone->src_pickable)
|
||||
g_signal_connect (clone->src_pickable, "disconnect",
|
||||
G_CALLBACK (gimp_clone_src_pickable_disconnect_cb),
|
||||
clone);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ struct _GimpClone
|
|||
|
||||
gboolean set_source;
|
||||
|
||||
GimpDrawable *src_drawable;
|
||||
GimpPickable *src_pickable;
|
||||
gint src_x;
|
||||
gint src_y;
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_CLONE_TYPE,
|
||||
PROP_ALIGN_MODE
|
||||
PROP_ALIGN_MODE,
|
||||
PROP_SAMPLE_MERGED
|
||||
};
|
||||
|
||||
|
||||
|
@ -103,6 +104,10 @@ gimp_clone_options_class_init (GimpCloneOptionsClass *klass)
|
|||
GIMP_TYPE_CLONE_ALIGN_MODE,
|
||||
CLONE_DEFAULT_ALIGN_MODE,
|
||||
0);
|
||||
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SAMPLE_MERGED,
|
||||
"sample-merged", NULL,
|
||||
FALSE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -121,6 +126,9 @@ gimp_clone_options_set_property (GObject *object,
|
|||
case PROP_ALIGN_MODE:
|
||||
options->align_mode = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_SAMPLE_MERGED:
|
||||
options->sample_merged = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -143,6 +151,9 @@ gimp_clone_options_get_property (GObject *object,
|
|||
case PROP_ALIGN_MODE:
|
||||
g_value_set_enum (value, options->align_mode);
|
||||
break;
|
||||
case PROP_SAMPLE_MERGED:
|
||||
g_value_set_boolean (value, options->sample_merged);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct _GimpCloneOptions
|
|||
|
||||
GimpCloneType clone_type;
|
||||
GimpCloneAlignMode align_mode;
|
||||
gboolean sample_merged;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -160,8 +160,13 @@ gimp_clone_tool_button_press (GimpTool *tool,
|
|||
GdkModifierType state,
|
||||
GimpDisplay *gdisp)
|
||||
{
|
||||
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
|
||||
GimpCloneTool *clone_tool = GIMP_CLONE_TOOL (tool);
|
||||
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
|
||||
GimpCloneTool *clone_tool = GIMP_CLONE_TOOL (tool);
|
||||
GimpCloneOptions *options;
|
||||
|
||||
options = GIMP_CLONE_OPTIONS (tool->tool_info->tool_options);
|
||||
|
||||
paint_tool->core->use_saved_proj = FALSE;
|
||||
|
||||
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
|
||||
{
|
||||
|
@ -181,6 +186,13 @@ gimp_clone_tool_button_press (GimpTool *tool,
|
|||
else
|
||||
{
|
||||
GIMP_CLONE (paint_tool->core)->set_source = FALSE;
|
||||
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE &&
|
||||
options->sample_merged &&
|
||||
gdisp == clone_tool->src_gdisp)
|
||||
{
|
||||
paint_tool->core->use_saved_proj = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
||||
|
@ -232,7 +244,7 @@ gimp_clone_tool_cursor_update (GimpTool *tool,
|
|||
{
|
||||
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
|
||||
ctype = GIMP_CURSOR_CROSSHAIR_SMALL;
|
||||
else if (! GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_drawable)
|
||||
else if (! GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_pickable)
|
||||
ctype = GIMP_CURSOR_BAD;
|
||||
}
|
||||
|
||||
|
@ -252,7 +264,7 @@ gimp_clone_tool_oper_update (GimpTool *tool,
|
|||
GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, gdisp);
|
||||
|
||||
if (GIMP_CLONE_OPTIONS (options)->clone_type == GIMP_IMAGE_CLONE &&
|
||||
GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_drawable == NULL)
|
||||
GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_pickable == NULL)
|
||||
{
|
||||
gimp_tool_replace_status (tool, gdisp,
|
||||
_("Ctrl-Click to set a clone source."));
|
||||
|
@ -271,14 +283,15 @@ gimp_clone_tool_draw (GimpDrawTool *draw_tool)
|
|||
|
||||
options = (GimpCloneOptions *) tool->tool_info->tool_options;
|
||||
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE && clone->src_drawable)
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE && clone->src_pickable)
|
||||
{
|
||||
gint off_x;
|
||||
gint off_y;
|
||||
gint off_x = 0;
|
||||
gint off_y = 0;
|
||||
GimpDisplay *tmp_gdisp;
|
||||
GimpCloneTool *clone_tool = GIMP_CLONE_TOOL (draw_tool);
|
||||
|
||||
gimp_item_offsets (GIMP_ITEM (clone->src_drawable), &off_x, &off_y);
|
||||
if (GIMP_IS_DRAWABLE (clone->src_pickable))
|
||||
gimp_item_offsets (GIMP_ITEM (clone->src_pickable), &off_x, &off_y);
|
||||
|
||||
tmp_gdisp = draw_tool->gdisp;
|
||||
draw_tool->gdisp = clone_tool->src_gdisp;
|
||||
|
@ -309,6 +322,7 @@ gimp_clone_options_gui (GimpToolOptions *tool_options)
|
|||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
|
||||
vbox = gimp_paint_options_gui (tool_options);
|
||||
|
||||
|
@ -327,5 +341,10 @@ gimp_clone_options_gui (GimpToolOptions *tool_options)
|
|||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
button = gimp_prop_check_button_new (config, "sample-merged",
|
||||
_("Sample Merged"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_show (button);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
|
|
@ -160,8 +160,13 @@ gimp_clone_tool_button_press (GimpTool *tool,
|
|||
GdkModifierType state,
|
||||
GimpDisplay *gdisp)
|
||||
{
|
||||
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
|
||||
GimpCloneTool *clone_tool = GIMP_CLONE_TOOL (tool);
|
||||
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
|
||||
GimpCloneTool *clone_tool = GIMP_CLONE_TOOL (tool);
|
||||
GimpCloneOptions *options;
|
||||
|
||||
options = GIMP_CLONE_OPTIONS (tool->tool_info->tool_options);
|
||||
|
||||
paint_tool->core->use_saved_proj = FALSE;
|
||||
|
||||
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
|
||||
{
|
||||
|
@ -181,6 +186,13 @@ gimp_clone_tool_button_press (GimpTool *tool,
|
|||
else
|
||||
{
|
||||
GIMP_CLONE (paint_tool->core)->set_source = FALSE;
|
||||
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE &&
|
||||
options->sample_merged &&
|
||||
gdisp == clone_tool->src_gdisp)
|
||||
{
|
||||
paint_tool->core->use_saved_proj = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
||||
|
@ -232,7 +244,7 @@ gimp_clone_tool_cursor_update (GimpTool *tool,
|
|||
{
|
||||
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
|
||||
ctype = GIMP_CURSOR_CROSSHAIR_SMALL;
|
||||
else if (! GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_drawable)
|
||||
else if (! GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_pickable)
|
||||
ctype = GIMP_CURSOR_BAD;
|
||||
}
|
||||
|
||||
|
@ -252,7 +264,7 @@ gimp_clone_tool_oper_update (GimpTool *tool,
|
|||
GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, gdisp);
|
||||
|
||||
if (GIMP_CLONE_OPTIONS (options)->clone_type == GIMP_IMAGE_CLONE &&
|
||||
GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_drawable == NULL)
|
||||
GIMP_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_pickable == NULL)
|
||||
{
|
||||
gimp_tool_replace_status (tool, gdisp,
|
||||
_("Ctrl-Click to set a clone source."));
|
||||
|
@ -271,14 +283,15 @@ gimp_clone_tool_draw (GimpDrawTool *draw_tool)
|
|||
|
||||
options = (GimpCloneOptions *) tool->tool_info->tool_options;
|
||||
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE && clone->src_drawable)
|
||||
if (options->clone_type == GIMP_IMAGE_CLONE && clone->src_pickable)
|
||||
{
|
||||
gint off_x;
|
||||
gint off_y;
|
||||
gint off_x = 0;
|
||||
gint off_y = 0;
|
||||
GimpDisplay *tmp_gdisp;
|
||||
GimpCloneTool *clone_tool = GIMP_CLONE_TOOL (draw_tool);
|
||||
|
||||
gimp_item_offsets (GIMP_ITEM (clone->src_drawable), &off_x, &off_y);
|
||||
if (GIMP_IS_DRAWABLE (clone->src_pickable))
|
||||
gimp_item_offsets (GIMP_ITEM (clone->src_pickable), &off_x, &off_y);
|
||||
|
||||
tmp_gdisp = draw_tool->gdisp;
|
||||
draw_tool->gdisp = clone_tool->src_gdisp;
|
||||
|
@ -309,6 +322,7 @@ gimp_clone_options_gui (GimpToolOptions *tool_options)
|
|||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
|
||||
vbox = gimp_paint_options_gui (tool_options);
|
||||
|
||||
|
@ -327,5 +341,10 @@ gimp_clone_options_gui (GimpToolOptions *tool_options)
|
|||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
button = gimp_prop_check_button_new (config, "sample-merged",
|
||||
_("Sample Merged"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_show (button);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue