Merged the "soc-2006-perspective-clone" branch. That branch is now

2006-09-07  Michael Natterer  <mitch@gimp.org>

	Merged the "soc-2006-perspective-clone" 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 GimpBrushTool and renamed the enum
	added to paint-enums.h and it values, added stock icon and menu
	entry.

	Thanks a lot to Pedro Alonso Ferrer!

	* app/paint/paint-enums.[ch]: new enum GimpPerspectiveCloneMode.

	* app/paint/Makefile.am
	* app/paint/gimpperspectiveclone.[ch]
	* app/paint/gimpperspectivecloneoptions.[ch]: the perspective
	clone core and its options.

	* app/paint/gimp-paint.c: register it.

	* app/tools/Makefile.am
	* app/tools/gimpperspectiveclonetool.[ch]: the perspective clone tool.

	* app/tools/gimp-tools.c: register it.

	* app/tools/gimppaintoptions-gui.c: show the widgets that are used
	by perspective clone.

	* app/widgets/gimphelp-ids.h: the help ID.

	* themes/Default/images/Makefile.am
	* themes/Default/images/tools/stock-tool-perspective-clone-16.png
	* themes/Default/images/tools/stock-tool-perspective-clone-22.png
	* libgimpwidgets/gimpstock.[ch]: its stock ID and icons.

	* menus/image-menu.xml.in: added it to the menu.
This commit is contained in:
Michael Natterer 2006-09-07 17:10:22 +00:00 committed by Michael Natterer
parent 57b4858352
commit 1b1497657a
21 changed files with 2267 additions and 76 deletions

View File

@ -1,3 +1,42 @@
2006-09-07 Michael Natterer <mitch@gimp.org>
Merged the "soc-2006-perspective-clone" 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 GimpBrushTool and renamed the enum
added to paint-enums.h and it values, added stock icon and menu
entry.
Thanks a lot to Pedro Alonso Ferrer!
* app/paint/paint-enums.[ch]: new enum GimpPerspectiveCloneMode.
* app/paint/Makefile.am
* app/paint/gimpperspectiveclone.[ch]
* app/paint/gimpperspectivecloneoptions.[ch]: the perspective
clone core and its options.
* app/paint/gimp-paint.c: register it.
* app/tools/Makefile.am
* app/tools/gimpperspectiveclonetool.[ch]: the perspective clone tool.
* app/tools/gimp-tools.c: register it.
* app/tools/gimppaintoptions-gui.c: show the widgets that are used
by perspective clone.
* app/widgets/gimphelp-ids.h: the help ID.
* themes/Default/images/Makefile.am
* themes/Default/images/tools/stock-tool-perspective-clone-16.png
* themes/Default/images/tools/stock-tool-perspective-clone-22.png
* libgimpwidgets/gimpstock.[ch]: its stock ID and icons.
* menus/image-menu.xml.in: added it to the menu.
2006-09-07 Sven Neumann <sven@gimp.org>
* configure.in: bumped version to 2.3.12.

View File

@ -15,64 +15,68 @@ INCLUDES = \
noinst_LIBRARIES = libapppaint.a
libapppaint_a_sources = \
paint-enums.h \
paint-types.h \
gimp-paint.c \
gimp-paint.h \
gimpairbrush.c \
gimpairbrush.h \
gimpairbrushoptions.c \
gimpairbrushoptions.h \
gimpbrushcore.c \
gimpbrushcore.h \
gimpbrushcore-kernels.h \
gimpclone.c \
gimpclone.h \
gimpcloneoptions.c \
gimpcloneoptions.h \
gimpconvolve.c \
gimpconvolve.h \
gimpconvolveoptions.c \
gimpconvolveoptions.h \
gimpdodgeburn.c \
gimpdodgeburn.h \
gimpdodgeburnoptions.c \
gimpdodgeburnoptions.h \
gimperaser.c \
gimperaser.h \
gimperaseroptions.c \
gimperaseroptions.h \
gimpheal.c \
gimpheal.h \
gimpink.c \
gimpink.h \
gimpink-blob.c \
gimpink-blob.h \
gimpink-undo.c \
gimpink-undo.h \
gimpinkoptions.c \
gimpinkoptions.h \
gimppaintcore.c \
gimppaintcore.h \
gimppaintcore-stroke.c \
gimppaintcore-stroke.h \
gimppaintcore-undo.c \
gimppaintcore-undo.h \
gimppaintoptions.c \
gimppaintoptions.h \
gimppencil.c \
gimppencil.h \
gimppenciloptions.c \
gimppenciloptions.h \
gimppaintbrush.c \
gimppaintbrush.h \
gimpsmudge.c \
gimpsmudge.h \
gimpsmudgeoptions.c \
gimpsmudgeoptions.h \
gimpsourcecore.c \
gimpsourcecore.h \
gimpsourceoptions.c \
paint-enums.h \
paint-types.h \
gimp-paint.c \
gimp-paint.h \
gimpairbrush.c \
gimpairbrush.h \
gimpairbrushoptions.c \
gimpairbrushoptions.h \
gimpbrushcore.c \
gimpbrushcore.h \
gimpbrushcore-kernels.h \
gimpclone.c \
gimpclone.h \
gimpcloneoptions.c \
gimpcloneoptions.h \
gimpconvolve.c \
gimpconvolve.h \
gimpconvolveoptions.c \
gimpconvolveoptions.h \
gimpdodgeburn.c \
gimpdodgeburn.h \
gimpdodgeburnoptions.c \
gimpdodgeburnoptions.h \
gimperaser.c \
gimperaser.h \
gimperaseroptions.c \
gimperaseroptions.h \
gimpheal.c \
gimpheal.h \
gimpink.c \
gimpink.h \
gimpink-blob.c \
gimpink-blob.h \
gimpink-undo.c \
gimpink-undo.h \
gimpinkoptions.c \
gimpinkoptions.h \
gimppaintcore.c \
gimppaintcore.h \
gimppaintcore-stroke.c \
gimppaintcore-stroke.h \
gimppaintcore-undo.c \
gimppaintcore-undo.h \
gimppaintoptions.c \
gimppaintoptions.h \
gimppencil.c \
gimppencil.h \
gimppenciloptions.c \
gimppenciloptions.h \
gimppaintbrush.c \
gimppaintbrush.h \
gimpperspectiveclone.c \
gimpperspectiveclone.h \
gimpperspectivecloneoptions.c \
gimpperspectivecloneoptions.h \
gimpsmudge.c \
gimpsmudge.h \
gimpsmudgeoptions.c \
gimpsmudgeoptions.h \
gimpsourcecore.c \
gimpsourcecore.h \
gimpsourceoptions.c \
gimpsourceoptions.h
libapppaint_a_built_sources = paint-enums.c

View File

@ -37,6 +37,7 @@
#include "gimppaintoptions.h"
#include "gimppaintbrush.h"
#include "gimppencil.h"
#include "gimpperspectiveclone.h"
#include "gimpsmudge.h"
@ -60,8 +61,9 @@ gimp_paint_init (Gimp *gimp)
gimp_dodge_burn_register,
gimp_smudge_register,
gimp_convolve_register,
gimp_clone_register,
gimp_perspective_clone_register,
gimp_heal_register,
gimp_clone_register,
gimp_ink_register,
gimp_airbrush_register,
gimp_eraser_register,

View File

@ -0,0 +1,775 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <glib-object.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpmath/gimpmatrix.h"
#include "paint-types.h"
#include "base/pixel-region.h"
#include "base/temp-buf.h"
#include "base/tile-manager.h"
#include "paint-funcs/paint-funcs.h"
#include "core/gimp.h"
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
#include "core/gimppattern.h"
#include "core/gimppickable.h"
#include "gimpperspectiveclone.h"
#include "gimpperspectivecloneoptions.h"
#include "gimp-intl.h"
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))
enum
{
PROP_0,
PROP_SRC_DRAWABLE,
PROP_SRC_X,
PROP_SRC_Y
};
static void gimp_perspective_clone_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_perspective_clone_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_perspective_clone_paint (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpPaintState paint_state,
guint32 time);
static void gimp_perspective_clone_motion (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options);
static void gimp_perspective_clone_line_image (GimpImage *dest,
GimpImage *src,
GimpDrawable *d_drawable,
GimpPickable *s_pickable,
guchar *s,
guchar *d,
gint src_bytes,
gint dest_bytes,
gint width);
static void gimp_perspective_clone_line_pattern (GimpImage *dest,
GimpDrawable *drawable,
GimpPattern *pattern,
guchar *d,
gint x,
gint y,
gint bytes,
gint width);
static void gimp_perspective_clone_set_src_drawable (GimpPerspectiveClone *clone,
GimpDrawable *drawable);
G_DEFINE_TYPE (GimpPerspectiveClone, gimp_perspective_clone,
GIMP_TYPE_BRUSH_CORE)
void
gimp_perspective_clone_register (Gimp *gimp,
GimpPaintRegisterCallback callback)
{
(* callback) (gimp,
GIMP_TYPE_PERSPECTIVE_CLONE,
GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS,
"gimp-perspective-clone",
_("PerspectiveClone"),
"gimp-tool-perspective-clone");
}
static void
gimp_perspective_clone_class_init (GimpPerspectiveCloneClass *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_perspective_clone_set_property;
object_class->get_property = gimp_perspective_clone_get_property;
paint_core_class->paint = gimp_perspective_clone_paint;
brush_core_class->handles_changing_brush = TRUE;
g_object_class_install_property (object_class, PROP_SRC_DRAWABLE,
g_param_spec_object ("src-drawable",
NULL, NULL,
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_SRC_X,
g_param_spec_double ("src-x", NULL, NULL,
0, GIMP_MAX_IMAGE_SIZE,
0.0,
GIMP_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_SRC_Y,
g_param_spec_double ("src-y", NULL, NULL,
0, GIMP_MAX_IMAGE_SIZE,
0.0,
GIMP_PARAM_READWRITE));
}
static void
gimp_perspective_clone_init (GimpPerspectiveClone *clone)
{
clone->set_source = FALSE;
clone->src_drawable = NULL;
clone->src_x = 0.0;
clone->src_y = 0.0;
clone->orig_src_x = 0.0;
clone->orig_src_y = 0.0;
clone->dest_x = 0.0; /* coords where the stroke starts */
clone->dest_y = 0.0;
clone->src_x_fv = 0.0; /* source coords in front_view perspective */
clone->src_y_fv = 0.0;
clone->dest_x_fv = 0.0; /* destination coords in front_view perspective */
clone->dest_y_fv = 0.0;
clone->offset_x = 0.0; /* offset from the source to the stroke that's being painted */
clone->offset_y = 0.0;
clone->first_stroke = TRUE;
gimp_matrix3_identity (&clone->transform);
gimp_matrix3_identity (&clone->transform_inv);
}
static void
gimp_perspective_clone_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (object);
switch (property_id)
{
case PROP_SRC_DRAWABLE:
gimp_perspective_clone_set_src_drawable (clone, g_value_get_object (value));
break;
case PROP_SRC_X:
clone->src_x = g_value_get_double (value);
break;
case PROP_SRC_Y:
clone->src_y = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_perspective_clone_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (object);
switch (property_id)
{
case PROP_SRC_DRAWABLE:
g_value_set_object (value, clone->src_drawable);
break;
case PROP_SRC_X:
g_value_set_int (value, clone->src_x);
break;
case PROP_SRC_Y:
g_value_set_int (value, clone->src_y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_perspective_clone_paint (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options,
GimpPaintState paint_state,
guint32 time)
{
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (paint_core);
GimpPerspectiveCloneOptions *options = GIMP_PERSPECTIVE_CLONE_OPTIONS (paint_options);
GimpContext *context = GIMP_CONTEXT (paint_options);
switch (paint_state)
{
case GIMP_PAINT_STATE_INIT:
if (clone->set_source)
{
gimp_perspective_clone_set_src_drawable (clone, drawable);
clone->src_x = paint_core->cur_coords.x;
clone->src_y = paint_core->cur_coords.y;
/* get source coordinates in front view perspective */
gimp_matrix3_transform_point (&clone->transform_inv,
clone->src_x, clone->src_y,
&clone->src_x_fv, &clone->src_y_fv);
clone->first_stroke = TRUE;
}
else if (options->align_mode == GIMP_SOURCE_ALIGN_NO)
{
clone->orig_src_x = clone->src_x;
clone->orig_src_y = clone->src_y;
clone->first_stroke = TRUE;
}
if (options->clone_type == GIMP_PATTERN_CLONE)
if (! gimp_context_get_pattern (context))
g_message (_("No patterns available for this operation."));
break;
case GIMP_PAINT_STATE_MOTION:
if (clone->set_source)
{
/* If the control key is down, move the src target and return */
clone->src_x = paint_core->cur_coords.x; /* coords where the stroke starts */
clone->src_y = paint_core->cur_coords.y;
/* get source coordinates in front view perspective */
gimp_matrix3_transform_point (&clone->transform_inv,
clone->src_x, clone->src_y,
&clone->src_x_fv, &clone->src_y_fv);
clone->first_stroke = TRUE;
}
else
{
/* otherwise, update the target */
gint dest_x;
gint dest_y;
dest_x = paint_core->cur_coords.x;
dest_y = paint_core->cur_coords.y;
if (options->align_mode == GIMP_SOURCE_ALIGN_REGISTERED)
{
clone->offset_x = 0;
clone->offset_y = 0;
}
else if (options->align_mode == GIMP_SOURCE_ALIGN_FIXED)
{
clone->offset_x = clone->src_x - dest_x;
clone->offset_y = clone->src_y - dest_y;
}
else if (clone->first_stroke)
{
clone->offset_x = clone->src_x - dest_x;
clone->offset_y = clone->src_y - dest_y;
clone->dest_x = dest_x; /* cooords where start the destination stroke */
clone->dest_y = dest_y;
/* get destination coordinates in front view perspective */
gimp_matrix3_transform_point (&clone->transform_inv,
clone->dest_x, clone->dest_y,
&clone->dest_x_fv, &clone->dest_y_fv);
clone->first_stroke = FALSE;
}
gimp_perspective_clone_motion (paint_core, drawable, paint_options);
}
break;
case GIMP_PAINT_STATE_FINISH:
break;
default:
break;
}
g_object_notify (G_OBJECT (clone), "src-x");
g_object_notify (G_OBJECT (clone), "src-y");
}
static void
gimp_perspective_clone_motion (GimpPaintCore *paint_core,
GimpDrawable *drawable,
GimpPaintOptions *paint_options)
{
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (paint_core);
GimpPerspectiveCloneOptions *options = GIMP_PERSPECTIVE_CLONE_OPTIONS (paint_options);
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpImage *image;
GimpImage *src_image = NULL;
GimpPickable *src_pickable = NULL;
guchar *s;
guchar *d;
TempBuf *area;
gpointer pr = NULL;
gint y;
gint x1d, y1d, x2d, y2d; /* Coordinates of the destination area to paint */
gdouble x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s; /* Coordinates of the boundary box to copy pixels to the tempbuf and after apply perspective transform */
gint itemp_x, itemp_y;
gint xmin, ymin, xmax, ymax;
TileManager *src_tiles;
PixelRegion srcPR, destPR, auxPR, auxPR2;
GimpPattern *pattern = NULL;
gdouble opacity;
gint offset_x;
gint offset_y;
guchar *src_data;
guchar *dest_data;
gint i, j;
gdouble temp_x, temp_y;
image = gimp_item_get_image (GIMP_ITEM (drawable));
opacity = gimp_paint_options_get_fade (paint_options, image,
paint_core->pixel_dist);
if (opacity == 0.0)
return;
/* make local copies because we change them */
offset_x = clone->offset_x;
offset_y = clone->offset_y;
/* Make sure we still have a source if we are doing image cloning */
if (options->clone_type == GIMP_IMAGE_CLONE)
{
if (! clone->src_drawable)
return;
src_pickable = GIMP_PICKABLE (clone->src_drawable);
src_image = gimp_pickable_get_image (src_pickable);
if (options->sample_merged)
{
gint off_x, off_y;
src_pickable = GIMP_PICKABLE (src_image->projection);
/* To the offset of the layer add the offset of the layer respect the entire image*/
gimp_item_offsets (GIMP_ITEM (clone->src_drawable), &off_x, &off_y);
// May I delete this offset, which is it function???
offset_x += off_x;
offset_y += off_y;
}
gimp_pickable_flush (src_pickable);
}
area = gimp_paint_core_get_paint_area (paint_core, drawable, paint_options);
if (! area)
return;
switch (options->clone_type)
{
TempBuf *orig, *temp_buf;
case GIMP_IMAGE_CLONE:
/* Set the paint area to transparent */
temp_buf_data_clear (area);
src_tiles = gimp_pickable_get_tiles (src_pickable);
/* Destination coordinates that will be painted */
x1d = CLAMP (area->x,
0, tile_manager_width (src_tiles));
y1d = CLAMP (area->y,
0, tile_manager_height (src_tiles));
x2d = CLAMP (area->x + area->width,
0, tile_manager_width (src_tiles));
y2d = CLAMP (area->y + area->height,
0, tile_manager_height (src_tiles));
/* Boundary box for source pixels to copy:
* Convert all the vertex of the box to paint in destination area to its correspondent in source area bearing in mind perspective
*/
gimp_perspective_clone_get_source_point (clone, x1d, y1d, &x1s, &y1s);
gimp_perspective_clone_get_source_point (clone, x1d, y2d, &x2s, &y2s);
gimp_perspective_clone_get_source_point (clone, x2d, y1d, &x3s, &y3s);
gimp_perspective_clone_get_source_point (clone, x2d, y2d, &x4s, &y4s);
xmin = floor (MIN4 (x1s, x2s, x3s, x4s));
xmax = ceil (MAX4 (x1s, x2s, x3s, x4s));
ymin = floor (MIN4 (y1s, y2s, y3s, y4s));
ymax = ceil (MAX4 (y1s, y2s, y3s, y4s));
xmax++; xmin--;
ymax++; ymin--;
xmin = CLAMP (xmin,
0, tile_manager_width (src_tiles));
ymin = CLAMP (ymin,
0, tile_manager_height (src_tiles));
xmax = CLAMP (xmax,
0, tile_manager_width (src_tiles));
ymax = CLAMP (ymax,
0, tile_manager_height (src_tiles));
/* if the source area is completely out of the image */
if (!(xmax - xmin) || !(ymax - ymin))
return;
/* If the source image is different from the destination,
* then we should copy straight from the destination image
* to the canvas.
* Otherwise, we need a call to get_orig_image to make sure
* we get a copy of the unblemished (offset) image
*/
if (( options->sample_merged && (src_image != image)) ||
(! options->sample_merged && (clone->src_drawable != drawable)))
{
/* get the original image */
pixel_region_init (&auxPR, src_tiles,
xmin, ymin, xmax-xmin, ymax - ymin, FALSE);
orig = temp_buf_new (xmax-xmin, ymax-ymin, auxPR.bytes, 0, 0, NULL);
pixel_region_init_temp_buf (&auxPR2, orig,
0, 0, xmax - xmin, ymax - ymin);
copy_region (&auxPR, &auxPR2);
}
else
{
/* get the original image */
if (options->sample_merged)
orig = gimp_paint_core_get_orig_proj (paint_core,
src_pickable,
xmin, ymin, xmax, ymax);
else
orig = gimp_paint_core_get_orig_image (paint_core,
GIMP_DRAWABLE (src_pickable),
xmin, ymin, xmax, ymax);
}
/* note: orig is a TempBuf where are all the pixels that I need to copy */
/* copy from orig to temp_buf, this buffer has the size of the destination area */
/* Also allocate memory for alpha channel */
temp_buf = temp_buf_new (x2d-x1d, y2d-y1d, orig->bytes+1, 0, 0, NULL);
src_data = temp_buf_data (orig);
dest_data = temp_buf_data (temp_buf);
for (i = x1d; i < x2d; i++)
{
for (j = y1d; j < y2d; j++)
{
guchar *dest_pixel;
gimp_perspective_clone_get_source_point (clone,
i, j,
&temp_x, &temp_y);
itemp_x = (gint) temp_x;
itemp_y = (gint) temp_y;
/* Points to the dest pixel in temp_buf*/
dest_pixel = dest_data + (gint)((j-y1d) * temp_buf->width + (i-x1d)) * temp_buf->bytes;
/* Check if the source pixel is inside the image*/
if (itemp_x > 0 &&
itemp_x < (tile_manager_width (src_tiles)-1) &&
itemp_y > 0 &&
itemp_y < (tile_manager_height (src_tiles)-1))
{
guchar *src_pixel;
guchar color1[temp_buf->bytes - 1];
guchar color2[temp_buf->bytes - 1];
guchar color3[temp_buf->bytes - 1];
guchar color4[temp_buf->bytes - 1];
gdouble dx, dy;
gint k;
dx = temp_x - itemp_x;
dy = temp_y - itemp_y;
/* linear interpolation */
/* (i,j)*((1-dx)*(1-dy) + (i+1,j)*(dx*(1-dy)) + (i,j+1)*((1-dx)*dy) + (i+1,j+1)*(dx*dy) */
src_pixel = src_data + (gint)((itemp_y-ymin) * orig->width + (itemp_x-xmin)) * orig->bytes;
for (k = 0 ; k < temp_buf->bytes-1; k++) color1[k] = *src_pixel++;
src_pixel = src_data + (gint)((itemp_y-ymin) * orig->width + (itemp_x+1-xmin)) * orig->bytes;
for (k = 0 ; k < temp_buf->bytes-1; k++) color2[k] = *src_pixel++;
src_pixel = src_data + (gint)((itemp_y+1-ymin) * orig->width + (itemp_x-xmin)) * orig->bytes;
for (k = 0 ; k < temp_buf->bytes-1; k++) color3[k] = *src_pixel++;
src_pixel = src_data + (gint)((itemp_y+1-ymin) * orig->width + (itemp_x+1-xmin)) * orig->bytes;
for (k = 0 ; k < temp_buf->bytes-1; k++) color4[k] = *src_pixel++;
/* copy the pixel interpolated to temp_buf */
for (k = 0 ; k < temp_buf->bytes-1; k++)
*dest_pixel++ = color1[k]*((1-dx)*(1-dy)) + color2[k]*(dx*(1-dy)) + color3[k]*((1-dx)*dy) + color4[k]*(dx*dy);
/* If the pixel is inside the image set the alpha channel visible */
*dest_pixel = 255;
}
else
{
dest_pixel[temp_buf->bytes-1] = 0; /* Pixels with source out-of-image are transparent */
}
}
}
pixel_region_init_temp_buf (&srcPR, temp_buf,
0, 0, x2d - x1d, y2d - y1d);
/* configure the destination */
pixel_region_init_temp_buf (&destPR, area, 0, 0, srcPR.w, srcPR.h);
pr = pixel_regions_register (2, &srcPR, &destPR);
break;
case GIMP_PATTERN_CLONE:
pattern = gimp_context_get_pattern (context);
if (!pattern)
return;
/* configure the destination */
pixel_region_init_temp_buf (&destPR, area,
0, 0, area->width, area->height);
pr = pixel_regions_register (1, &destPR);
break;
}
for (; pr != NULL; pr = pixel_regions_process (pr))
{
s = srcPR.data;
d = destPR.data;
for (y = 0; y < destPR.h; y++)
{
switch (options->clone_type)
{
case GIMP_IMAGE_CLONE:
gimp_perspective_clone_line_image (image, src_image,
drawable, src_pickable,
s, d,
srcPR.bytes, destPR.bytes, destPR.w);
s += srcPR.rowstride;
break;
case GIMP_PATTERN_CLONE:
gimp_perspective_clone_line_pattern (image, drawable,
pattern, d,
area->x + offset_x,
area->y + y + offset_y,
destPR.bytes, destPR.w);
break;
}
d += destPR.rowstride;
}
}
if (paint_options->pressure_options->opacity)
opacity *= PRESSURE_SCALE * paint_core->cur_coords.pressure;
gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
MIN (opacity, GIMP_OPACITY_OPAQUE),
gimp_context_get_opacity (context),
gimp_context_get_paint_mode (context),
gimp_paint_options_get_brush_mode (paint_options),
/* In fixed mode, paint incremental so the
* individual brushes are properly applied
* on top of each other.
* Otherwise the stuff we paint is seamless
* and we don't need intermediate masking.
*/
options->align_mode == GIMP_SOURCE_ALIGN_FIXED ?
GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
}
static void
gimp_perspective_clone_line_image (GimpImage *dest,
GimpImage *src,
GimpDrawable *d_drawable,
GimpPickable *s_pickable,
guchar *s,
guchar *d,
gint src_bytes,
gint dest_bytes,
gint width)
{
guchar rgba[MAX_CHANNELS];
gint alpha;
alpha = dest_bytes - 1;
while (width--)
{
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] = s[src_bytes-1]; /* This line is diferent that in gimpclone !! */
s += src_bytes;
d += dest_bytes;
}
}
static void
gimp_perspective_clone_line_pattern (GimpImage *dest,
GimpDrawable *drawable,
GimpPattern *pattern,
guchar *d,
gint x,
gint y,
gint bytes,
gint width)
{
guchar *pat, *p;
GimpImageBaseType color_type;
gint alpha;
gint pat_bytes;
gint i;
pat_bytes = pattern->mask->bytes;
/* Make sure x, y are positive */
while (x < 0)
x += pattern->mask->width;
while (y < 0)
y += pattern->mask->height;
/* Get a pointer to the appropriate scanline of the pattern buffer */
pat = temp_buf_data (pattern->mask) +
(y % pattern->mask->height) * pattern->mask->width * pat_bytes;
color_type = (pat_bytes == 3 ||
pat_bytes == 4) ? GIMP_RGB : GIMP_GRAY;
alpha = bytes - 1;
for (i = 0; i < width; i++)
{
p = pat + ((i + x) % pattern->mask->width) * pat_bytes;
gimp_image_transform_color (dest, drawable, d, color_type, p);
if (pat_bytes == 2 || pat_bytes == 4)
d[alpha] = p[pat_bytes - 1];
else
d[alpha] = OPAQUE_OPACITY;
d += bytes;
}
}
static void
gimp_perspective_clone_src_drawable_removed (GimpDrawable *drawable,
GimpPerspectiveClone *clone)
{
if (drawable == clone->src_drawable)
{
clone->src_drawable = NULL;
}
g_signal_handlers_disconnect_by_func (drawable,
gimp_perspective_clone_src_drawable_removed,
clone);
}
static void
gimp_perspective_clone_set_src_drawable (GimpPerspectiveClone *clone,
GimpDrawable *drawable)
{
if (clone->src_drawable == drawable)
return;
if (clone->src_drawable)
g_signal_handlers_disconnect_by_func (clone->src_drawable,
gimp_perspective_clone_src_drawable_removed,
clone);
clone->src_drawable = drawable;
if (clone->src_drawable)
g_signal_connect (clone->src_drawable, "removed",
G_CALLBACK (gimp_perspective_clone_src_drawable_removed),
clone);
g_object_notify (G_OBJECT (clone), "src-drawable");
}
void
gimp_perspective_clone_get_source_point (GimpPerspectiveClone *perspective_clone,
gdouble x,
gdouble y,
gdouble *newx,
gdouble *newy)
{
gdouble temp_x, temp_y;
gdouble offset_x_fv, offset_y_fv;
gimp_matrix3_transform_point (&perspective_clone->transform_inv,
x, y, &temp_x, &temp_y);
/* Get the offset of each pixel in destination area from the
* destination pixel in front view perspective
*/
offset_x_fv = temp_x - perspective_clone->dest_x_fv;
offset_y_fv = temp_y - perspective_clone->dest_y_fv;
/* Get the source pixel in front view perspective */
temp_x = offset_x_fv + perspective_clone->src_x_fv;
temp_y = offset_y_fv + perspective_clone->src_y_fv;
/* Convert the source pixel to perspective view */
gimp_matrix3_transform_point (&perspective_clone->transform,
temp_x, temp_y, newx, newy);
}

View File

@ -0,0 +1,84 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_PERSPECTIVE_CLONE_H__
#define __GIMP_PERSPECTIVE_CLONE_H__
#include "gimpclone.h"
#define GIMP_TYPE_PERSPECTIVE_CLONE (gimp_perspective_clone_get_type ())
#define GIMP_PERSPECTIVE_CLONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PERSPECTIVE_CLONE, GimpPerspectiveClone))
#define GIMP_PERSPECTIVE_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PERSPECTIVE_CLONE, GimpPerspectiveCloneClass))
#define GIMP_IS_PERSPECTIVE_CLONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PERSPECTIVE_CLONE))
#define GIMP_IS_PERSPECTIVE_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PERSPECTIVE_CLONE))
#define GIMP_PERSPECTIVE_CLONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PERSPECTIVE_CLONE, GimpPerspectiveCloneClass))
typedef struct _GimpPerspectiveClone GimpPerspectiveClone;
typedef struct _GimpPerspectiveCloneClass GimpPerspectiveCloneClass;
struct _GimpPerspectiveClone
{
GimpClone parent_instance;
gboolean set_source;
GimpDrawable *src_drawable;
gdouble src_x; /* coordinates where the cross that indicate where is copying each moment is painted */
gdouble src_y;
gdouble orig_src_x;
gdouble orig_src_y;
gdouble dest_x; /* coords where the stroke starts */
gdouble dest_y;
gdouble src_x_fv; /* source coords in front_view perspective */
gdouble src_y_fv;
gdouble dest_x_fv; /* destination coords in front_view perspective */
gdouble dest_y_fv;
gdouble offset_x;
gdouble offset_y;
gboolean first_stroke;
GimpMatrix3 transform;
GimpMatrix3 transform_inv;
};
struct _GimpPerspectiveCloneClass
{
GimpCloneClass parent_class;
};
void gimp_perspective_clone_register (Gimp *gimp,
GimpPaintRegisterCallback callback);
GType gimp_perspective_clone_get_type (void) G_GNUC_CONST;
void gimp_perspective_clone_get_source_point (GimpPerspectiveClone *clone,
gdouble x,
gdouble y,
gdouble *newx,
gdouble *newy);
#endif /* __GIMP_CLONE_VANISHIGN_H__ */

View File

@ -0,0 +1,147 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib-object.h>
#include "libgimpconfig/gimpconfig.h"
#include "paint-types.h"
#include "gimpperspectivecloneoptions.h"
#define PERSPECTIVE_CLONE_DEFAULT_MODE GIMP_PERSPECTIVE_CLONE_MODE_ADJUST
#define PERSPECTIVE_CLONE_DEFAULT_TYPE GIMP_IMAGE_CLONE
#define PERSPECTIVE_CLONE_DEFAULT_ALIGN_MODE GIMP_SOURCE_ALIGN_NO
enum
{
PROP_0,
PROP_CLONE_MODE,
PROP_CLONE_TYPE,
PROP_ALIGN_MODE,
PROP_SAMPLE_MERGED
};
static void gimp_perspective_clone_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_perspective_clone_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GimpPerspectiveCloneOptions, gimp_perspective_clone_options,
GIMP_TYPE_PAINT_OPTIONS)
static void
gimp_perspective_clone_options_class_init (GimpPerspectiveCloneOptionsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = gimp_perspective_clone_options_set_property;
object_class->get_property = gimp_perspective_clone_options_get_property;
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_CLONE_MODE,
"clone-mode", NULL,
GIMP_TYPE_PERSPECTIVE_CLONE_MODE,
PERSPECTIVE_CLONE_DEFAULT_MODE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_CLONE_TYPE,
"clone-type", NULL,
GIMP_TYPE_CLONE_TYPE,
PERSPECTIVE_CLONE_DEFAULT_TYPE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_ALIGN_MODE,
"align-mode", NULL,
GIMP_TYPE_SOURCE_ALIGN_MODE,
PERSPECTIVE_CLONE_DEFAULT_ALIGN_MODE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_SAMPLE_MERGED,
"sample-merged", NULL,
FALSE,
GIMP_PARAM_STATIC_STRINGS);
}
static void
gimp_perspective_clone_options_init (GimpPerspectiveCloneOptions *options)
{
}
static void
gimp_perspective_clone_options_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpPerspectiveCloneOptions *options = GIMP_PERSPECTIVE_CLONE_OPTIONS (object);
switch (property_id)
{
case PROP_CLONE_MODE:
options->clone_mode = g_value_get_enum (value);
break;
case PROP_CLONE_TYPE:
options->clone_type = g_value_get_enum (value);
break;
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;
}
}
static void
gimp_perspective_clone_options_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpPerspectiveCloneOptions *options = GIMP_PERSPECTIVE_CLONE_OPTIONS (object);
switch (property_id)
{
case PROP_CLONE_MODE:
g_value_set_enum (value, options->clone_mode);
break;
case PROP_CLONE_TYPE:
g_value_set_enum (value, options->clone_type);
break;
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;
}
}

View File

@ -0,0 +1,56 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_PERSPECTIVE_CLONE_OPTIONS_H__
#define __GIMP_PERSPECTIVE_CLONE_OPTIONS_H__
#include "gimppaintoptions.h"
#define GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS (gimp_perspective_clone_options_get_type ())
#define GIMP_PERSPECTIVE_CLONE_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS, GimpPerspectiveCloneOptions))
#define GIMP_PERSPECTIVE_CLONE_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS, GimpPerspectiveCloneOptionsClass))
#define GIMP_IS_PERSPECTIVE_CLONE_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS))
#define GIMP_IS_PERSPECTIVE_CLONE_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS))
#define GIMP_PERSPECTIVE_CLONE_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS, GimpPerspectiveCloneOptionsClass))
typedef struct _GimpPerspectiveCloneOptions GimpPerspectiveCloneOptions;
typedef struct _GimpPerspectiveCloneOptionsClass GimpPerspectiveCloneOptionsClass;
struct _GimpPerspectiveCloneOptions
{
GimpPaintOptions paint_instance;
GimpPerspectiveCloneMode clone_mode;
GimpCloneType clone_type;
GimpSourceAlignMode align_mode;
gboolean sample_merged;
};
struct _GimpPerspectiveCloneOptionsClass
{
GimpPaintOptionsClass parent_class;
};
GType gimp_perspective_clone_options_get_type (void) G_GNUC_CONST;
#endif /* __GIMP_PERSPECTIVE_CLONE_OPTIONS_H__ */

View File

@ -36,6 +36,34 @@ gimp_brush_application_mode_get_type (void)
return type;
}
GType
gimp_perspective_clone_mode_get_type (void)
{
static const GEnumValue values[] =
{
{ GIMP_PERSPECTIVE_CLONE_MODE_ADJUST, "GIMP_PERSPECTIVE_CLONE_MODE_ADJUST", "adjust" },
{ GIMP_PERSPECTIVE_CLONE_MODE_PAINT, "GIMP_PERSPECTIVE_CLONE_MODE_PAINT", "paint" },
{ 0, NULL, NULL }
};
static const GimpEnumDesc descs[] =
{
{ GIMP_PERSPECTIVE_CLONE_MODE_ADJUST, N_("Modify Perspective Plane"), NULL },
{ GIMP_PERSPECTIVE_CLONE_MODE_PAINT, N_("Perspective Clone"), NULL },
{ 0, NULL, NULL }
};
static GType type = 0;
if (! type)
{
type = g_enum_register_static ("GimpPerspectiveCloneMode", values);
gimp_enum_set_value_descriptions (type, descs);
}
return type;
}
GType
gimp_source_align_mode_get_type (void)
{

View File

@ -47,6 +47,17 @@ typedef enum
} GimpBrushApplicationMode;
#define GIMP_TYPE_PERSPECTIVE_CLONE_MODE (gimp_perspective_clone_mode_get_type ())
GType gimp_perspective_clone_mode_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
GIMP_PERSPECTIVE_CLONE_MODE_ADJUST, /*< desc="Modify Perspective Plane" >*/
GIMP_PERSPECTIVE_CLONE_MODE_PAINT /*< desc="Perspective Clone" >*/
} GimpPerspectiveCloneMode;
#define GIMP_TYPE_SOURCE_ALIGN_MODE (gimp_source_align_mode_get_type ())
GType gimp_source_align_mode_get_type (void) G_GNUC_CONST;

View File

@ -116,6 +116,8 @@ libapptools_a_sources = \
gimppainttool.h \
gimppenciltool.c \
gimppenciltool.h \
gimpperspectiveclonetool.c \
gimpperspectiveclonetool.h \
gimpperspectivetool.c \
gimpperspectivetool.h \
gimpposterizetool.c \

View File

@ -73,6 +73,7 @@
#include "gimpmovetool.h"
#include "gimppaintbrushtool.h"
#include "gimppenciltool.h"
#include "gimpperspectiveclonetool.h"
#include "gimpperspectivetool.h"
#include "gimpposterizetool.h"
#include "gimpthresholdtool.h"
@ -133,6 +134,7 @@ gimp_tools_init (Gimp *gimp)
gimp_dodge_burn_tool_register,
gimp_smudge_tool_register,
gimp_convolve_tool_register,
gimp_perspective_clone_tool_register,
gimp_heal_tool_register,
gimp_clone_tool_register,
gimp_ink_tool_register,
@ -518,6 +520,10 @@ gimp_tools_register (GType tool_type,
{
paint_core_name = "gimp-heal";
}
else if (tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL)
{
paint_core_name = "gimp-perspective-clone";
}
else if (tool_type == GIMP_TYPE_CONVOLVE_TOOL)
{
paint_core_name = "gimp-convolve";

View File

@ -49,6 +49,7 @@
#include "gimppaintbrushtool.h"
#include "gimppaintoptions-gui.h"
#include "gimppenciltool.h"
#include "gimpperspectiveclonetool.h"
#include "gimpsmudgetool.h"
#include "gimptooloptions-gui.h"
@ -181,11 +182,12 @@ 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 ||
if (tool_type == GIMP_TYPE_ERASER_TOOL ||
tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_CONVOLVE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_SMUDGE_TOOL)
{
button = gimp_prop_check_button_new (config, "hard", _("Hard edge"));
@ -240,6 +242,7 @@ pressure_options_gui (GimpPressureOptions *pressure,
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_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_ERASER_TOOL)
{
@ -250,12 +253,13 @@ 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 ||
if (tool_type == GIMP_TYPE_AIRBRUSH_TOOL ||
tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_CONVOLVE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
tool_type == GIMP_TYPE_SMUDGE_TOOL)
{
button = gimp_prop_check_button_new (config, "pressure-hardness",
@ -276,12 +280,13 @@ 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 ||
tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
if (tool_type == GIMP_TYPE_CLONE_TOOL ||
tool_type == GIMP_TYPE_HEAL_TOOL ||
tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL ||
tool_type == GIMP_TYPE_CONVOLVE_TOOL ||
tool_type == GIMP_TYPE_DODGE_BURN_TOOL ||
tool_type == GIMP_TYPE_ERASER_TOOL ||
tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
tool_type == GIMP_TYPE_PENCIL_TOOL)
{
button = gimp_prop_check_button_new (config, "pressure-size",

View File

@ -0,0 +1,917 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
#include "tools-types.h"
#include "core/gimp-transform-utils.h"
#include "core/gimpchannel.h"
#include "core/gimpimage.h"
#include "core/gimppickable.h"
#include "core/gimptoolinfo.h"
#include "core/gimpdrawable-transform.h"
#include "paint/gimpperspectiveclone.h"
#include "paint/gimpperspectivecloneoptions.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpviewablebox.h"
#include "widgets/gimpwidgets-utils.h"
#include "display/gimpdisplay.h"
#include "gimpperspectiveclonetool.h"
#include "gimppaintoptions-gui.h"
#include "gimptoolcontrol.h"
#include "gimp-intl.h"
#define HANDLE_SIZE 10
#define TARGET_WIDTH 15
#define TARGET_HEIGHT 15
static GObject * gimp_perspective_clone_tool_constructor (GType type,
guint n_params,
GObjectConstructParam *params);
static gboolean gimp_perspective_clone_tool_initialize (GimpTool *tool,
GimpDisplay *display);
static gboolean gimp_perspective_clone_tool_has_display (GimpTool *tool,
GimpDisplay *display);
static GimpDisplay * gimp_perspective_clone_tool_has_image (GimpTool *tool,
GimpImage *image);
static void gimp_perspective_clone_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *display);
static void gimp_perspective_clone_tool_button_press (GimpTool *tool,
GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpDisplay *display);
static void gimp_perspective_clone_tool_motion (GimpTool *tool,
GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpDisplay *display);
static void gimp_perspective_clone_tool_cursor_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
GimpDisplay *display);
static void gimp_perspective_clone_tool_oper_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
gboolean proximity,
GimpDisplay *display);
static void gimp_perspective_clone_tool_mode_notify (GObject *config,
GParamSpec *pspec,
GimpPerspectiveCloneTool *perspective_clone_tool);
static void gimp_perspective_clone_tool_draw (GimpDrawTool *draw_tool);
static void gimp_perspective_clone_tool_transform_bounding_box (GimpPerspectiveCloneTool *perspective_clone_tool);
static void gimp_perspective_clone_tool_bounds (GimpPerspectiveCloneTool *tool,
GimpDisplay *display);
static void gimp_perspective_clone_tool_prepare (GimpPerspectiveCloneTool *perspective_clone_tool,
GimpDisplay *display);
static void gimp_perspective_clone_tool_recalc (GimpPerspectiveCloneTool *perspective_clone_tool,
GimpDisplay *display);
static GtkWidget * gimp_perspective_clone_options_gui (GimpToolOptions *tool_options);
G_DEFINE_TYPE (GimpPerspectiveCloneTool, gimp_perspective_clone_tool,
GIMP_TYPE_BRUSH_TOOL)
#define parent_class gimp_perspective_clone_tool_parent_class
void
gimp_perspective_clone_tool_register (GimpToolRegisterCallback callback,
gpointer data)
{
(* callback) (GIMP_TYPE_PERSPECTIVE_CLONE_TOOL,
GIMP_TYPE_PERSPECTIVE_CLONE_OPTIONS,
gimp_perspective_clone_options_gui,
GIMP_PAINT_OPTIONS_CONTEXT_MASK |
GIMP_CONTEXT_PATTERN_MASK,
"gimp-perspective-clone-tool",
_("Perspective Clone"),
_("Paint using Image Regions Preserving the Perspective of the Image"),
N_("_Clone"), "C",
NULL, GIMP_HELP_TOOL_PERSPECTIVE_CLONE,
GIMP_STOCK_TOOL_PERSPECTIVE_CLONE,
data);
}
static void
gimp_perspective_clone_tool_class_init (GimpPerspectiveCloneToolClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
object_class->constructor = gimp_perspective_clone_tool_constructor;
tool_class->initialize = gimp_perspective_clone_tool_initialize;
tool_class->has_display = gimp_perspective_clone_tool_has_display;
tool_class->has_image = gimp_perspective_clone_tool_has_image;
tool_class->control = gimp_perspective_clone_tool_control;
tool_class->button_press = gimp_perspective_clone_tool_button_press;
tool_class->motion = gimp_perspective_clone_tool_motion;
tool_class->cursor_update = gimp_perspective_clone_tool_cursor_update;
tool_class->oper_update = gimp_perspective_clone_tool_oper_update;
draw_tool_class->draw = gimp_perspective_clone_tool_draw;
}
static void
gimp_perspective_clone_tool_init (GimpPerspectiveCloneTool *perspective_clone_tool)
{
GimpTool *tool = GIMP_TOOL (perspective_clone_tool);
gint i;
gimp_tool_control_set_action_object_2 (tool->control,
"context/context-pattern-select-set");
for (i = 0; i < TRAN_INFO_SIZE; i++)
{
perspective_clone_tool->trans_info[i] = 0.0;
perspective_clone_tool->old_trans_info[i] = 0.0;
}
gimp_matrix3_identity (&perspective_clone_tool->transform);
perspective_clone_tool->use_grid = FALSE;
perspective_clone_tool->use_handles = TRUE;
/*perspective_clone_tool->ngx = 0;
perspective_clone_tool->ngy = 0;
perspective_clone_tool->grid_coords = NULL;
perspective_clone_tool->tgrid_coords = NULL;*/
}
static GObject *
gimp_perspective_clone_tool_constructor (GType type,
guint n_params,
GObjectConstructParam *params)
{
GObject *object;
GimpTool *tool;
GimpPerspectiveCloneTool *perspective_clone_tool;
GObject *options;
object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
tool = GIMP_TOOL (object);
perspective_clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (object);
options = G_OBJECT (tool->tool_info->tool_options);
g_assert (GIMP_IS_TOOL_INFO (tool->tool_info));
g_signal_connect_object (options,
"notify::clone-mode",
G_CALLBACK (gimp_perspective_clone_tool_mode_notify),
perspective_clone_tool, 0);
/* set cursor depending work mode */
if (GIMP_PERSPECTIVE_CLONE_OPTIONS (options)->clone_mode ==
GIMP_PERSPECTIVE_CLONE_MODE_ADJUST)
gimp_tool_control_set_tool_cursor (GIMP_TOOL(perspective_clone_tool)->control,
GIMP_TOOL_CURSOR_PERSPECTIVE);
else
gimp_tool_control_set_tool_cursor (GIMP_TOOL(perspective_clone_tool)->control,
GIMP_TOOL_CURSOR_CLONE);
return object;
}
static gboolean
gimp_perspective_clone_tool_initialize (GimpTool *tool,
GimpDisplay *display)
{
GimpPerspectiveCloneTool *perspective_clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
if (display != tool->display)
{
gint i;
/* Set the pointer to the active display */
tool->display = display;
tool->drawable = gimp_image_active_drawable (display->image);
/* Find the transform bounds initializing */
gimp_perspective_clone_tool_bounds (perspective_clone_tool, display);
gimp_perspective_clone_tool_prepare (perspective_clone_tool, display);
/* Recalculate the transform tool */
gimp_perspective_clone_tool_recalc (perspective_clone_tool, display);
/* start drawing the bounding box and handles... */
gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
perspective_clone_tool->function = TRANSFORM_CREATING;
/* Save the current transformation info */
for (i = 0; i < TRAN_INFO_SIZE; i++)
perspective_clone_tool->old_trans_info[i] =
perspective_clone_tool->trans_info[i];
}
return TRUE;
}
static gboolean
gimp_perspective_clone_tool_has_display (GimpTool *tool,
GimpDisplay *display)
{
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
return (display == clone_tool->src_display ||
GIMP_TOOL_CLASS (parent_class)->has_display (tool, display));
}
static GimpDisplay *
gimp_perspective_clone_tool_has_image (GimpTool *tool,
GimpImage *image)
{
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
GimpDisplay *display;
display = GIMP_TOOL_CLASS (parent_class)->has_image (tool, image);
if (! display && clone_tool->src_display)
{
if (image && clone_tool->src_display->image == image)
display = clone_tool->src_display;
/* NULL image means any display */
if (! image)
display = clone_tool->src_display;
}
return display;
}
static void
gimp_perspective_clone_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *display)
{
GimpPerspectiveCloneTool *perspective_clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
switch (action)
{
case GIMP_TOOL_ACTION_PAUSE:
break;
case GIMP_TOOL_ACTION_RESUME:
/* only in the case that Mode: Modify Poligon is set " */
gimp_perspective_clone_tool_bounds (perspective_clone_tool, display);
gimp_perspective_clone_tool_recalc (perspective_clone_tool, display);
break;
case GIMP_TOOL_ACTION_HALT:
perspective_clone_tool->src_display = NULL;
g_object_set (GIMP_PAINT_TOOL (tool)->core,
"src-drawable", NULL,
NULL);
break;
}
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
}
static void
gimp_perspective_clone_tool_button_press (GimpTool *tool,
GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpDisplay *display)
{
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (paint_tool->core);
GimpPerspectiveCloneOptions *options;
options = GIMP_PERSPECTIVE_CLONE_OPTIONS (tool->tool_info->tool_options);
if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST)
{
if (clone_tool->function == TRANSFORM_CREATING)
gimp_perspective_clone_tool_oper_update (tool, coords, state, TRUE, display);
clone_tool->lastx = clone_tool->startx = coords->x;
clone_tool->lasty = clone_tool->starty = coords->y;
gimp_tool_control_activate (tool->control);
}
else
{
gdouble nnx, nny;
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
paint_tool->core->use_saved_proj = FALSE;
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
{
clone->set_source = TRUE;
clone_tool->src_display = display;
}
else
{
clone->set_source = FALSE;
if (options->clone_type == GIMP_IMAGE_CLONE &&
options->sample_merged &&
display == clone_tool->src_display)
{
paint_tool->core->use_saved_proj = TRUE;
}
}
GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
display);
/* Set the coordinates for the reference cross */
gimp_perspective_clone_get_source_point (clone,
coords->x, coords->y,
&nnx, &nny);
clone_tool->src_x = nnx;
clone_tool->src_y = nny;
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
}
static void
gimp_perspective_clone_tool_prepare (GimpPerspectiveCloneTool *perspective_clone_tool,
GimpDisplay *display)
{
perspective_clone_tool->trans_info[X0] = (gdouble) perspective_clone_tool->x1;
perspective_clone_tool->trans_info[Y0] = (gdouble) perspective_clone_tool->y1;
perspective_clone_tool->trans_info[X1] = (gdouble) perspective_clone_tool->x2;
perspective_clone_tool->trans_info[Y1] = (gdouble) perspective_clone_tool->y1;
perspective_clone_tool->trans_info[X2] = (gdouble) perspective_clone_tool->x1;
perspective_clone_tool->trans_info[Y2] = (gdouble) perspective_clone_tool->y2;
perspective_clone_tool->trans_info[X3] = (gdouble) perspective_clone_tool->x2;
perspective_clone_tool->trans_info[Y3] = (gdouble) perspective_clone_tool->y2;
}
void
gimp_perspective_clone_tool_recalc (GimpPerspectiveCloneTool *perspective_clone_tool,
GimpDisplay *display)
{
g_return_if_fail (GIMP_IS_DISPLAY (display));
gimp_matrix3_identity (&perspective_clone_tool->transform);
gimp_transform_matrix_perspective (&perspective_clone_tool->transform,
perspective_clone_tool->x1,
perspective_clone_tool->y1,
perspective_clone_tool->x2 - perspective_clone_tool->x1,
perspective_clone_tool->y2 - perspective_clone_tool->y1,
perspective_clone_tool->trans_info[X0],
perspective_clone_tool->trans_info[Y0],
perspective_clone_tool->trans_info[X1],
perspective_clone_tool->trans_info[Y1],
perspective_clone_tool->trans_info[X2],
perspective_clone_tool->trans_info[Y2],
perspective_clone_tool->trans_info[X3],
perspective_clone_tool->trans_info[Y3]);
gimp_perspective_clone_tool_transform_bounding_box (perspective_clone_tool);
}
static void
gimp_perspective_clone_tool_motion (GimpTool *tool,
GimpCoords *coords,
guint32 time,
GdkModifierType state,
GimpDisplay *display)
{
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (paint_tool->core);
GimpPerspectiveCloneOptions *options;
options = GIMP_PERSPECTIVE_CLONE_OPTIONS (tool->tool_info->tool_options);
if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST)
{
gdouble diff_x, diff_y;
/* if we are creating, there is nothing to be done so exit. */
if (clone_tool->function == TRANSFORM_CREATING /*|| ! tr_tool->use_grid*/)
return;
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
clone_tool->curx = coords->x;
clone_tool->cury = coords->y;
clone_tool->state = state;
/* recalculate the tool's transformation matrix */
diff_x = clone_tool->curx - clone_tool->lastx;
diff_y = clone_tool->cury - clone_tool->lasty;
switch (clone_tool->function)
{
case TRANSFORM_HANDLE_NW:
clone_tool->trans_info[X0] += diff_x;
clone_tool->trans_info[Y0] += diff_y;
break;
case TRANSFORM_HANDLE_NE:
clone_tool->trans_info[X1] += diff_x;
clone_tool->trans_info[Y1] += diff_y;
break;
case TRANSFORM_HANDLE_SW:
clone_tool->trans_info[X2] += diff_x;
clone_tool->trans_info[Y2] += diff_y;
break;
case TRANSFORM_HANDLE_SE:
clone_tool->trans_info[X3] += diff_x;
clone_tool->trans_info[Y3] += diff_y;
break;
default:
break;
}
gimp_perspective_clone_tool_recalc (clone_tool, display);
clone_tool->lastx = clone_tool->curx;
clone_tool->lasty = clone_tool->cury;
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
else if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_PAINT)
{
gdouble nnx, nny;
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
clone->set_source = TRUE;
else
clone->set_source = FALSE;
GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state,
display);
/* Set the coordinates for the reference cross */
gimp_perspective_clone_get_source_point (clone,
coords->x, coords->y,
&nnx, &nny);
clone_tool->src_x = nnx;
clone_tool->src_y = nny;
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
}
static void
gimp_perspective_clone_tool_cursor_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
GimpDisplay *display)
{
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
GimpPerspectiveCloneOptions *options;
GimpCursorType cursor = GIMP_CURSOR_MOUSE;
GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE;
options = GIMP_PERSPECTIVE_CLONE_OPTIONS (tool->tool_info->tool_options);
if (gimp_image_coords_in_active_pickable (display->image, coords,
FALSE, TRUE))
{
cursor = GIMP_CURSOR_MOUSE;
}
if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST)
{
/* perspective cursors */
cursor = gimp_tool_control_get_cursor (tool->control);
if (clone_tool->use_handles)
{
switch (clone_tool->function)
{
case TRANSFORM_HANDLE_NW:
cursor = GIMP_CURSOR_CORNER_TOP_LEFT;
break;
case TRANSFORM_HANDLE_NE:
cursor = GIMP_CURSOR_CORNER_TOP_RIGHT;
break;
case TRANSFORM_HANDLE_SW:
cursor = GIMP_CURSOR_CORNER_BOTTOM_LEFT;
break;
case TRANSFORM_HANDLE_SE:
cursor = GIMP_CURSOR_CORNER_BOTTOM_RIGHT;
break;
default:
cursor = GIMP_CURSOR_CROSSHAIR_SMALL;
break;
}
}
}
else
{
if (options->clone_type == GIMP_IMAGE_CLONE)
{
if ((state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
{
cursor = GIMP_CURSOR_CROSSHAIR_SMALL;
}
else if (! GIMP_PERSPECTIVE_CLONE (GIMP_PAINT_TOOL (tool)->core)->src_drawable)
{
modifier = GIMP_CURSOR_MODIFIER_BAD;
}
}
}
gimp_tool_control_set_cursor (tool->control, cursor);
gimp_tool_control_set_cursor_modifier (tool->control, modifier);
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
}
static void
gimp_perspective_clone_tool_oper_update (GimpTool *tool,
GimpCoords *coords,
GdkModifierType state,
gboolean proximity,
GimpDisplay *display)
{
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
GimpPerspectiveCloneOptions *options;
options = GIMP_PERSPECTIVE_CLONE_OPTIONS (tool->tool_info->tool_options);
if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST)
{
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
clone_tool->function = TRANSFORM_HANDLE_NONE;
if (display != tool->display)
return;
if (clone_tool->use_handles)
{
gdouble closest_dist;
gdouble dist;
closest_dist = gimp_draw_tool_calc_distance (draw_tool, display,
coords->x, coords->y,
clone_tool->tx1,
clone_tool->ty1);
clone_tool->function = TRANSFORM_HANDLE_NW;
dist = gimp_draw_tool_calc_distance (draw_tool, display,
coords->x, coords->y,
clone_tool->tx2,
clone_tool->ty2);
if (dist < closest_dist)
{
closest_dist = dist;
clone_tool->function = TRANSFORM_HANDLE_NE;
}
dist = gimp_draw_tool_calc_distance (draw_tool, display,
coords->x, coords->y,
clone_tool->tx3,
clone_tool->ty3);
if (dist < closest_dist)
{
closest_dist = dist;
clone_tool->function = TRANSFORM_HANDLE_SW;
}
dist = gimp_draw_tool_calc_distance (draw_tool, display,
coords->x, coords->y,
clone_tool->tx4,
clone_tool->ty4);
if (dist < closest_dist)
{
closest_dist = dist;
clone_tool->function = TRANSFORM_HANDLE_SE;
}
}
}
else
{
GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
proximity, display);
if (options->clone_type == GIMP_IMAGE_CLONE && proximity)
{
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (GIMP_PAINT_TOOL (tool)->core);
if (clone->src_drawable == NULL)
{
gimp_tool_replace_status (tool, display,
_("Ctrl-Click to set a clone source."));
}
else
{
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
clone_tool->src_x = clone->src_x;
clone_tool->src_y = clone->src_y;
if (! clone->first_stroke)
{
if (options->align_mode == GIMP_SOURCE_ALIGN_YES)
{
gdouble nnx, nny;
/* Set the coordinates for the reference cross */
gimp_perspective_clone_get_source_point (clone,
coords->x,
coords->y,
&nnx, &nny);
clone_tool->src_x = nnx;
clone_tool->src_y = nny;
}
}
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
}
}
}
}
static void
gimp_perspective_clone_tool_draw (GimpDrawTool *draw_tool)
{
GimpTool *tool = GIMP_TOOL (draw_tool);
GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (draw_tool);
GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (GIMP_PAINT_TOOL (tool)->core);
GimpPerspectiveCloneOptions *options;
options = GIMP_PERSPECTIVE_CLONE_OPTIONS (tool->tool_info->tool_options);
if (clone_tool->use_handles)
{
/* draw the bounding box */
gimp_draw_tool_draw_line (draw_tool,
clone_tool->tx1, clone_tool->ty1,
clone_tool->tx2, clone_tool->ty2,
FALSE);
gimp_draw_tool_draw_line (draw_tool,
clone_tool->tx2, clone_tool->ty2,
clone_tool->tx4, clone_tool->ty4,
FALSE);
gimp_draw_tool_draw_line (draw_tool,
clone_tool->tx3, clone_tool->ty3,
clone_tool->tx4, clone_tool->ty4,
FALSE);
gimp_draw_tool_draw_line (draw_tool,
clone_tool->tx3, clone_tool->ty3,
clone_tool->tx1, clone_tool->ty1,
FALSE);
/* draw the tool handles */
gimp_draw_tool_draw_handle (draw_tool,
GIMP_HANDLE_SQUARE,
clone_tool->tx1, clone_tool->ty1,
HANDLE_SIZE, HANDLE_SIZE,
GTK_ANCHOR_CENTER,
FALSE);
gimp_draw_tool_draw_handle (draw_tool,
GIMP_HANDLE_SQUARE,
clone_tool->tx2, clone_tool->ty2,
HANDLE_SIZE, HANDLE_SIZE,
GTK_ANCHOR_CENTER,
FALSE);
gimp_draw_tool_draw_handle (draw_tool,
GIMP_HANDLE_SQUARE,
clone_tool->tx3, clone_tool->ty3,
HANDLE_SIZE, HANDLE_SIZE,
GTK_ANCHOR_CENTER,
FALSE);
gimp_draw_tool_draw_handle (draw_tool,
GIMP_HANDLE_SQUARE,
clone_tool->tx4, clone_tool->ty4,
HANDLE_SIZE, HANDLE_SIZE,
GTK_ANCHOR_CENTER,
FALSE);
}
if (options->clone_type == GIMP_IMAGE_CLONE &&
clone->src_drawable && clone_tool->src_display)
{
GimpDisplay *tmp_display;
gint off_x;
gint off_y;
gimp_item_offsets (GIMP_ITEM (clone->src_drawable), &off_x, &off_y);
tmp_display = draw_tool->display;
draw_tool->display = clone_tool->src_display;
gimp_draw_tool_draw_handle (draw_tool,
GIMP_HANDLE_CROSS,
clone_tool->src_x,
clone_tool->src_y,
TARGET_WIDTH, TARGET_WIDTH,
GTK_ANCHOR_CENTER,
FALSE);
draw_tool->display = tmp_display;
}
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
}
static void
gimp_perspective_clone_tool_transform_bounding_box (GimpPerspectiveCloneTool *perspective_clone_tool)
{
g_return_if_fail (GIMP_IS_PERSPECTIVE_CLONE_TOOL (perspective_clone_tool));
gimp_matrix3_transform_point (&perspective_clone_tool->transform,
perspective_clone_tool->x1, perspective_clone_tool->y1,
&perspective_clone_tool->tx1, &perspective_clone_tool->ty1);
gimp_matrix3_transform_point (&perspective_clone_tool->transform,
perspective_clone_tool->x2, perspective_clone_tool->y1,
&perspective_clone_tool->tx2, &perspective_clone_tool->ty2);
gimp_matrix3_transform_point (&perspective_clone_tool->transform,
perspective_clone_tool->x1, perspective_clone_tool->y2,
&perspective_clone_tool->tx3, &perspective_clone_tool->ty3);
gimp_matrix3_transform_point (&perspective_clone_tool->transform,
perspective_clone_tool->x2, perspective_clone_tool->y2,
&perspective_clone_tool->tx4, &perspective_clone_tool->ty4);
#if 0
gimp_matrix3_transform_point (&tr_tool->transform,
tr_tool->cx, tr_tool->cy,
&tr_tool->tcx, &tr_tool->tcy);
if (tr_tool->grid_coords && tr_tool->tgrid_coords)
{
gint i, k;
gint gci;
gci = 0;
k = (tr_tool->ngx + tr_tool->ngy) * 2;
for (i = 0; i < k; i++)
{
gimp_matrix3_transform_point (&tr_tool->transform,
tr_tool->grid_coords[gci],
tr_tool->grid_coords[gci + 1],
&tr_tool->tgrid_coords[gci],
&tr_tool->tgrid_coords[gci + 1]);
gci += 2;
}
}
#endif
}
static void
gimp_perspective_clone_tool_bounds (GimpPerspectiveCloneTool *tool,
GimpDisplay *display)
{
g_return_if_fail (GIMP_IS_DISPLAY (display));
tool->x1 = 0;
tool->y1 = 0;
tool->x2 = display->image->width;
tool->y2 = display->image->height;
}
static void
gimp_perspective_clone_tool_mode_notify (GObject *config,
GParamSpec *pspec,
GimpPerspectiveCloneTool *perspective_clone_tool)
{
GimpPerspectiveClone *perspective_clone;
GimpPerspectiveCloneOptions *options;
perspective_clone = GIMP_PERSPECTIVE_CLONE (GIMP_PAINT_TOOL(perspective_clone_tool)->core);
options = GIMP_PERSPECTIVE_CLONE_OPTIONS (config);
if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_PAINT)
{
gimp_tool_control_set_tool_cursor (GIMP_TOOL (perspective_clone_tool)->control,
GIMP_TOOL_CURSOR_CLONE);
perspective_clone->transform = perspective_clone_tool->transform;
perspective_clone->transform_inv = perspective_clone_tool->transform;
gimp_matrix3_invert (&perspective_clone->transform_inv);
/* print the matrix */
g_printerr ("%f\t", (perspective_clone_tool->transform).coeff[0][0]);
g_printerr ("%f\t", (perspective_clone_tool->transform).coeff[0][1]);
g_printerr ("%f\n", (perspective_clone_tool->transform).coeff[0][2]);
g_printerr ("%f\t", (perspective_clone_tool->transform).coeff[1][0]);
g_printerr ("%f\t", (perspective_clone_tool->transform).coeff[1][1]);
g_printerr ("%f\n", (perspective_clone_tool->transform).coeff[1][2]);
g_printerr ("%f\t", (perspective_clone_tool->transform).coeff[2][0]);
g_printerr ("%f\t", (perspective_clone_tool->transform).coeff[2][1]);
g_printerr ("%f\n\n", (perspective_clone_tool->transform).coeff[2][2]);
}
else
{
gimp_tool_control_set_tool_cursor (GIMP_TOOL (perspective_clone_tool)->control,
GIMP_TOOL_CURSOR_PERSPECTIVE);
}
}
/* tool options stuff */
static GtkWidget *
gimp_perspective_clone_options_gui (GimpToolOptions *tool_options)
{
GObject *config = G_OBJECT (tool_options);
GtkWidget *vbox;
GtkWidget *paint_options;
GtkWidget *frame;
GtkWidget *mode;
GtkWidget *button;
GtkWidget *hbox;
GtkWidget *table;
GtkWidget *combo;
vbox = gtk_vbox_new (FALSE, 6);
paint_options = gimp_paint_options_gui (tool_options);
/* radio buttons to set if you are modifying perspe plane or painting */
mode = gimp_prop_enum_radio_frame_new (config, "clone-mode",
_("Mode"), 0, 0);
gtk_box_pack_start (GTK_BOX (vbox), mode, FALSE, FALSE, 0);
gtk_widget_show (mode);
gtk_box_pack_start (GTK_BOX (vbox), paint_options, FALSE, FALSE, 0);
gtk_widget_show (paint_options);
frame = gimp_prop_enum_radio_frame_new (config, "clone-type",
_("Source"), 0, 0);
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"));
gimp_enum_radio_frame_add (GTK_FRAME (frame), button, GIMP_IMAGE_CLONE);
hbox = gimp_prop_pattern_box_new (NULL, GIMP_CONTEXT (tool_options), 2,
"pattern-view-type", "pattern-view-size");
gimp_enum_radio_frame_add (GTK_FRAME (frame), hbox, GIMP_PATTERN_CLONE);
table = gtk_table_new (1, 2, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 2);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
gtk_widget_show (table);
/*combo = gimp_prop_enum_combo_box_new (config, "align-mode", 0, 0);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("Alignment:"), 0.0, 0.5,
combo, 1, FALSE);
*/
frame = gimp_prop_enum_radio_frame_new (config, "align-mode",
_("Alignment"),
0, 0);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
return vbox;
}

View File

@ -0,0 +1,107 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_PERSPECTIVE_CLONE_TOOL_H__
#define __GIMP_PERSPECTIVE_CLONE_TOOL_H__
#include "gimpbrushtool.h"
#include "gimptransformtool.h" /* Quit, but define TransInfo */
/* buffer sizes for scaling information strings (for the info dialog) */
#define MAX_INFO_BUF 40
#define TRAN_INFO_SIZE 8
#define GIMP_TYPE_PERSPECTIVE_CLONE_TOOL (gimp_perspective_clone_tool_get_type ())
#define GIMP_PERSPECTIVE_CLONE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PERSPECTIVE_CLONE_TOOL, GimpPerspectiveCloneTool))
#define GIMP_PERSPECTIVE_CLONE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PERSPECTIVE_CLONE_TOOL, GimpPerspectiveCloneToolClass))
#define GIMP_IS_PERSPECTIVE_CLONE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PERSPECTIVE_CLONE_TOOL))
#define GIMP_IS_PERSPECTIVE_CLONE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PERSPECTIVE_CLONE_TOOL))
#define GIMP_PERSPECTIVE_CLONE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PERSPECTIVE_CLONE_TOOL, GimpPerspectiveCloneToolClass))
typedef struct _GimpPerspectiveCloneTool GimpPerspectiveCloneTool;
typedef struct _GimpPerspectiveCloneToolClass GimpPerspectiveCloneToolClass;
struct _GimpPerspectiveCloneTool
{
GimpBrushTool parent_instance;
GimpDisplay *src_display;
gint src_x;
gint src_y;
gdouble startx; /* starting x coord */
gdouble starty; /* starting y coord */
gdouble curx; /* current x coord */
gdouble cury; /* current y coord */
gdouble lastx; /* last x coord */
gdouble lasty; /* last y coord */
GdkModifierType state; /* state of buttons and keys */
GimpMatrix3 transform; /* transformation matrix */
TransInfo trans_info; /* transformation info */
TransInfo old_trans_info; /* for cancelling a drag operation */
gint x1, y1; /* upper left hand coordinate */
gint x2, y2; /* lower right hand coords */
gdouble tx1, ty1; /* transformed coords */
gdouble tx2, ty2;
gdouble tx3, ty3;
gdouble tx4, ty4;
gdouble tcx, tcy;
gboolean use_grid; /* does the tool use the grid */
gboolean use_handles; /* uses the corner handles */
TransformAction function; /* current tool activity */
/*gint ngx, ngy;*/ /* number of grid lines in original
* x and y directions
*/
/*gdouble *grid_coords;*/ /* x and y coordinates of the grid
* endpoints (a total of (ngx+ngy)*2
* coordinate pairs)
*/
/*gdouble *tgrid_coords;*/ /* transformed grid_coords */
};
struct _GimpPerspectiveCloneToolClass
{
GimpBrushToolClass parent_class;
};
void gimp_perspective_clone_tool_register (GimpToolRegisterCallback callback,
gpointer data);
GType gimp_perspective_clone_tool_get_type (void) G_GNUC_CONST;
#endif /* __GIMP_PERSPECTIVE_CLONE_TOOL_H__ */

View File

@ -264,6 +264,7 @@
#define GIMP_HELP_TOOL_PAINTBRUSH "gimp-tool-paintbrush"
#define GIMP_HELP_TOOL_PENCIL "gimp-tool-pencil"
#define GIMP_HELP_TOOL_PERSPECTIVE "gimp-tool-perspective"
#define GIMP_HELP_TOOL_PERSPECTIVE_CLONE "gimp-tool-perspective-clone"
#define GIMP_HELP_TOOL_POSTERIZE "gimp-tool-posterize"
#define GIMP_HELP_TOOL_RECT_SELECT "gimp-tool-rect-select"
#define GIMP_HELP_TOOL_ROTATE "gimp-tool-rotate"

View File

@ -297,6 +297,7 @@ static const GtkStockItem gimp_stock_items[] =
{ GIMP_STOCK_TOOL_PATH, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_TOOL_PENCIL, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_TOOL_PERSPECTIVE, N_("_Transform"), 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_TOOL_PERSPECTIVE_CLONE, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_TOOL_POSTERIZE, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_TOOL_RECT_SELECT, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_TOOL_ROTATE, N_("_Rotate"), 0, 0, LIBGIMP_DOMAIN },
@ -434,6 +435,7 @@ gimp_stock_button_pixbufs[] =
{ GIMP_STOCK_TOOL_PATH, stock_tool_path_22 },
{ GIMP_STOCK_TOOL_PENCIL, stock_tool_pencil_22 },
{ GIMP_STOCK_TOOL_PERSPECTIVE, stock_tool_perspective_22 },
{ GIMP_STOCK_TOOL_PERSPECTIVE_CLONE, stock_tool_perspective_clone_22 },
{ GIMP_STOCK_TOOL_POSTERIZE, stock_tool_posterize_22 },
{ GIMP_STOCK_TOOL_RECT_SELECT, stock_tool_rect_select_22 },
{ GIMP_STOCK_TOOL_ROTATE, stock_tool_rotate_22 },
@ -581,6 +583,7 @@ gimp_stock_menu_pixbufs[] =
{ GIMP_STOCK_TOOL_PATH, stock_tool_path_16 },
{ GIMP_STOCK_TOOL_PENCIL, stock_tool_pencil_16 },
{ GIMP_STOCK_TOOL_PERSPECTIVE, stock_tool_perspective_16 },
{ GIMP_STOCK_TOOL_PERSPECTIVE_CLONE, stock_tool_perspective_clone_16 },
{ GIMP_STOCK_TOOL_POSTERIZE, stock_tool_posterize_16 },
{ GIMP_STOCK_TOOL_RECT_SELECT, stock_tool_rect_select_16 },
{ GIMP_STOCK_TOOL_ROTATE, stock_tool_rotate_16 },

View File

@ -129,6 +129,7 @@ G_BEGIN_DECLS
#define GIMP_STOCK_TOOL_PATH "gimp-tool-path"
#define GIMP_STOCK_TOOL_PENCIL "gimp-tool-pencil"
#define GIMP_STOCK_TOOL_PERSPECTIVE "gimp-tool-perspective"
#define GIMP_STOCK_TOOL_PERSPECTIVE_CLONE "gimp-tool-perspective-clone"
#define GIMP_STOCK_TOOL_POSTERIZE "gimp-tool-posterize"
#define GIMP_STOCK_TOOL_RECT_SELECT "gimp-tool-rect-select"
#define GIMP_STOCK_TOOL_ROTATE "gimp-tool-rotate"

View File

@ -498,6 +498,7 @@
<menuitem action="tools-ink" />
<menuitem action="tools-clone" />
<menuitem action="tools-heal" />
<menuitem action="tools-perspective-clone" />
<menuitem action="tools-convolve" />
<menuitem action="tools-smudge" />
<menuitem action="tools-dodge-burn" />

View File

@ -292,6 +292,8 @@ STOCK_TOOL_IMAGES = \
tools/stock-tool-pencil-22.png \
tools/stock-tool-perspective-16.png \
tools/stock-tool-perspective-22.png \
tools/stock-tool-perspective-clone-16.png \
tools/stock-tool-perspective-clone-22.png \
tools/stock-tool-posterize-16.png \
tools/stock-tool-posterize-22.png \
tools/stock-tool-rect-select-16.png \

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B