2003-08-27 13:44:57 +08:00
|
|
|
/* curve_bend plugin for the GIMP */
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Revision history
|
2004-02-09 22:43:46 +08:00
|
|
|
* (2004/02/08) v1.3.18 hof: #133244 exit with execution error if there is
|
|
|
|
* an empty selection
|
|
|
|
* (2003/08/24) v1.3.18 hof: #119937 show busy cursor when recalculating
|
|
|
|
* preview
|
2002-09-12 05:52:49 +08:00
|
|
|
* (2002/09/xx) v1.1.18 mitch and gsr: clean interface
|
2000-02-21 19:00:28 +08:00
|
|
|
* (2000/02/16) v1.1.17b hof: added spinbuttons for rotate entry
|
2000-02-17 00:38:36 +08:00
|
|
|
* (2000/02/16) v1.1.17 hof: undo bugfix (#6012)
|
2003-11-06 23:27:05 +08:00
|
|
|
* don't call gimp_undo_push_group_end
|
2000-02-17 00:38:36 +08:00
|
|
|
* after gimp_displays_flush
|
1999-09-13 19:03:37 +08:00
|
|
|
* (1999/09/13) v1.01 hof: PDB-calls updated for gimp 1.1.9
|
1999-07-29 01:44:32 +08:00
|
|
|
* (1999/05/10) v1.0 hof: first public release
|
|
|
|
* (1999/04/23) v0.0 hof: coding started,
|
|
|
|
* splines and dialog parts are similar to curves.c
|
|
|
|
*/
|
2000-01-07 00:40:17 +08:00
|
|
|
|
|
|
|
#include "config.h"
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2003-08-17 07:26:17 +08:00
|
|
|
#include <errno.h>
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2005-03-04 23:12:29 +08:00
|
|
|
#include <glib/gstdio.h>
|
2000-01-07 00:40:17 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
2000-01-07 00:40:17 +08:00
|
|
|
|
1999-11-24 07:49:42 +08:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2000-05-01 05:03:44 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* Defines */
|
2005-08-14 02:29:14 +08:00
|
|
|
#define PLUG_IN_PROC "plug-in-curve-bend"
|
|
|
|
#define PLUG_IN_BINARY "curve_bend"
|
2003-08-27 13:44:57 +08:00
|
|
|
#define PLUG_IN_VERSION "v1.3.18 (2003/08/26)"
|
1999-07-29 01:44:32 +08:00
|
|
|
#define PLUG_IN_IMAGE_TYPES "RGB*, GRAY*"
|
|
|
|
#define PLUG_IN_AUTHOR "Wolfgang Hofer (hof@hotbot.com)"
|
|
|
|
#define PLUG_IN_COPYRIGHT "Wolfgang Hofer"
|
|
|
|
|
|
|
|
#define PLUG_IN_ITER_NAME "plug_in_curve_bend_Iterator"
|
|
|
|
#define PLUG_IN_DATA_ITER_FROM "plug_in_curve_bend_ITER_FROM"
|
|
|
|
#define PLUG_IN_DATA_ITER_TO "plug_in_curve_bend_ITER_TO"
|
|
|
|
|
|
|
|
#define KEY_POINTFILE "POINTFILE_CURVE_BEND"
|
|
|
|
#define KEY_POINTS "POINTS"
|
|
|
|
#define KEY_VAL_Y "VAL_Y"
|
|
|
|
|
|
|
|
#define MIDDLE 127
|
|
|
|
|
|
|
|
#define SIGNED_ROUND(x) ((int) (((x < 0) ? (x) - 0.5 : (x) + 0.5) ))
|
|
|
|
#define MIX_CHANNEL(a, b, m) (((a * m) + (b * (255 - m))) / 255)
|
|
|
|
|
|
|
|
#define UP_GRAPH 0x1
|
|
|
|
#define UP_XRANGE_TOP 0x2
|
|
|
|
#define UP_PREVIEW_EXPOSE 0x4
|
|
|
|
#define UP_PREVIEW 0x8
|
|
|
|
#define UP_DRAW 0x10
|
|
|
|
#define UP_ALL 0xFF
|
|
|
|
|
|
|
|
#define ENTRY_WIDTH 50
|
|
|
|
#define GRAPH_WIDTH 256
|
|
|
|
#define GRAPH_HEIGHT 256
|
|
|
|
#define PREVIEW_SIZE_X 256
|
|
|
|
#define PREVIEW_SIZE_Y 256
|
|
|
|
#define PV_IMG_WIDTH 128
|
|
|
|
#define PV_IMG_HEIGHT 128
|
|
|
|
#define RADIUS 3
|
|
|
|
#define MIN_DISTANCE 8
|
2004-07-31 05:29:45 +08:00
|
|
|
#define PREVIEW_BPP 4
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
#define SMOOTH 0
|
|
|
|
#define GFREE 1
|
|
|
|
|
|
|
|
#define GRAPH_MASK GDK_EXPOSURE_MASK | \
|
2004-07-31 05:29:45 +08:00
|
|
|
GDK_POINTER_MOTION_MASK | \
|
|
|
|
GDK_POINTER_MOTION_HINT_MASK | \
|
1999-07-29 01:44:32 +08:00
|
|
|
GDK_ENTER_NOTIFY_MASK | \
|
2004-07-31 05:29:45 +08:00
|
|
|
GDK_BUTTON_PRESS_MASK | \
|
|
|
|
GDK_BUTTON_RELEASE_MASK | \
|
|
|
|
GDK_BUTTON1_MOTION_MASK
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
#define OUTLINE_UPPER 0
|
|
|
|
#define OUTLINE_LOWER 1
|
|
|
|
|
|
|
|
typedef struct _BenderValues BenderValues;
|
|
|
|
struct _BenderValues
|
|
|
|
{
|
2004-02-09 22:43:46 +08:00
|
|
|
guchar curve[2][256]; /* for curve_type freehand mode 0 <= curve <= 255 */
|
|
|
|
gdouble points[2][17][2]; /* for curve_type smooth mode 0.0 <= points <= 1.0 */
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
int curve_type;
|
|
|
|
|
|
|
|
gint smoothing;
|
|
|
|
gint antialias;
|
|
|
|
gint work_on_copy;
|
|
|
|
gdouble rotation;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
gint32 total_steps;
|
|
|
|
gdouble current_step;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _Curves Curves;
|
|
|
|
|
|
|
|
struct _Curves
|
|
|
|
{
|
|
|
|
int x, y; /* coords for last mouse click */
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _BenderDialog BenderDialog;
|
|
|
|
|
|
|
|
struct _BenderDialog
|
|
|
|
{
|
2000-01-13 23:39:26 +08:00
|
|
|
GtkWidget *shell;
|
|
|
|
GtkWidget *outline_menu;
|
|
|
|
GtkWidget *pv_widget;
|
|
|
|
GtkWidget *graph;
|
2000-02-21 19:00:28 +08:00
|
|
|
GtkAdjustment *rotate_data;
|
2000-01-13 23:39:26 +08:00
|
|
|
GdkPixmap *pixmap;
|
2004-05-18 19:28:13 +08:00
|
|
|
GtkWidget *filechooser;
|
2000-01-13 23:39:26 +08:00
|
|
|
|
2004-08-31 22:02:10 +08:00
|
|
|
GdkCursor *cursor_busy;
|
2003-08-27 13:44:57 +08:00
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpDrawable *drawable;
|
2000-01-13 23:39:26 +08:00
|
|
|
int color;
|
|
|
|
int outline;
|
|
|
|
gint preview;
|
|
|
|
|
|
|
|
int grab_point;
|
|
|
|
int last;
|
|
|
|
int leftmost;
|
|
|
|
int rightmost;
|
|
|
|
int curve_type;
|
|
|
|
gdouble points[2][17][2]; /* 0.0 <= points <= 1.0 */
|
|
|
|
guchar curve[2][256]; /* 0 <= curve <= 255 */
|
2003-11-06 23:27:05 +08:00
|
|
|
gint32 *curve_ptr[2]; /* 0 <= curve_ptr <= src_drawable_width
|
2004-07-31 05:29:45 +08:00
|
|
|
* both arrays are allocated dynamic,
|
|
|
|
* depending on drawable width
|
|
|
|
*/
|
2000-01-13 23:39:26 +08:00
|
|
|
gint32 min2[2];
|
|
|
|
gint32 max2[2];
|
|
|
|
gint32 zero2[2];
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2000-01-13 23:39:26 +08:00
|
|
|
gint show_progress;
|
|
|
|
gint smoothing;
|
|
|
|
gint antialias;
|
|
|
|
gint work_on_copy;
|
|
|
|
gdouble rotation;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
|
2000-01-13 23:39:26 +08:00
|
|
|
gint32 preview_image_id;
|
|
|
|
gint32 preview_layer_id1;
|
|
|
|
gint32 preview_layer_id2;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
BenderValues *bval_from;
|
|
|
|
BenderValues *bval_to;
|
|
|
|
BenderValues *bval_curr;
|
2000-01-13 23:39:26 +08:00
|
|
|
|
2003-07-02 19:07:41 +08:00
|
|
|
gboolean run;
|
1999-07-29 01:44:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* points Coords:
|
|
|
|
*
|
2003-11-06 23:27:05 +08:00
|
|
|
* 1.0 +----+----+----+----+
|
|
|
|
* | . | | |
|
|
|
|
* +--.-+--.-+----+----+
|
|
|
|
* . | . | |
|
|
|
|
* 0.5 +----+----+-.--+----+
|
|
|
|
* | | | . .
|
|
|
|
* +----+----+----+-.-.+
|
|
|
|
* | | | | |
|
|
|
|
* 0.0 +----+----+----+----+
|
1999-07-29 01:44:32 +08:00
|
|
|
* 0.0 0.5 1.0
|
|
|
|
*
|
|
|
|
* curve Coords:
|
|
|
|
*
|
|
|
|
* OUTLINE_UPPER OUTLINE_LOWER
|
|
|
|
*
|
|
|
|
* 255 +----+----+----+----+ 255 +----+----+----+----+
|
2004-07-31 05:29:45 +08:00
|
|
|
* | . | | | --- max | . | | | --- max
|
|
|
|
* +--.-+--.-+----+----+ +--.-+--.-+----+----+
|
|
|
|
* . | . | | zero ___ . | . | |
|
|
|
|
* +----+----+-.--+----+ +----+----+-.--+----+
|
|
|
|
* | | | . . --- zero | | | . .
|
|
|
|
* +----+----+----+-.-.+ ___ min +----+----+----+-.-.+ ___ min
|
|
|
|
* | | | | | | | | | |
|
|
|
|
* 0 +----+----+----+----+ 0 +----+----+----+----+
|
|
|
|
* 0 255 0 255
|
1999-07-29 01:44:32 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
typedef double CRMatrix[4][4];
|
|
|
|
|
2000-01-13 23:39:26 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpDrawable *drawable;
|
2000-01-13 23:39:26 +08:00
|
|
|
gint x1;
|
|
|
|
gint y1;
|
|
|
|
gint x2;
|
|
|
|
gint y2;
|
|
|
|
gint index_alpha; /* 0 == no alpha, 1 == GREYA, 3 == RGBA */
|
|
|
|
gint bpp;
|
2003-08-27 13:44:57 +08:00
|
|
|
GimpPixelFetcher *pft;
|
2000-01-13 23:39:26 +08:00
|
|
|
gint tile_width;
|
|
|
|
gint tile_height;
|
1999-07-29 01:44:32 +08:00
|
|
|
} t_GDRW;
|
|
|
|
|
2000-01-13 23:39:26 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
1999-07-29 01:44:32 +08:00
|
|
|
gint32 y;
|
|
|
|
guchar color[4];
|
|
|
|
} t_Last;
|
|
|
|
|
|
|
|
|
|
|
|
/* curves action functions */
|
|
|
|
static void query (void);
|
2003-07-02 19:07:41 +08:00
|
|
|
static void run (const gchar *name,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
static BenderDialog * bender_new_dialog (GimpDrawable *);
|
1999-07-29 01:44:32 +08:00
|
|
|
static void bender_update (BenderDialog *, int);
|
2000-01-13 23:39:26 +08:00
|
|
|
static void bender_plot_curve (BenderDialog *,
|
2004-07-31 05:29:45 +08:00
|
|
|
int, int, int, int,
|
|
|
|
gint32, gint32, gint);
|
2000-01-13 23:39:26 +08:00
|
|
|
static void bender_calculate_curve (BenderDialog *, gint32,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32, gint);
|
2000-02-21 19:00:28 +08:00
|
|
|
static void bender_rotate_adj_callback (GtkAdjustment *, gpointer);
|
2004-07-31 05:29:45 +08:00
|
|
|
static void bender_border_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_type_callback (GtkWidget *, gpointer);
|
1999-07-29 01:44:32 +08:00
|
|
|
static void bender_reset_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_copy_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_copy_inv_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_swap_callback (GtkWidget *, gpointer);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void bender_response (GtkWidget *, gint,
|
|
|
|
BenderDialog *);
|
1999-07-29 01:44:32 +08:00
|
|
|
static void bender_smoothing_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_antialias_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_work_on_copy_callback (GtkWidget *, gpointer);
|
|
|
|
static void bender_preview_update (GtkWidget *, gpointer);
|
|
|
|
static void bender_preview_update_once (GtkWidget *, gpointer);
|
2003-11-19 22:51:52 +08:00
|
|
|
static void bender_load_callback (GtkWidget *,
|
|
|
|
BenderDialog *);
|
|
|
|
static void bender_save_callback (GtkWidget *,
|
|
|
|
BenderDialog *);
|
2000-01-13 23:39:26 +08:00
|
|
|
static gint bender_graph_events (GtkWidget *, GdkEvent *,
|
2004-07-31 05:29:45 +08:00
|
|
|
BenderDialog *);
|
2000-01-13 23:39:26 +08:00
|
|
|
static void bender_CR_compose (CRMatrix, CRMatrix,
|
2004-07-31 05:29:45 +08:00
|
|
|
CRMatrix);
|
1999-07-29 01:44:32 +08:00
|
|
|
static void bender_init_min_max (BenderDialog *, gint32);
|
2000-08-22 09:26:57 +08:00
|
|
|
static BenderDialog * do_dialog (GimpDrawable *);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_init_gdrw (t_GDRW *gdrw, GimpDrawable *drawable,
|
2004-07-31 05:29:45 +08:00
|
|
|
int dirty, int shadow);
|
2000-02-08 06:23:02 +08:00
|
|
|
static void p_end_gdrw (t_GDRW *gdrw);
|
2000-08-22 09:26:57 +08:00
|
|
|
static gint32 p_main_bend (BenderDialog *, GimpDrawable *, gint);
|
|
|
|
static gint32 p_create_pv_image (GimpDrawable *src_drawable, gint32 *layer_id);
|
2000-02-08 06:23:02 +08:00
|
|
|
static void p_render_preview (BenderDialog *cd, gint32 layer_id);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_get_pixel (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x, gint32 y, guchar *pixel);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_put_pixel (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x, gint32 y, guchar *pixel);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_put_mix_pixel (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x, gint32 y, guchar *color,
|
|
|
|
gint32 nb_curvy, gint32 nb2_curvy,
|
|
|
|
gint32 curvy);
|
2000-02-08 06:23:02 +08:00
|
|
|
static void p_stretch_curves (BenderDialog *cd, gint32 xmax, gint32 ymax);
|
|
|
|
static void p_cd_to_bval (BenderDialog *cd, BenderValues *bval);
|
|
|
|
static void p_cd_from_bval (BenderDialog *cd, BenderValues *bval);
|
|
|
|
static void p_store_values (BenderDialog *cd);
|
|
|
|
static void p_retrieve_values (BenderDialog *cd);
|
|
|
|
static void p_bender_calculate_iter_curve (BenderDialog *cd, gint32 xmax, gint32 ymax);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_delta_gdouble (double *val, double val_from, double val_to,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 total_steps, gdouble current_step);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_delta_gint32 (gint32 *val, gint32 val_from, gint32 val_to,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 total_steps, gdouble current_step);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_copy_points (BenderDialog *cd, int outline, int xy,
|
2004-07-31 05:29:45 +08:00
|
|
|
int argc, gdouble *floatarray);
|
2003-11-06 23:27:05 +08:00
|
|
|
static void p_copy_yval (BenderDialog *cd, int outline,
|
2004-07-31 05:29:45 +08:00
|
|
|
int argc, gint8 *int8array);
|
2001-07-29 17:43:09 +08:00
|
|
|
static int p_save_pointfile (BenderDialog *cd, const gchar *filename);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* Global Variables */
|
2006-05-16 20:26:20 +08:00
|
|
|
const GimpPlugInInfo PLUG_IN_INFO =
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
NULL, /* init_proc */
|
|
|
|
NULL, /* quit_proc */
|
|
|
|
query, /* query_proc */
|
|
|
|
run /* run_proc */
|
|
|
|
};
|
|
|
|
|
|
|
|
static CRMatrix CR_basis =
|
|
|
|
{
|
|
|
|
{ -0.5, 1.5, -1.5, 0.5 },
|
|
|
|
{ 1.0, -2.5, 2.0, -0.5 },
|
|
|
|
{ -0.5, 0.0, 0.5, 0.0 },
|
|
|
|
{ 0.0, 1.0, 0.0, 0.0 },
|
|
|
|
};
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static int gb_debug = FALSE;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* Functions */
|
|
|
|
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX PDB_STUFF XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
|
|
|
|
2005-11-17 15:28:07 +08:00
|
|
|
#ifdef ROTATE_OPTIMIZE
|
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* ============================================================================
|
|
|
|
* p_pdb_procedure_available
|
|
|
|
* if requested procedure is available in the PDB return the number of args
|
|
|
|
* (0 upto n) that are needed to call the procedure.
|
|
|
|
* if not available return -1
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
static gint
|
2003-07-02 19:07:41 +08:00
|
|
|
p_pdb_procedure_available (const gchar *proc_name)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
2000-06-13 22:42:50 +08:00
|
|
|
gint l_nparams;
|
|
|
|
gint l_nreturn_vals;
|
|
|
|
GimpPDBProcType l_proc_type;
|
|
|
|
gchar *l_proc_blurb;
|
|
|
|
gchar *l_proc_help;
|
|
|
|
gchar *l_proc_author;
|
|
|
|
gchar *l_proc_copyright;
|
|
|
|
gchar *l_proc_date;
|
|
|
|
GimpParamDef *l_params;
|
|
|
|
GimpParamDef *l_return_vals;
|
1999-07-29 01:44:32 +08:00
|
|
|
gint l_rc;
|
|
|
|
|
|
|
|
l_rc = 0;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* Query the gimp application's procedural database
|
|
|
|
* regarding a particular procedure.
|
|
|
|
*/
|
2000-08-08 05:30:35 +08:00
|
|
|
if (gimp_procedural_db_proc_info (proc_name,
|
2004-07-31 05:29:45 +08:00
|
|
|
&l_proc_blurb,
|
|
|
|
&l_proc_help,
|
|
|
|
&l_proc_author,
|
|
|
|
&l_proc_copyright,
|
|
|
|
&l_proc_date,
|
|
|
|
&l_proc_type,
|
|
|
|
&l_nparams, &l_nreturn_vals,
|
|
|
|
&l_params, &l_return_vals))
|
2003-12-04 22:05:17 +08:00
|
|
|
{
|
|
|
|
/* procedure found in PDB */
|
|
|
|
return l_nparams;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
g_printerr ("Warning: Procedure %s not found.\n", proc_name);
|
1999-07-29 01:44:32 +08:00
|
|
|
return -1;
|
2003-08-27 13:44:57 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2005-11-17 15:28:07 +08:00
|
|
|
#endif /* ROTATE_OPTIMIZE */
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
static gint
|
|
|
|
p_gimp_rotate (gint32 image_id,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 drawable_id,
|
|
|
|
gint32 interpolation,
|
|
|
|
gdouble angle_deg)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-04 22:05:17 +08:00
|
|
|
gdouble l_angle_rad;
|
|
|
|
gint l_rc;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
#ifdef ROTATE_OPTIMIZE
|
2005-11-17 15:28:07 +08:00
|
|
|
static gchar *l_rotate_proc = "plug-in-rotate";
|
|
|
|
GimpParam *return_vals;
|
|
|
|
gint nreturn_vals;
|
2003-12-04 22:05:17 +08:00
|
|
|
gint32 l_angle_step;
|
2005-11-17 15:28:07 +08:00
|
|
|
gint l_nparams;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (angle_deg == 90.0) { l_angle_step = 1; }
|
|
|
|
else if(angle_deg == 180.0) { l_angle_step = 2; }
|
|
|
|
else if(angle_deg == 270.0) { l_angle_step = 3; }
|
|
|
|
else { l_angle_step = 0; }
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (l_angle_step != 0)
|
|
|
|
{
|
2005-11-17 15:28:07 +08:00
|
|
|
l_nparams = p_pdb_procedure_available (l_rotate_proc);
|
1999-07-29 01:44:32 +08:00
|
|
|
if (l_nparams == 5)
|
|
|
|
{
|
2003-12-04 22:05:17 +08:00
|
|
|
/* use faster rotate plugin on multiples of 90 degrees */
|
2005-11-17 15:28:07 +08:00
|
|
|
return_vals = gimp_run_procedure (l_rotate_proc,
|
2003-12-04 22:05:17 +08:00
|
|
|
&nreturn_vals,
|
|
|
|
GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE,
|
|
|
|
GIMP_PDB_IMAGE, image_id,
|
|
|
|
GIMP_PDB_DRAWABLE, drawable_id,
|
|
|
|
GIMP_PDB_INT32, l_angle_step,
|
|
|
|
GIMP_PDB_INT32, FALSE, /* dont rotate the whole image */
|
|
|
|
GIMP_PDB_END);
|
|
|
|
|
|
|
|
if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2003-12-04 22:05:17 +08:00
|
|
|
}
|
2005-11-17 15:28:07 +08:00
|
|
|
#endif /* ROTATE_OPTIMIZE */
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
l_angle_rad = (angle_deg * G_PI) / 180.0;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2005-11-17 15:28:07 +08:00
|
|
|
l_rc = gimp_drawable_transform_rotate_default (drawable_id, l_angle_rad,
|
|
|
|
TRUE, 0, 0, interpolation,
|
|
|
|
FALSE);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2005-11-17 15:28:07 +08:00
|
|
|
if (l_rc == -1)
|
|
|
|
g_printerr ("Error: gimp_drawable_transform_rotate_default call failed\n");
|
2003-12-04 22:05:17 +08:00
|
|
|
|
|
|
|
return l_rc;
|
2003-08-27 13:44:57 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_if_selection_float_it
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static gint32
|
2003-11-06 23:27:05 +08:00
|
|
|
p_if_selection_float_it (gint32 image_id,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 layer_id)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-06 00:30:01 +08:00
|
|
|
if (! gimp_layer_is_floating_sel (layer_id))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint32 l_sel_channel_id;
|
|
|
|
gint32 l_x1, l_x2, l_y1, l_y2;
|
|
|
|
gint32 non_empty;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
/* check and see if we have a selection mask */
|
2004-02-09 22:47:41 +08:00
|
|
|
l_sel_channel_id = gimp_image_get_selection (image_id);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
gimp_selection_bounds (image_id, &non_empty, &l_x1, &l_y1, &l_x2, &l_y2);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (non_empty && l_sel_channel_id >= 0)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
/* selection is TRUE, make a layer (floating selection) from
|
|
|
|
the selection */
|
|
|
|
if (gimp_edit_copy (layer_id))
|
|
|
|
{
|
|
|
|
layer_id = gimp_edit_paste (layer_id, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
2003-12-06 00:30:01 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2003-12-06 00:30:01 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
return layer_id;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX END_PDB_STUFF XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M M AAAAA IIIIII N N
|
|
|
|
* M M M M A A II NN N
|
2003-11-06 23:27:05 +08:00
|
|
|
* M M M AAAAAAA II N N N
|
1999-07-29 01:44:32 +08:00
|
|
|
* M M A A II N NN
|
|
|
|
* M M A A IIIIII N N
|
|
|
|
*/
|
|
|
|
|
|
|
|
MAIN ()
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
static void
|
2000-02-08 06:23:02 +08:00
|
|
|
query (void)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef args[] =
|
2000-05-01 05:03:44 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
|
|
|
|
{ GIMP_PDB_IMAGE, "image", "Input image" },
|
|
|
|
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable (must be a layer without layermask)"},
|
|
|
|
{ GIMP_PDB_FLOAT, "rotation", "Direction {angle 0 to 360 degree } of the bend effect"},
|
|
|
|
{ GIMP_PDB_INT32, "smoothing", "Smoothing { TRUE, FALSE }"},
|
|
|
|
{ GIMP_PDB_INT32, "antialias", "Antialias { TRUE, FALSE }"},
|
|
|
|
{ GIMP_PDB_INT32, "work_on_copy", "{ TRUE, FALSE } TRUE: copy the drawable and bend the copy"},
|
|
|
|
{ GIMP_PDB_INT32, "curve_type", " { 0, 1 } 0 == smooth (use 17 points), 1 == freehand (use 256 val_y) "},
|
|
|
|
{ GIMP_PDB_INT32, "argc_upper_point_x", "{2 <= argc <= 17} "},
|
|
|
|
{ GIMP_PDB_FLOATARRAY, "upper_point_x", "array of 17 x point_koords { 0.0 <= x <= 1.0 or -1 for unused point }"},
|
|
|
|
{ GIMP_PDB_INT32, "argc_upper_point_y", "{2 <= argc <= 17} "},
|
|
|
|
{ GIMP_PDB_FLOATARRAY, "upper_point_y", "array of 17 y point_koords { 0.0 <= y <= 1.0 or -1 for unused point }"},
|
|
|
|
{ GIMP_PDB_INT32, "argc_lower_point_x", "{2 <= argc <= 17} "},
|
|
|
|
{ GIMP_PDB_FLOATARRAY, "lower_point_x", "array of 17 x point_koords { 0.0 <= x <= 1.0 or -1 for unused point }"},
|
|
|
|
{ GIMP_PDB_INT32, "argc_lower_point_y", "{2 <= argc <= 17} "},
|
|
|
|
{ GIMP_PDB_FLOATARRAY, "lower_point_y", "array of 17 y point_koords { 0.0 <= y <= 1.0 or -1 for unused point }"},
|
|
|
|
{ GIMP_PDB_INT32, "argc_upper_val_y", "{ 256 } "},
|
|
|
|
{ GIMP_PDB_INT8ARRAY, "upper_val_y", "array of 256 y freehand koord { 0 <= y <= 255 }"},
|
|
|
|
{ GIMP_PDB_INT32, "argc_lower_val_y", "{ 256 } "},
|
|
|
|
{ GIMP_PDB_INT8ARRAY, "lower_val_y", "array of 256 y freehand koord { 0 <= y <= 255 }"}
|
1999-07-29 01:44:32 +08:00
|
|
|
};
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef return_vals[] =
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
{ GIMP_PDB_LAYER, "bent_layer", "the handled layer" }
|
1999-07-29 01:44:32 +08:00
|
|
|
};
|
|
|
|
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef args_iter[] =
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
{ GIMP_PDB_INT32, "run_mode", "non-interactive" },
|
|
|
|
{ GIMP_PDB_INT32, "total_steps", "total number of steps (# of layers-1 to apply the related plug-in)" },
|
|
|
|
{ GIMP_PDB_FLOAT, "current_step", "current (for linear iterations this is the layerstack position, otherwise some value inbetween)" },
|
|
|
|
{ GIMP_PDB_INT32, "len_struct", "length of stored data structure with id is equal to the plug_in proc_name" },
|
1999-07-29 01:44:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* the actual installation of the bend plugin */
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_install_procedure (PLUG_IN_PROC,
|
2006-03-17 17:29:48 +08:00
|
|
|
N_("Bend the image using two control curves"),
|
1999-07-29 01:44:32 +08:00
|
|
|
"This plug-in does bend the active layer "
|
2004-10-13 05:48:39 +08:00
|
|
|
"If there is a current selection it is copied to "
|
|
|
|
"floating selection and the curve_bend distortion "
|
|
|
|
"is done on the floating selection. If "
|
|
|
|
"work_on_copy parameter is TRUE, the curve_bend "
|
|
|
|
"distortion is done on a copy of the active layer "
|
|
|
|
"(or floating selection). The upper and lower edges "
|
|
|
|
"are bent in shape of 2 spline curves. both (upper "
|
|
|
|
"and lower) curves are determined by upto 17 points "
|
|
|
|
"or by 256 Y-Values if curve_type == 1 (freehand "
|
|
|
|
"mode) If rotation is not 0, the layer is rotated "
|
|
|
|
"before and rotated back after the bend operation. "
|
|
|
|
"This enables bending in other directions than "
|
|
|
|
"vertical. bending usually changes the size of "
|
|
|
|
"the handled layer. this plugin sets the offsets "
|
|
|
|
"of the handled layer to keep its center at the "
|
|
|
|
"same position",
|
1999-07-29 01:44:32 +08:00
|
|
|
PLUG_IN_AUTHOR,
|
|
|
|
PLUG_IN_COPYRIGHT,
|
|
|
|
PLUG_IN_VERSION,
|
2004-05-07 08:30:24 +08:00
|
|
|
N_("_Curve Bend..."),
|
1999-07-29 01:44:32 +08:00
|
|
|
PLUG_IN_IMAGE_TYPES,
|
2000-08-22 09:26:57 +08:00
|
|
|
GIMP_PLUGIN,
|
2001-12-06 10:28:58 +08:00
|
|
|
G_N_ELEMENTS (args),
|
|
|
|
G_N_ELEMENTS (return_vals),
|
1999-07-29 01:44:32 +08:00
|
|
|
args,
|
|
|
|
return_vals);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Distorts");
|
2004-05-07 08:30:24 +08:00
|
|
|
|
Changed the semantics of GIMP_EXTENSION and (to some extent) of
2003-06-19 Michael Natterer <mitch@gimp.org>
Changed the semantics of GIMP_EXTENSION and (to some extent)
of GIMP_PLUGIN:
The old meaning of EXTENSION was "I live in the toolbox" and
PLUGIN meant "I take RUN-MODE,IMAGE,DRAWABLE args (but only if I
am invoked interactively)". This is completely useless, since
living in the toolbox means having "<Toolbox>" in the menu_path
and taking RUN-MODE,IMAGE,DRAWABLE means just that, regardless of
what type of procedure we are.
The new meaning of GIMP_PLUGIN is just "I am an ordinary procedure,
I am invoked, do my job and finish", while GIMP_EXTENSION means
"I will install temporary procedures and I will keep running to
keep them available".
(A GIMP_EXTENSION *must* call gimp_extension_ack() now to tell the
core that it's ready to run, or the core will block waiting for
the message !!!).
* configure.in: bumped version number to 1.3.16.
* libgimpbase/gimpprotocol.h: increased protocol version number so
old extensions will refuse to load.
* app/gui/plug-in-commands.c (plug_in_run_cmd_callback): don't
blindly pass RUN-MODE,IMAGE,DRAWABLE to GIMP_PLUGIN procedures but
look at their parameters and pass them either RUN-MODE, or
RUN-MODE,IMAGE, or RUN-MODE,IMAGE,DRAWABLE.
* app/pdb/procedural_db.c: cleaned up, better error reporting,
replaced an impossible error message by g_return_if_fail()
* app/plug-in/plug-in-message.c (plug_in_handle_proc_install):
better error messages.
* app/plug-in/plug-in-params.c: allocate parameter arrays using
g_new0() so we don't have to worry about uninitialized stuff
later.
* app/plug-in/plug-in-run.c (plug_in_run): wait for
gimp_extension_ack() installation confirmation for ALL extensions,
not just for automatically started ones.
* app/plug-in/plug-ins.c: cleanup.
* libgimp/gimp.[ch]: cleaned up and API-documented massively. Made
all magic values given in the GPConfig message static and added
accessor functions for them. Added gimp_tile_width()/height().
Added new function gimp_extension_enable() which turns on
asynchronous processing of temp_proc run requests without having
to enter an endless gimp_extension_process() loop. Moved all
private functions to the end of the file. Added tons of
g_return_if_fail() all over the place. Call gimp_run_procedure2()
from gimp_run_procedure() instead of duplicating the
code. Indentation, spacing, stuff...
* libgimp/gimptile.[ch]: removed gimp_tile_width()/height().
* libgimp/gimpdrawable.c
* libgimp/gimppixelrgn.c
* libgimp/gimptile.c: use the gimp_tile_width()/height() accessor
functions.
* libgimp/gimp.def: added gimp_extension_enable.
* libgimp/gimpmenu.c: removed evil code which connected to
_readchannel manually and use gimp_extension_enable() for watching
temp_procs.
* plug-ins/helpbrowser/helpbrowser.c: removed the same evil code
here and call gimp_extension_enable(). Call gimp_extension_ack()
to let the core know that the temp_proc is installed.
* plug-ins/script-fu/script-fu.c: made all procedures except the
permanently running "extension_script_fu" ordinary GIMP_PLUGIN
procedures.
* plug-ins/common/curve_bend.c
* plug-ins/common/plugindetails.c
* plug-ins/common/screenshot.c
* plug-ins/common/uniteditor.c
* plug-ins/common/winclipboard.c
* plug-ins/dbbrowser/dbbrowser.c
* plug-ins/gfli/gfli.c
* plug-ins/twain/twain.c
* plug-ins/webbrowser/webbrowser.c
* plug-ins/winsnap/winsnap.c: made them all ordinary GIMP_PLUGIN
procedures and renamed them from "extension_*" to "plug_in_*".
Random cleanups.
* app/widgets/gimphelp.c
* plug-ins/maze/maze_face.c: call "plug_in_web_browser" now.
2003-06-20 01:12:00 +08:00
|
|
|
/* the installation of the Iterator procedure for the bend plugin */
|
1999-07-29 01:44:32 +08:00
|
|
|
gimp_install_procedure (PLUG_IN_ITER_NAME,
|
2004-10-13 05:48:39 +08:00
|
|
|
"This procedure calculates the modified values "
|
|
|
|
"for one iterationstep for the call of "
|
|
|
|
"plug_in_curve_bend",
|
1999-07-29 01:44:32 +08:00
|
|
|
"",
|
|
|
|
PLUG_IN_AUTHOR,
|
|
|
|
PLUG_IN_COPYRIGHT,
|
|
|
|
PLUG_IN_VERSION,
|
|
|
|
NULL, /* do not appear in menus */
|
|
|
|
NULL,
|
Changed the semantics of GIMP_EXTENSION and (to some extent) of
2003-06-19 Michael Natterer <mitch@gimp.org>
Changed the semantics of GIMP_EXTENSION and (to some extent)
of GIMP_PLUGIN:
The old meaning of EXTENSION was "I live in the toolbox" and
PLUGIN meant "I take RUN-MODE,IMAGE,DRAWABLE args (but only if I
am invoked interactively)". This is completely useless, since
living in the toolbox means having "<Toolbox>" in the menu_path
and taking RUN-MODE,IMAGE,DRAWABLE means just that, regardless of
what type of procedure we are.
The new meaning of GIMP_PLUGIN is just "I am an ordinary procedure,
I am invoked, do my job and finish", while GIMP_EXTENSION means
"I will install temporary procedures and I will keep running to
keep them available".
(A GIMP_EXTENSION *must* call gimp_extension_ack() now to tell the
core that it's ready to run, or the core will block waiting for
the message !!!).
* configure.in: bumped version number to 1.3.16.
* libgimpbase/gimpprotocol.h: increased protocol version number so
old extensions will refuse to load.
* app/gui/plug-in-commands.c (plug_in_run_cmd_callback): don't
blindly pass RUN-MODE,IMAGE,DRAWABLE to GIMP_PLUGIN procedures but
look at their parameters and pass them either RUN-MODE, or
RUN-MODE,IMAGE, or RUN-MODE,IMAGE,DRAWABLE.
* app/pdb/procedural_db.c: cleaned up, better error reporting,
replaced an impossible error message by g_return_if_fail()
* app/plug-in/plug-in-message.c (plug_in_handle_proc_install):
better error messages.
* app/plug-in/plug-in-params.c: allocate parameter arrays using
g_new0() so we don't have to worry about uninitialized stuff
later.
* app/plug-in/plug-in-run.c (plug_in_run): wait for
gimp_extension_ack() installation confirmation for ALL extensions,
not just for automatically started ones.
* app/plug-in/plug-ins.c: cleanup.
* libgimp/gimp.[ch]: cleaned up and API-documented massively. Made
all magic values given in the GPConfig message static and added
accessor functions for them. Added gimp_tile_width()/height().
Added new function gimp_extension_enable() which turns on
asynchronous processing of temp_proc run requests without having
to enter an endless gimp_extension_process() loop. Moved all
private functions to the end of the file. Added tons of
g_return_if_fail() all over the place. Call gimp_run_procedure2()
from gimp_run_procedure() instead of duplicating the
code. Indentation, spacing, stuff...
* libgimp/gimptile.[ch]: removed gimp_tile_width()/height().
* libgimp/gimpdrawable.c
* libgimp/gimppixelrgn.c
* libgimp/gimptile.c: use the gimp_tile_width()/height() accessor
functions.
* libgimp/gimp.def: added gimp_extension_enable.
* libgimp/gimpmenu.c: removed evil code which connected to
_readchannel manually and use gimp_extension_enable() for watching
temp_procs.
* plug-ins/helpbrowser/helpbrowser.c: removed the same evil code
here and call gimp_extension_enable(). Call gimp_extension_ack()
to let the core know that the temp_proc is installed.
* plug-ins/script-fu/script-fu.c: made all procedures except the
permanently running "extension_script_fu" ordinary GIMP_PLUGIN
procedures.
* plug-ins/common/curve_bend.c
* plug-ins/common/plugindetails.c
* plug-ins/common/screenshot.c
* plug-ins/common/uniteditor.c
* plug-ins/common/winclipboard.c
* plug-ins/dbbrowser/dbbrowser.c
* plug-ins/gfli/gfli.c
* plug-ins/twain/twain.c
* plug-ins/webbrowser/webbrowser.c
* plug-ins/winsnap/winsnap.c: made them all ordinary GIMP_PLUGIN
procedures and renamed them from "extension_*" to "plug_in_*".
Random cleanups.
* app/widgets/gimphelp.c
* plug-ins/maze/maze_face.c: call "plug_in_web_browser" now.
2003-06-20 01:12:00 +08:00
|
|
|
GIMP_PLUGIN,
|
2001-12-06 10:28:58 +08:00
|
|
|
G_N_ELEMENTS (args_iter), 0,
|
2000-05-01 05:03:44 +08:00
|
|
|
args_iter, NULL);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-07-02 19:07:41 +08:00
|
|
|
run (const gchar *name,
|
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2001-07-29 17:43:09 +08:00
|
|
|
const gchar *l_env;
|
1999-07-29 01:44:32 +08:00
|
|
|
BenderDialog *cd;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2004-02-09 22:43:46 +08:00
|
|
|
GimpDrawable *l_active_drawable = NULL;
|
|
|
|
gint32 l_active_drawable_id = -1;
|
|
|
|
gint32 l_image_id = -1;
|
|
|
|
gint32 l_layer_id = -1;
|
|
|
|
gint32 l_layer_mask_id = -1;
|
|
|
|
gint32 l_bent_layer_id = -1;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* Get the runmode from the in-parameters */
|
2001-12-19 08:13:16 +08:00
|
|
|
GimpRunMode run_mode = param[0].data.d_int32;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* status variable, use it to check for errors in invocation usualy only
|
|
|
|
during non-interactive calling */
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/*always return at least the status to the caller. */
|
2000-08-22 09:26:57 +08:00
|
|
|
static GimpParam values[2];
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
INIT_I18N ();
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
cd = NULL;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
l_env = g_getenv ("BEND_DEBUG");
|
2003-08-27 13:44:57 +08:00
|
|
|
if (l_env != NULL)
|
2003-12-04 22:05:17 +08:00
|
|
|
{
|
|
|
|
if((*l_env != 'n') && (*l_env != 'N')) gb_debug = 1;
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (gb_debug) g_printerr ("\n\nDEBUG: run %s\n", name);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
values[0].type = GIMP_PDB_STATUS;
|
1999-07-29 01:44:32 +08:00
|
|
|
values[0].data.d_status = status;
|
2003-12-04 22:05:17 +08:00
|
|
|
|
|
|
|
values[1].type = GIMP_PDB_LAYER;
|
1999-07-29 01:44:32 +08:00
|
|
|
values[1].data.d_int32 = -1;
|
2003-12-04 22:05:17 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
*nreturn_vals = 2;
|
2003-12-04 22:05:17 +08:00
|
|
|
*return_vals = values;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
if (strcmp (name, PLUG_IN_ITER_NAME) == 0)
|
2003-12-04 22:05:17 +08:00
|
|
|
{
|
|
|
|
gint32 len_struct;
|
|
|
|
gint32 total_steps;
|
|
|
|
gdouble current_step;
|
|
|
|
BenderValues bval; /* current values while iterating */
|
|
|
|
BenderValues bval_from, bval_to; /* start and end values */
|
|
|
|
|
|
|
|
/* Iterator procedure for animated calls is usually called from
|
|
|
|
* "plug_in_gap_layers_run_animfilter"
|
|
|
|
* (always run noninteractive)
|
|
|
|
*/
|
|
|
|
if ((run_mode == GIMP_RUN_NONINTERACTIVE) && (nparams == 4))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
total_steps = param[1].data.d_int32;
|
|
|
|
current_step = param[2].data.d_float;
|
|
|
|
len_struct = param[3].data.d_int32;
|
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (len_struct == sizeof (bval))
|
|
|
|
{
|
|
|
|
/* get _FROM and _TO data,
|
|
|
|
* This data was stored by plug_in_gap_layers_run_animfilter
|
|
|
|
*/
|
|
|
|
gimp_get_data (PLUG_IN_DATA_ITER_FROM, &bval_from);
|
|
|
|
gimp_get_data (PLUG_IN_DATA_ITER_TO, &bval_to);
|
|
|
|
bval = bval_from;
|
|
|
|
|
|
|
|
p_delta_gdouble (&bval.rotation, bval_from.rotation,
|
|
|
|
bval_to.rotation, total_steps, current_step);
|
|
|
|
/* note: iteration of curve and points arrays would not give useful results.
|
|
|
|
* (there might be different number of points in the from/to bender values )
|
|
|
|
* the iteration is done later, (see p_bender_calculate_iter_curve)
|
|
|
|
* when the curve is calculated.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bval.total_steps = total_steps;
|
|
|
|
bval.current_step = current_step;
|
|
|
|
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_set_data (PLUG_IN_PROC, &bval, sizeof (bval));
|
2003-12-04 22:05:17 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
values[0].data.d_status = status;
|
|
|
|
return;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* get image and drawable */
|
|
|
|
l_image_id = param[1].data.d_int32;
|
|
|
|
l_layer_id = param[2].data.d_drawable;
|
|
|
|
|
2003-12-05 22:18:47 +08:00
|
|
|
gimp_image_undo_group_start (l_image_id);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (! gimp_drawable_is_layer (l_layer_id))
|
|
|
|
{
|
2004-02-09 22:43:46 +08:00
|
|
|
g_message (_("Can operate on layers only (but was called on channel or mask)."));
|
2003-12-04 22:05:17 +08:00
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* check for layermask */
|
2003-12-04 22:05:17 +08:00
|
|
|
l_layer_mask_id = gimp_layer_get_mask (l_layer_id);
|
|
|
|
if (l_layer_mask_id >= 0)
|
|
|
|
{
|
|
|
|
/* apply the layermask
|
|
|
|
* some transitions (especially rotate) cant operate proper on
|
|
|
|
* layers with masks !
|
|
|
|
*/
|
2004-06-06 03:22:46 +08:00
|
|
|
if (run_mode == GIMP_RUN_NONINTERACTIVE)
|
|
|
|
{
|
|
|
|
gimp_layer_remove_mask (l_layer_id, 0 /* 0==APPLY */ );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_message (_("Cannot operate on layers with masks."));
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
2003-12-04 22:05:17 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* if there is a selection, make it the floating selection layer */
|
2004-02-09 22:43:46 +08:00
|
|
|
l_active_drawable_id = p_if_selection_float_it (l_image_id, l_layer_id);
|
|
|
|
if (l_active_drawable_id < 0)
|
|
|
|
{
|
|
|
|
/* could not float the selection because selection rectangle
|
|
|
|
* is completely empty return GIMP_PDB_EXECUTION_ERROR
|
|
|
|
*/
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
if (run_mode != GIMP_RUN_NONINTERACTIVE)
|
|
|
|
{
|
|
|
|
g_message (_("Cannot operate on empty selections."));
|
2004-07-31 05:29:45 +08:00
|
|
|
}
|
2004-02-09 22:43:46 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l_active_drawable = gimp_drawable_get (l_active_drawable_id);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* how are we running today? */
|
2003-12-04 22:05:17 +08:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
|
|
|
/* how are we running today? */
|
|
|
|
switch (run_mode)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-04 22:05:17 +08:00
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
/* Possibly retrieve data from a previous run */
|
2005-08-14 02:29:14 +08:00
|
|
|
/* gimp_get_data (PLUG_IN_PROC, &g_bndvals); */
|
2003-12-04 22:05:17 +08:00
|
|
|
|
|
|
|
/* Get information from the dialog */
|
|
|
|
cd = do_dialog (l_active_drawable);
|
|
|
|
cd->show_progress = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
|
|
|
/* check to see if invoked with the correct number of parameters */
|
|
|
|
if (nparams >= 20)
|
|
|
|
{
|
|
|
|
cd = g_new (BenderDialog, 1);
|
|
|
|
cd->run = TRUE;
|
2005-09-30 16:16:10 +08:00
|
|
|
cd->show_progress = TRUE;
|
2003-12-04 22:05:17 +08:00
|
|
|
cd->drawable = l_active_drawable;
|
|
|
|
|
|
|
|
cd->rotation = (gdouble) param[3].data.d_float;
|
|
|
|
cd->smoothing = (gint) param[4].data.d_int32;
|
|
|
|
cd->antialias = (gint) param[5].data.d_int32;
|
|
|
|
cd->work_on_copy = (gint) param[6].data.d_int32;
|
|
|
|
cd->curve_type = (gint) param[7].data.d_int32;
|
|
|
|
|
|
|
|
p_copy_points (cd, OUTLINE_UPPER, 0,
|
|
|
|
param[8].data.d_int32,
|
|
|
|
param[9].data.d_floatarray);
|
|
|
|
p_copy_points (cd, OUTLINE_UPPER, 1,
|
|
|
|
param[10].data.d_int32,
|
|
|
|
param[11].data.d_floatarray);
|
|
|
|
p_copy_points (cd, OUTLINE_LOWER, 0,
|
|
|
|
param[12].data.d_int32,
|
|
|
|
param[13].data.d_floatarray);
|
|
|
|
p_copy_points (cd, OUTLINE_LOWER, 1,
|
|
|
|
param[14].data.d_int32,
|
|
|
|
param[15].data.d_floatarray);
|
|
|
|
|
|
|
|
p_copy_yval (cd, OUTLINE_UPPER,
|
|
|
|
param[16].data.d_int32,
|
|
|
|
param[17].data.d_int8array);
|
|
|
|
p_copy_yval (cd, OUTLINE_UPPER,
|
|
|
|
param[18].data.d_int32,
|
|
|
|
param[19].data.d_int8array);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
|
|
cd = g_new (BenderDialog, 1);
|
|
|
|
cd->run = TRUE;
|
|
|
|
cd->show_progress = TRUE;
|
|
|
|
cd->drawable = l_active_drawable;
|
|
|
|
p_retrieve_values (cd); /* Possibly retrieve data from a previous run */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (! cd)
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
|
|
|
/* Run the main function */
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (cd->run)
|
|
|
|
{
|
|
|
|
l_bent_layer_id = p_main_bend (cd, cd->drawable, cd->work_on_copy);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
/* Store variable states for next run */
|
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
|
|
|
{
|
|
|
|
p_store_values (cd);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2003-12-04 22:05:17 +08:00
|
|
|
else
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-04 22:05:17 +08:00
|
|
|
status = GIMP_PDB_CANCEL;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-12-05 22:18:47 +08:00
|
|
|
gimp_image_undo_group_end (l_image_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 22:05:17 +08:00
|
|
|
if (run_mode != GIMP_RUN_NONINTERACTIVE)
|
|
|
|
gimp_displays_flush ();
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2003-12-04 22:05:17 +08:00
|
|
|
else
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-05 22:18:47 +08:00
|
|
|
gimp_image_undo_group_end (l_image_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
values[0].data.d_status = status;
|
|
|
|
values[1].data.d_int32 = l_bent_layer_id; /* return the id of handled layer */
|
2003-08-27 13:44:57 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static int
|
2003-11-06 23:27:05 +08:00
|
|
|
p_save_pointfile (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
const gchar *filename)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint j;
|
1999-07-29 01:44:32 +08:00
|
|
|
FILE *l_fp;
|
|
|
|
|
2005-03-04 23:12:29 +08:00
|
|
|
l_fp = g_fopen(filename, "w+");
|
2003-08-17 07:26:17 +08:00
|
|
|
if (!l_fp)
|
|
|
|
{
|
2003-11-15 21:53:33 +08:00
|
|
|
g_message (_("Could not open '%s' for writing: %s"),
|
2004-07-31 05:29:45 +08:00
|
|
|
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
2003-08-17 07:26:17 +08:00
|
|
|
return -1;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
fprintf(l_fp, "%s\n", KEY_POINTFILE);
|
|
|
|
fprintf(l_fp, "VERSION 1.0\n\n");
|
|
|
|
|
|
|
|
fprintf(l_fp, "# points for upper and lower smooth curve (0.0 <= pt <= 1.0)\n");
|
|
|
|
fprintf(l_fp, "# there are upto 17 points where unused points are set to -1\n");
|
|
|
|
fprintf(l_fp, "# UPPERX UPPERY LOWERX LOWERY\n");
|
|
|
|
fprintf(l_fp, "\n");
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for(j = 0; j < 17; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
fprintf(l_fp, "%s %+.6f %+.6f %+.6f %+.6f\n", KEY_POINTS,
|
2003-11-06 23:27:05 +08:00
|
|
|
(float)cd->points[OUTLINE_UPPER][j][0],
|
1999-07-29 01:44:32 +08:00
|
|
|
(float)cd->points[OUTLINE_UPPER][j][1],
|
2003-11-06 23:27:05 +08:00
|
|
|
(float)cd->points[OUTLINE_LOWER][j][0],
|
1999-07-29 01:44:32 +08:00
|
|
|
(float)cd->points[OUTLINE_LOWER][j][1] );
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(l_fp, "\n");
|
|
|
|
fprintf(l_fp, "# y values for upper/lower freehand curve (0 <= y <= 255) \n");
|
|
|
|
fprintf(l_fp, "# there must be exactly 256 y values \n");
|
|
|
|
fprintf(l_fp, "# UPPER_Y LOWER_Y\n");
|
|
|
|
fprintf(l_fp, "\n");
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for (j = 0; j < 256; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
fprintf(l_fp, "%s %3d %3d\n", KEY_VAL_Y,
|
1999-07-29 01:44:32 +08:00
|
|
|
(int)cd->curve[OUTLINE_UPPER][j],
|
|
|
|
(int)cd->curve[OUTLINE_LOWER][j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(l_fp);
|
2003-08-27 13:44:57 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static int
|
2003-11-06 23:27:05 +08:00
|
|
|
p_load_pointfile (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
const gchar *filename)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint l_pi, l_ci, l_n, l_len;
|
1999-07-29 01:44:32 +08:00
|
|
|
FILE *l_fp;
|
|
|
|
char l_buff[2000];
|
|
|
|
float l_fux, l_fuy, l_flx, l_fly;
|
2003-08-27 13:44:57 +08:00
|
|
|
gint l_iuy, l_ily ;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2005-03-04 23:12:29 +08:00
|
|
|
l_fp = g_fopen(filename, "r");
|
2003-08-27 13:44:57 +08:00
|
|
|
if (!l_fp)
|
2003-08-17 07:26:17 +08:00
|
|
|
{
|
2003-11-15 21:53:33 +08:00
|
|
|
g_message (_("Could not open '%s' for reading: %s"),
|
2004-07-31 05:29:45 +08:00
|
|
|
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
2003-08-17 07:26:17 +08:00
|
|
|
return -1;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
l_pi = 0;
|
|
|
|
l_ci = 0;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
fgets (l_buff, 2000 - 1, l_fp);
|
|
|
|
if (strncmp(l_buff, KEY_POINTFILE, strlen(KEY_POINTFILE)) == 0)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
while (NULL != fgets (l_buff, 2000-1, l_fp))
|
|
|
|
{
|
|
|
|
l_len = strlen(KEY_POINTS);
|
|
|
|
if(strncmp(l_buff, KEY_POINTS, l_len) == 0)
|
|
|
|
{
|
|
|
|
l_n = sscanf(&l_buff[l_len], "%f %f %f %f", &l_fux, &l_fuy, &l_flx, &l_fly);
|
|
|
|
if((l_n == 4) && (l_pi < 17))
|
|
|
|
{
|
|
|
|
cd->points[OUTLINE_UPPER][l_pi][0] = l_fux;
|
|
|
|
cd->points[OUTLINE_UPPER][l_pi][1] = l_fuy;
|
|
|
|
cd->points[OUTLINE_LOWER][l_pi][0] = l_flx;
|
|
|
|
cd->points[OUTLINE_LOWER][l_pi][1] = l_fly;
|
|
|
|
l_pi++;
|
|
|
|
}
|
2004-07-31 05:29:45 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("warnig: BAD points[%d] in file %s are ignored\n", l_pi, filename);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
l_len = strlen(KEY_VAL_Y);
|
2003-08-27 13:44:57 +08:00
|
|
|
if (strncmp(l_buff, KEY_VAL_Y, l_len) == 0)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
l_n = sscanf(&l_buff[l_len], "%d %d", &l_iuy, &l_ily);
|
2003-08-27 13:44:57 +08:00
|
|
|
if ((l_n == 2) && (l_ci < 256))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->curve[OUTLINE_UPPER][l_ci] = l_iuy;
|
|
|
|
cd->curve[OUTLINE_LOWER][l_ci] = l_ily;
|
|
|
|
l_ci++;
|
|
|
|
}
|
2004-07-31 05:29:45 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("warnig: BAD y_vals[%d] in file %s are ignored\n", l_ci, filename);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(l_fp);
|
2003-08-27 13:44:57 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_cd_to_bval (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
BenderValues *bval)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint i,j;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for (i = 0; i < 2; i++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
for(j = 0; j < 256; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
bval->curve[i][j] = cd->curve[i][j];
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for(j = 0; j < 17; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
bval->points[i][j][0] = cd->points[i][j][0]; /* x */
|
|
|
|
bval->points[i][j][1] = cd->points[i][j][1]; /* y */
|
|
|
|
}
|
|
|
|
}
|
2003-08-27 13:44:57 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
bval->curve_type = cd->curve_type;
|
|
|
|
bval->smoothing = cd->smoothing;
|
|
|
|
bval->antialias = cd->antialias;
|
|
|
|
bval->work_on_copy = cd->work_on_copy;
|
|
|
|
bval->rotation = cd->rotation;
|
|
|
|
|
|
|
|
bval->total_steps = 0;
|
2003-08-27 13:44:57 +08:00
|
|
|
bval->current_step = 0.0;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
1999-07-29 01:44:32 +08:00
|
|
|
p_cd_from_bval(BenderDialog *cd, BenderValues *bval)
|
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint i,j;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for(i = 0; i < 2; i++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
for(j = 0; j < 256; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->curve[i][j] = bval->curve[i][j];
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for(j = 0; j < 17; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->points[i][j][0] = bval->points[i][j][0]; /* x */
|
|
|
|
cd->points[i][j][1] = bval->points[i][j][1]; /* y */
|
|
|
|
}
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
cd->curve_type = bval->curve_type;
|
|
|
|
cd->smoothing = bval->smoothing;
|
|
|
|
cd->antialias = bval->antialias;
|
|
|
|
cd->work_on_copy = bval->work_on_copy;
|
|
|
|
cd->rotation = bval->rotation;
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2000-02-08 06:23:02 +08:00
|
|
|
p_store_values (BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderValues l_bval;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
p_cd_to_bval(cd, &l_bval);
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_set_data(PLUG_IN_PROC, &l_bval, sizeof(l_bval));
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2000-02-08 06:23:02 +08:00
|
|
|
p_retrieve_values (BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderValues l_bval;
|
|
|
|
|
|
|
|
l_bval.total_steps = 0;
|
|
|
|
l_bval.current_step = -444.4; /* init with an invalid dummy value */
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_get_data (PLUG_IN_PROC, &l_bval);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (l_bval.total_steps == 0)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->bval_from = NULL;
|
|
|
|
cd->bval_to = NULL;
|
|
|
|
if(l_bval.current_step != -444.4)
|
|
|
|
{
|
|
|
|
/* last_value data was retrieved (and dummy value was overwritten) */
|
|
|
|
p_cd_from_bval(cd, &l_bval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-12-06 10:28:58 +08:00
|
|
|
cd->bval_from = g_new (BenderValues, 1);
|
|
|
|
cd->bval_to = g_new (BenderValues, 1);
|
|
|
|
cd->bval_curr = g_new (BenderValues, 1);
|
2002-06-14 04:32:21 +08:00
|
|
|
*cd->bval_curr = l_bval;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* it seems that we are called from GAP with "Varying Values" */
|
|
|
|
gimp_get_data(PLUG_IN_DATA_ITER_FROM, cd->bval_from);
|
|
|
|
gimp_get_data(PLUG_IN_DATA_ITER_TO, cd->bval_to);
|
2002-06-14 04:32:21 +08:00
|
|
|
*cd->bval_curr = l_bval;
|
1999-07-29 01:44:32 +08:00
|
|
|
p_cd_from_bval(cd, cd->bval_curr);
|
|
|
|
cd->work_on_copy = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
static void
|
|
|
|
p_delta_gdouble (double *val,
|
2004-07-31 05:29:45 +08:00
|
|
|
double val_from,
|
|
|
|
double val_to,
|
|
|
|
gint32 total_steps,
|
|
|
|
gdouble current_step)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
double delta;
|
|
|
|
|
|
|
|
if(total_steps < 1) return;
|
|
|
|
|
|
|
|
delta = ((double)(val_to - val_from) / (double)total_steps) * ((double)total_steps - current_step);
|
|
|
|
*val = val_from + delta;
|
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
static void
|
|
|
|
p_delta_gint32 (gint32 *val,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 val_from,
|
|
|
|
gint32 val_to,
|
|
|
|
gint32 total_steps,
|
|
|
|
gdouble current_step)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
double delta;
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (total_steps < 1) return;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
delta = ((double)(val_to - val_from) / (double)total_steps) * ((double)total_steps - current_step);
|
|
|
|
*val = val_from + delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_copy_points (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
int outline,
|
|
|
|
int xy,
|
|
|
|
int argc,
|
|
|
|
gdouble *floatarray)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
int j;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for (j = 0; j < 17; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->points[outline][j][xy] = -1;
|
|
|
|
}
|
2003-08-27 13:44:57 +08:00
|
|
|
for(j = 0; j < argc; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->points[outline][j][xy] = floatarray[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_copy_yval (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
int outline,
|
|
|
|
int argc,
|
|
|
|
gint8 *int8array)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
int j;
|
|
|
|
guchar fill;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
fill = MIDDLE;
|
2003-08-27 13:44:57 +08:00
|
|
|
for (j = 0; j < 256; j++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
if (j < argc)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
fill = cd->curve[outline][j] = int8array[j];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cd->curve[outline][j] = fill;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
|
|
|
/* curves machinery */
|
|
|
|
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static BenderDialog *
|
2000-08-22 09:26:57 +08:00
|
|
|
do_dialog (GimpDrawable *drawable)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderDialog *cd;
|
|
|
|
|
|
|
|
/* Init GTK */
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY, TRUE);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* The curve_bend dialog */
|
|
|
|
cd = bender_new_dialog (drawable);
|
|
|
|
|
|
|
|
/* create temporary image (with a small copy of drawable) for the preview */
|
|
|
|
cd->preview_image_id = p_create_pv_image(drawable, &cd->preview_layer_id1);
|
|
|
|
cd->preview_layer_id2 = -1;
|
|
|
|
|
|
|
|
if (!GTK_WIDGET_VISIBLE (cd->shell))
|
|
|
|
gtk_widget_show (cd->shell);
|
|
|
|
|
2005-01-16 07:18:30 +08:00
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW | UP_PREVIEW_EXPOSE);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
gtk_main ();
|
|
|
|
gdk_flush ();
|
|
|
|
|
|
|
|
gimp_image_delete(cd->preview_image_id);
|
|
|
|
cd->preview_image_id = -1;
|
|
|
|
cd->preview_layer_id1 = -1;
|
|
|
|
cd->preview_layer_id2 = -1;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
return cd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************/
|
|
|
|
/* Select Curves dialog */
|
|
|
|
/**************************/
|
|
|
|
|
|
|
|
static BenderDialog *
|
2000-08-22 09:26:57 +08:00
|
|
|
bender_new_dialog (GimpDrawable *drawable)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderDialog *cd;
|
2003-10-30 04:57:21 +08:00
|
|
|
GtkWidget *main_hbox;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *vbox2;
|
|
|
|
GtkWidget *abox;
|
|
|
|
GtkWidget *frame;
|
|
|
|
GtkWidget *upper, *lower;
|
|
|
|
GtkWidget *smooth, *freew;
|
|
|
|
GtkWidget *toggle;
|
|
|
|
GtkWidget *button;
|
|
|
|
GtkWidget *spinbutton;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkObject *data;
|
|
|
|
GdkDisplay *display;
|
|
|
|
gint i, j;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2001-12-06 10:28:58 +08:00
|
|
|
cd = g_new (BenderDialog, 1);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
cd->preview = FALSE;
|
|
|
|
cd->curve_type = SMOOTH;
|
|
|
|
cd->pixmap = NULL;
|
2004-05-18 19:28:13 +08:00
|
|
|
cd->filechooser = NULL;
|
1999-07-29 01:44:32 +08:00
|
|
|
cd->outline = OUTLINE_UPPER;
|
|
|
|
cd->show_progress = FALSE;
|
|
|
|
cd->smoothing = TRUE;
|
|
|
|
cd->antialias = TRUE;
|
|
|
|
cd->work_on_copy = FALSE;
|
|
|
|
cd->rotation = 0.0; /* vertical bend */
|
|
|
|
|
|
|
|
cd->drawable = drawable;
|
2001-06-15 04:07:38 +08:00
|
|
|
cd->color = gimp_drawable_is_rgb (cd->drawable->drawable_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
cd->run = FALSE;
|
|
|
|
cd->bval_from = NULL;
|
|
|
|
cd->bval_to = NULL;
|
|
|
|
cd->bval_curr = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
for (j = 0; j < 256; j++)
|
|
|
|
cd->curve[i][j] = MIDDLE;
|
|
|
|
|
|
|
|
cd->grab_point = -1;
|
|
|
|
for (i = 0; i < 2; i++)
|
2002-09-12 05:52:49 +08:00
|
|
|
{
|
1999-07-29 01:44:32 +08:00
|
|
|
for (j = 0; j < 17; j++)
|
2002-09-12 05:52:49 +08:00
|
|
|
{
|
2004-07-31 05:29:45 +08:00
|
|
|
cd->points[i][j][0] = -1;
|
|
|
|
cd->points[i][j][1] = -1;
|
2002-09-12 05:52:49 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
cd->points[i][0][0] = 0.0; /* x */
|
|
|
|
cd->points[i][0][1] = 0.5; /* y */
|
|
|
|
cd->points[i][16][0] = 1.0; /* x */
|
|
|
|
cd->points[i][16][1] = 0.5; /* y */
|
2002-09-12 05:52:49 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
p_retrieve_values(cd); /* Possibly retrieve data from a previous run */
|
|
|
|
|
|
|
|
/* The shell and main vbox */
|
2005-08-14 02:29:14 +08:00
|
|
|
cd->shell = gimp_dialog_new (_("Curve Bend"), PLUG_IN_BINARY,
|
2003-11-06 23:27:05 +08:00
|
|
|
NULL, 0,
|
2005-08-14 02:29:14 +08:00
|
|
|
gimp_standard_help_func, PLUG_IN_PROC,
|
2000-01-07 00:40:17 +08:00
|
|
|
|
2004-07-31 05:29:45 +08:00
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
2002-05-25 01:19:50 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
NULL);
|
2000-01-07 00:40:17 +08:00
|
|
|
|
2005-02-09 04:40:33 +08:00
|
|
|
gtk_dialog_set_alternative_button_order (GTK_DIALOG (cd->shell),
|
2005-09-06 05:40:29 +08:00
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
|
|
|
|
2005-09-10 02:07:31 +08:00
|
|
|
gimp_window_set_transient (GTK_WINDOW (cd->shell));
|
2005-02-09 04:40:33 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
g_signal_connect (cd->shell, "response",
|
|
|
|
G_CALLBACK (bender_response),
|
|
|
|
cd);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-08-31 22:02:10 +08:00
|
|
|
/* busy cursor */
|
2003-10-30 04:57:21 +08:00
|
|
|
display = gtk_widget_get_display (cd->shell);
|
2004-08-31 22:02:10 +08:00
|
|
|
cd->cursor_busy = gdk_cursor_new_for_display (display, GDK_WATCH);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
/* The main hbox */
|
2004-05-18 19:28:13 +08:00
|
|
|
main_hbox = gtk_hbox_new (FALSE, 12);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (cd->shell)->vbox), main_hbox);
|
|
|
|
gtk_widget_show (main_hbox);
|
|
|
|
|
|
|
|
/* Left side column */
|
2004-05-18 19:28:13 +08:00
|
|
|
vbox = gtk_vbox_new (FALSE, 12);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (main_hbox), vbox);
|
|
|
|
gtk_widget_show (vbox);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
/* Preview area, top of column */
|
2004-05-18 19:28:13 +08:00
|
|
|
frame = gimp_frame_new (_("Preview"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_widget_show (frame);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
vbox2 = gtk_vbox_new (FALSE, 6);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox2);
|
|
|
|
gtk_widget_show (vbox2);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox2), abox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (abox);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* The range drawing area */
|
|
|
|
frame = gtk_frame_new (NULL);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
|
|
|
gtk_container_add (GTK_CONTAINER (abox), frame);
|
2001-12-29 21:26:29 +08:00
|
|
|
gtk_widget_show (frame);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-07-31 05:29:45 +08:00
|
|
|
cd->pv_widget = gimp_preview_area_new ();
|
|
|
|
gtk_widget_set_size_request (cd->pv_widget,
|
|
|
|
PREVIEW_SIZE_X, PREVIEW_SIZE_Y);
|
1999-07-29 01:44:32 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), cd->pv_widget);
|
|
|
|
gtk_widget_show (cd->pv_widget);
|
2001-12-29 21:26:29 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 6);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_end (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
2002-09-08 00:31:32 +08:00
|
|
|
|
|
|
|
/* The preview button */
|
2005-08-23 08:18:08 +08:00
|
|
|
button = gtk_button_new_with_mnemonic (_("_Preview Once"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_widget_show (button);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-08 00:31:32 +08:00
|
|
|
G_CALLBACK (bender_preview_update_once),
|
|
|
|
cd);
|
|
|
|
|
|
|
|
/* The preview toggle */
|
2004-05-26 04:16:07 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("Automatic pre_view"));
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->preview);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2002-09-08 00:31:32 +08:00
|
|
|
G_CALLBACK (bender_preview_update),
|
|
|
|
cd);
|
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
/* Options area, bottom of column */
|
2004-05-18 19:28:13 +08:00
|
|
|
frame = gimp_frame_new (_("Options"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_end (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
vbox = gtk_vbox_new (FALSE, 6);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
gtk_widget_show (vbox);
|
|
|
|
|
|
|
|
/* Render Options */
|
2004-05-18 19:28:13 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 6);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
|
|
|
/* Rotate spinbutton */
|
2003-08-27 13:44:57 +08:00
|
|
|
label = gtk_label_new_with_mnemonic (_("Rotat_e:"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (label);
|
|
|
|
|
|
|
|
spinbutton = gimp_spin_button_new (&data,
|
|
|
|
0, 0.0, 360.0, 1, 45, 90,
|
|
|
|
0.5, 1);
|
|
|
|
cd->rotate_data = GTK_ADJUSTMENT (data);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (spinbutton);
|
|
|
|
|
|
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
|
|
|
|
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (cd->rotate_data, "value-changed",
|
2003-01-07 14:16:02 +08:00
|
|
|
G_CALLBACK (bender_rotate_adj_callback),
|
|
|
|
cd);
|
2002-09-12 05:52:49 +08:00
|
|
|
|
|
|
|
/* The smoothing toggle */
|
2003-08-27 13:44:57 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("Smoo_thing"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->smoothing);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2002-09-12 05:52:49 +08:00
|
|
|
G_CALLBACK (bender_smoothing_callback),
|
|
|
|
cd);
|
|
|
|
|
|
|
|
/* The antialiasing toggle */
|
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("_Antialiasing"));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->antialias);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2002-09-12 05:52:49 +08:00
|
|
|
G_CALLBACK (bender_antialias_callback),
|
|
|
|
cd);
|
|
|
|
|
2004-07-31 05:29:45 +08:00
|
|
|
/* The work_on_copy toggle */
|
2004-05-26 04:16:07 +08:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("Work on cop_y"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->work_on_copy);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (toggle, "toggled",
|
2002-09-12 05:52:49 +08:00
|
|
|
G_CALLBACK (bender_work_on_copy_callback),
|
|
|
|
cd);
|
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* The curves graph */
|
2004-05-18 19:28:13 +08:00
|
|
|
frame = gimp_frame_new (_("Modify Curves"));
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (main_hbox), frame);
|
2001-12-29 21:26:29 +08:00
|
|
|
gtk_widget_show (frame);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
vbox = gtk_vbox_new (FALSE, 12);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
gtk_widget_show (vbox);
|
2002-09-08 00:31:32 +08:00
|
|
|
|
|
|
|
abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), abox, FALSE, FALSE, 0);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_widget_show (abox);
|
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
cd->graph = gtk_drawing_area_new ();
|
2001-12-29 21:26:29 +08:00
|
|
|
gtk_widget_set_size_request (cd->graph,
|
|
|
|
GRAPH_WIDTH + RADIUS * 2,
|
|
|
|
GRAPH_HEIGHT + RADIUS * 2);
|
1999-07-29 01:44:32 +08:00
|
|
|
gtk_widget_set_events (cd->graph, GRAPH_MASK);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (abox), cd->graph);
|
1999-07-29 01:44:32 +08:00
|
|
|
gtk_widget_show (cd->graph);
|
2001-12-29 21:26:29 +08:00
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (cd->graph, "event",
|
2001-12-29 21:26:29 +08:00
|
|
|
G_CALLBACK (bender_graph_events),
|
|
|
|
cd);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 12);
|
2003-08-27 13:44:57 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
2003-11-15 02:05:39 +08:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Curve for Border"),
|
|
|
|
G_CALLBACK (bender_border_callback),
|
|
|
|
&cd->outline, cd->outline,
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-11-15 02:05:39 +08:00
|
|
|
_("_Upper"), OUTLINE_UPPER, &upper,
|
|
|
|
_("_Lower"), OUTLINE_LOWER, &lower,
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-11-15 02:05:39 +08:00
|
|
|
NULL);
|
2003-08-27 13:44:57 +08:00
|
|
|
|
|
|
|
g_object_set_data (G_OBJECT (upper), "cd", cd);
|
|
|
|
g_object_set_data (G_OBJECT (lower), "cd", cd);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (frame);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-11-15 02:05:39 +08:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Curve Type"),
|
|
|
|
G_CALLBACK (bender_type_callback),
|
|
|
|
&cd->curve_type, cd->curve_type,
|
2003-08-27 13:44:57 +08:00
|
|
|
|
2003-11-15 02:05:39 +08:00
|
|
|
_("Smoot_h"), SMOOTH, &smooth,
|
|
|
|
_("_Free"), GFREE, &freew,
|
2003-08-27 13:44:57 +08:00
|
|
|
|
2003-11-15 02:05:39 +08:00
|
|
|
NULL);
|
2003-08-27 13:44:57 +08:00
|
|
|
g_object_set_data (G_OBJECT (smooth), "cd", cd);
|
|
|
|
g_object_set_data (G_OBJECT (freew), "cd", cd);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (frame);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
/* hbox for curve options */
|
|
|
|
hbox = gtk_hbox_new (FALSE, 4);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
|
|
|
/* The Copy button */
|
|
|
|
button = gtk_button_new_with_mnemonic (_("_Copy"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
1999-07-29 01:44:32 +08:00
|
|
|
gtk_widget_show (button);
|
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
gimp_help_set_help_data (button,
|
|
|
|
_("Copy the active curve to the other border"), NULL);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-08 00:31:32 +08:00
|
|
|
G_CALLBACK (bender_copy_callback),
|
2001-12-29 21:26:29 +08:00
|
|
|
cd);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
/* The CopyInv button */
|
|
|
|
button = gtk_button_new_with_mnemonic (_("_Mirror"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (button);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
gimp_help_set_help_data (button,
|
2004-08-31 22:02:10 +08:00
|
|
|
_("Mirror the active curve to the other border"),
|
|
|
|
NULL);
|
2002-09-08 00:31:32 +08:00
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-08 00:31:32 +08:00
|
|
|
G_CALLBACK (bender_copy_inv_callback),
|
|
|
|
cd);
|
|
|
|
|
|
|
|
/* The Swap button */
|
|
|
|
button = gtk_button_new_with_mnemonic (_("S_wap"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (button);
|
|
|
|
|
|
|
|
gimp_help_set_help_data (button,
|
|
|
|
_("Swap the two curves"), NULL);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-08 00:31:32 +08:00
|
|
|
G_CALLBACK (bender_swap_callback),
|
2001-12-29 21:26:29 +08:00
|
|
|
cd);
|
|
|
|
|
2002-09-08 00:31:32 +08:00
|
|
|
/* The Reset button */
|
|
|
|
button = gtk_button_new_from_stock (GIMP_STOCK_RESET);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (button);
|
|
|
|
|
|
|
|
gimp_help_set_help_data (button,
|
|
|
|
_("Reset the active curve"), NULL);
|
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-08 00:31:32 +08:00
|
|
|
G_CALLBACK (bender_reset_callback),
|
|
|
|
cd);
|
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
/* hbox for curve load and save */
|
2002-09-08 00:31:32 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 4);
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
2002-09-08 00:31:32 +08:00
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
/* The Load button */
|
|
|
|
button = gtk_button_new_from_stock (GTK_STOCK_OPEN);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (button);
|
2002-09-08 00:31:32 +08:00
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
gimp_help_set_help_data (button,
|
|
|
|
_("Load the curves from a file"), NULL);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-12 05:52:49 +08:00
|
|
|
G_CALLBACK (bender_load_callback),
|
2001-12-29 21:26:29 +08:00
|
|
|
cd);
|
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
/* The Save button */
|
|
|
|
button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (button);
|
2001-12-29 21:26:29 +08:00
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
gimp_help_set_help_data (button,
|
|
|
|
_("Save the curves to a file"), NULL);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-01-07 14:16:02 +08:00
|
|
|
g_signal_connect (button, "clicked",
|
2002-09-12 05:52:49 +08:00
|
|
|
G_CALLBACK (bender_save_callback),
|
2001-12-29 21:26:29 +08:00
|
|
|
cd);
|
|
|
|
|
2002-09-12 05:52:49 +08:00
|
|
|
gtk_widget_show (main_hbox);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
return cd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_update (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
int update)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2004-08-31 22:02:10 +08:00
|
|
|
gint i;
|
|
|
|
gint other;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
if (update & UP_PREVIEW)
|
|
|
|
{
|
2004-08-31 22:02:10 +08:00
|
|
|
gdk_window_set_cursor (GTK_WIDGET (cd->shell)->window, cd->cursor_busy);
|
2003-08-27 13:44:57 +08:00
|
|
|
gdk_flush ();
|
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
if (cd->preview_layer_id2 >= 0)
|
|
|
|
gimp_image_remove_layer(cd->preview_image_id, cd->preview_layer_id2);
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
cd->preview_layer_id2 = p_main_bend(cd, gimp_drawable_get (cd->preview_layer_id1), TRUE /* work_on_copy*/ );
|
1999-07-29 01:44:32 +08:00
|
|
|
p_render_preview(cd, cd->preview_layer_id2);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
if (update & UP_DRAW)
|
2004-07-31 05:29:45 +08:00
|
|
|
gtk_widget_queue_draw (cd->pv_widget);
|
2003-08-27 13:44:57 +08:00
|
|
|
|
2004-08-31 22:02:10 +08:00
|
|
|
gdk_window_set_cursor (GTK_WIDGET (cd->shell)->window, NULL);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
if (update & UP_PREVIEW_EXPOSE)
|
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
/* on expose just redraw cd->preview_layer_id2
|
|
|
|
* that holds the bent version of the preview (if there is one)
|
1999-07-29 01:44:32 +08:00
|
|
|
*/
|
|
|
|
if (cd->preview_layer_id2 < 0)
|
2003-11-06 23:27:05 +08:00
|
|
|
cd->preview_layer_id2 = p_main_bend(cd, gimp_drawable_get (cd->preview_layer_id1), TRUE /* work_on_copy*/ );
|
1999-07-29 01:44:32 +08:00
|
|
|
p_render_preview(cd, cd->preview_layer_id2);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
if (update & UP_DRAW)
|
2004-07-31 05:29:45 +08:00
|
|
|
gtk_widget_queue_draw (cd->pv_widget);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
if ((update & UP_GRAPH) && (update & UP_DRAW) && cd->pixmap != NULL)
|
|
|
|
{
|
|
|
|
GdkPoint points[256];
|
|
|
|
|
|
|
|
/* Clear the pixmap */
|
|
|
|
gdk_draw_rectangle (cd->pixmap, cd->graph->style->bg_gc[GTK_STATE_NORMAL],
|
2004-07-31 05:29:45 +08:00
|
|
|
TRUE, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* Draw the grid lines */
|
|
|
|
for (i = 0; i < 5; i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL],
|
|
|
|
RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS,
|
|
|
|
GRAPH_WIDTH + RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS);
|
|
|
|
gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL],
|
|
|
|
i * (GRAPH_WIDTH / 4) + RADIUS, RADIUS,
|
|
|
|
i * (GRAPH_WIDTH / 4) + RADIUS, GRAPH_HEIGHT + RADIUS);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* Draw the other curve */
|
2003-08-27 13:44:57 +08:00
|
|
|
other = (cd->outline == 0) ? 1 : 0;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
for (i = 0; i < 256; i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
points[i].x = i + RADIUS;
|
|
|
|
points[i].y = 255 - cd->curve[other][i] + RADIUS;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
gdk_draw_points (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL], points, 256);
|
|
|
|
|
|
|
|
|
|
|
|
/* Draw the active curve */
|
|
|
|
for (i = 0; i < 256; i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
points[i].x = i + RADIUS;
|
|
|
|
points[i].y = 255 - cd->curve[cd->outline][i] + RADIUS;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
gdk_draw_points (cd->pixmap, cd->graph->style->black_gc, points, 256);
|
|
|
|
|
|
|
|
/* Draw the points */
|
|
|
|
if (cd->curve_type == SMOOTH)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
for (i = 0; i < 17; i++)
|
|
|
|
{
|
|
|
|
if (cd->points[cd->outline][i][0] != -1)
|
|
|
|
gdk_draw_arc (cd->pixmap, cd->graph->style->black_gc, TRUE,
|
|
|
|
(cd->points[cd->outline][i][0] * 255.0),
|
|
|
|
255 - (cd->points[cd->outline][i][1] * 255.0),
|
|
|
|
RADIUS * 2, RADIUS * 2, 0, 23040);
|
|
|
|
}
|
|
|
|
}
|
2001-08-31 22:01:47 +08:00
|
|
|
gdk_draw_drawable (cd->graph->window, cd->graph->style->black_gc, cd->pixmap,
|
2004-07-31 05:29:45 +08:00
|
|
|
0, 0, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_plot_curve (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
int p1,
|
|
|
|
int p2,
|
|
|
|
int p3,
|
|
|
|
int p4,
|
|
|
|
gint32 xmax,
|
|
|
|
gint32 ymax,
|
|
|
|
gint fix255)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
CRMatrix geometry;
|
|
|
|
CRMatrix tmp1, tmp2;
|
|
|
|
CRMatrix deltas;
|
|
|
|
double x, dx, dx2, dx3;
|
|
|
|
double y, dy, dy2, dy3;
|
|
|
|
double d, d2, d3;
|
|
|
|
int lastx, lasty;
|
|
|
|
gint32 newx, newy;
|
2003-11-06 23:27:05 +08:00
|
|
|
gint32 ntimes;
|
1999-07-29 01:44:32 +08:00
|
|
|
gint32 i;
|
|
|
|
|
|
|
|
/* construct the geometry matrix from the segment */
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
geometry[i][2] = 0;
|
|
|
|
geometry[i][3] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
geometry[0][0] = (cd->points[cd->outline][p1][0] * xmax);
|
|
|
|
geometry[1][0] = (cd->points[cd->outline][p2][0] * xmax);
|
|
|
|
geometry[2][0] = (cd->points[cd->outline][p3][0] * xmax);
|
|
|
|
geometry[3][0] = (cd->points[cd->outline][p4][0] * xmax);
|
|
|
|
|
|
|
|
geometry[0][1] = (cd->points[cd->outline][p1][1] * ymax);
|
|
|
|
geometry[1][1] = (cd->points[cd->outline][p2][1] * ymax);
|
|
|
|
geometry[2][1] = (cd->points[cd->outline][p3][1] * ymax);
|
|
|
|
geometry[3][1] = (cd->points[cd->outline][p4][1] * ymax);
|
|
|
|
|
|
|
|
/* subdivide the curve ntimes (1000) times */
|
|
|
|
ntimes = 4 * xmax;
|
|
|
|
/* ntimes can be adjusted to give a finer or coarser curve */
|
|
|
|
d = 1.0 / ntimes;
|
|
|
|
d2 = d * d;
|
|
|
|
d3 = d * d * d;
|
|
|
|
|
|
|
|
/* construct a temporary matrix for determining the forward differencing deltas */
|
|
|
|
tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
|
|
|
|
tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
|
|
|
|
tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
|
|
|
|
tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
|
|
|
|
|
|
|
|
/* compose the basis and geometry matrices */
|
|
|
|
bender_CR_compose (CR_basis, geometry, tmp1);
|
|
|
|
|
|
|
|
/* compose the above results to get the deltas matrix */
|
|
|
|
bender_CR_compose (tmp2, tmp1, deltas);
|
|
|
|
|
|
|
|
/* extract the x deltas */
|
|
|
|
x = deltas[0][0];
|
|
|
|
dx = deltas[1][0];
|
|
|
|
dx2 = deltas[2][0];
|
|
|
|
dx3 = deltas[3][0];
|
|
|
|
|
|
|
|
/* extract the y deltas */
|
|
|
|
y = deltas[0][1];
|
|
|
|
dy = deltas[1][1];
|
|
|
|
dy2 = deltas[2][1];
|
|
|
|
dy3 = deltas[3][1];
|
|
|
|
|
|
|
|
lastx = CLAMP (x, 0, xmax);
|
|
|
|
lasty = CLAMP (y, 0, ymax);
|
|
|
|
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (fix255)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->curve[cd->outline][lastx] = lasty;
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
else
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
cd->curve_ptr[cd->outline][lastx] = lasty;
|
|
|
|
if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* loop over the curve */
|
|
|
|
for (i = 0; i < ntimes; i++)
|
|
|
|
{
|
|
|
|
/* increment the x values */
|
|
|
|
x += dx;
|
|
|
|
dx += dx2;
|
|
|
|
dx2 += dx3;
|
|
|
|
|
|
|
|
/* increment the y values */
|
|
|
|
y += dy;
|
|
|
|
dy += dy2;
|
|
|
|
dy2 += dy3;
|
|
|
|
|
|
|
|
newx = CLAMP ((ROUND (x)), 0, xmax);
|
|
|
|
newy = CLAMP ((ROUND (y)), 0, ymax);
|
|
|
|
|
|
|
|
/* if this point is different than the last one...then draw it */
|
|
|
|
if ((lastx != newx) || (lasty != newy))
|
|
|
|
{
|
|
|
|
if(fix255)
|
|
|
|
{
|
|
|
|
/* use fixed array size (for the curve graph) */
|
|
|
|
cd->curve[cd->outline][newx] = newy;
|
2004-07-31 05:29:45 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* use dynamic allocated curve_ptr (for the real curve) */
|
|
|
|
cd->curve_ptr[cd->outline][newx] = newy;
|
|
|
|
|
|
|
|
if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lastx = newx;
|
|
|
|
lasty = newy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
bender_calculate_curve (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 xmax,
|
|
|
|
gint32 ymax,
|
|
|
|
gint fix255)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int points[17];
|
|
|
|
int num_pts;
|
|
|
|
int p1, p2, p3, p4;
|
|
|
|
int xmid;
|
|
|
|
int yfirst, ylast;
|
|
|
|
|
|
|
|
switch (cd->curve_type)
|
|
|
|
{
|
|
|
|
case GFREE:
|
|
|
|
break;
|
|
|
|
case SMOOTH:
|
|
|
|
/* cycle through the curves */
|
|
|
|
num_pts = 0;
|
|
|
|
for (i = 0; i < 17; i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
if (cd->points[cd->outline][i][0] != -1)
|
|
|
|
points[num_pts++] = i;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
xmid = xmax / 2;
|
|
|
|
/* Initialize boundary curve points */
|
|
|
|
if (num_pts != 0)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
1999-07-29 01:44:32 +08:00
|
|
|
if(fix255)
|
|
|
|
{
|
|
|
|
for (i = 0; i < (cd->points[cd->outline][points[0]][0] * 255); i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
cd->curve[cd->outline][i] = (cd->points[cd->outline][points[0]][1] * 255);
|
1999-07-29 01:44:32 +08:00
|
|
|
for (i = (cd->points[cd->outline][points[num_pts - 1]][0] * 255); i < 256; i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
cd->curve[cd->outline][i] = (cd->points[cd->outline][points[num_pts - 1]][1] * 255);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-07-31 05:29:45 +08:00
|
|
|
yfirst = cd->points[cd->outline][points[0]][1] * ymax;
|
|
|
|
ylast = cd->points[cd->outline][points[num_pts - 1]][1] * ymax;
|
|
|
|
|
|
|
|
for (i = 0; i < xmid; i++)
|
|
|
|
{
|
|
|
|
cd->curve_ptr[cd->outline][i] = yfirst;
|
|
|
|
}
|
|
|
|
for (i = xmid; i <= xmax; i++)
|
|
|
|
{
|
|
|
|
cd->curve_ptr[cd->outline][i] = ylast;
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < num_pts - 1; i++)
|
|
|
|
{
|
2004-07-31 05:29:45 +08:00
|
|
|
p1 = (i == 0) ? points[i] : points[(i - 1)];
|
|
|
|
p2 = points[i];
|
|
|
|
p3 = points[(i + 1)];
|
|
|
|
p4 = (i == (num_pts - 2)) ? points[(num_pts - 1)] : points[(i + 2)];
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-07-31 05:29:45 +08:00
|
|
|
bender_plot_curve (cd, p1, p2, p3, p4, xmax, ymax, fix255);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-02-21 19:00:28 +08:00
|
|
|
bender_rotate_adj_callback (GtkAdjustment *adjustment,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer client_data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) client_data;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2000-02-21 19:00:28 +08:00
|
|
|
if (adjustment->value != cd->rotation)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2000-02-21 19:00:28 +08:00
|
|
|
cd->rotation = adjustment->value;
|
2003-11-06 23:27:05 +08:00
|
|
|
if (cd->preview)
|
2003-08-27 13:44:57 +08:00
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-08-27 13:44:57 +08:00
|
|
|
bender_border_callback (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderDialog *cd;
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
gimp_radio_button_update (widget, data);
|
|
|
|
cd = g_object_get_data (G_OBJECT (widget), "cd");
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
2003-11-06 23:27:05 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
static void
|
2003-08-27 13:44:57 +08:00
|
|
|
bender_type_callback (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderDialog *cd;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
gimp_radio_button_update (widget, data);
|
|
|
|
cd = g_object_get_data (G_OBJECT (widget), "cd");
|
|
|
|
if (cd->curve_type == SMOOTH)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint i;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* pick representative points from the curve and make them control points */
|
|
|
|
for (i = 0; i <= 8; i++)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
gint index = CLAMP ((i * 32), 0, 255);
|
|
|
|
cd->points[cd->outline][i * 2][0] = (gdouble)index / 255.0;
|
|
|
|
cd->points[cd->outline][i * 2][1] = (gdouble)cd->curve[cd->outline][index] / 255.0;
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
bender_calculate_curve (cd, 255, 255, TRUE);
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
if (cd->preview)
|
2004-07-31 05:29:45 +08:00
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
else
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_reset_callback (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer client_data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
BenderDialog *cd;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
cd = (BenderDialog *) client_data;
|
|
|
|
|
|
|
|
/* Initialize the values */
|
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
cd->curve[cd->outline][i] = MIDDLE;
|
|
|
|
|
|
|
|
cd->grab_point = -1;
|
|
|
|
for (i = 0; i < 17; i++)
|
|
|
|
{
|
|
|
|
cd->points[cd->outline][i][0] = -1;
|
|
|
|
cd->points[cd->outline][i][1] = -1;
|
|
|
|
}
|
|
|
|
cd->points[cd->outline][0][0] = 0.0; /* x */
|
|
|
|
cd->points[cd->outline][0][1] = 0.5; /* y */
|
|
|
|
cd->points[cd->outline][16][0] = 1.0; /* x */
|
|
|
|
cd->points[cd->outline][16][1] = 0.5; /* y */
|
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
if (cd->preview)
|
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_copy_callback (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer client_data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog *) client_data;
|
1999-07-29 01:44:32 +08:00
|
|
|
int i;
|
|
|
|
int other;
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
other = (cd->outline) ? 0 : 1;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
for (i = 0; i < 17; i++)
|
|
|
|
{
|
|
|
|
cd->points[other][i][0] = cd->points[cd->outline][i][0];
|
|
|
|
cd->points[other][i][1] = cd->points[cd->outline][i][1];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i= 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
cd->curve[other][i] = cd->curve[cd->outline][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
if (cd->preview)
|
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_copy_inv_callback (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer client_data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) client_data;
|
1999-07-29 01:44:32 +08:00
|
|
|
int i;
|
|
|
|
int other;
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
other = (cd->outline) ? 0 : 1;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
for (i = 0; i < 17; i++)
|
|
|
|
{
|
|
|
|
cd->points[other][i][0] = cd->points[cd->outline][i][0]; /* x */
|
|
|
|
cd->points[other][i][1] = 1.0 - cd->points[cd->outline][i][1]; /* y */
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i= 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
cd->curve[other][i] = 255 - cd->curve[cd->outline][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
if (cd->preview)
|
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_swap_callback (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer client_data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
1999-08-17 03:33:35 +08:00
|
|
|
#define SWAP_VALUE(a, b, h) { h=a; a=b; b=h; }
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) client_data;
|
1999-07-29 01:44:32 +08:00
|
|
|
int i;
|
|
|
|
int other;
|
|
|
|
gdouble hd;
|
|
|
|
guchar hu;
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
other = (cd->outline) ? 0 : 1;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
for (i = 0; i < 17; i++)
|
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
SWAP_VALUE(cd->points[other][i][0], cd->points[cd->outline][i][0], hd); /* x */
|
1999-07-29 01:44:32 +08:00
|
|
|
SWAP_VALUE(cd->points[other][i][1], cd->points[cd->outline][i][1], hd); /* y */
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i= 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
SWAP_VALUE(cd->curve[other][i], cd->curve[cd->outline][i], hu);
|
|
|
|
}
|
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
if (cd->preview)
|
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
bender_response (GtkWidget *widget,
|
|
|
|
gint response_id,
|
|
|
|
BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
|
|
cd->run = TRUE;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (cd->shell));
|
|
|
|
gtk_main_quit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-01-07 00:40:17 +08:00
|
|
|
bender_preview_update (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) data;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
cd->preview = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
if(cd->preview)
|
2003-08-27 13:44:57 +08:00
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-01-07 00:40:17 +08:00
|
|
|
bender_preview_update_once (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) data;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-05-18 19:28:13 +08:00
|
|
|
p_points_save_to_file_response (GtkWidget *dialog,
|
|
|
|
gint response_id,
|
|
|
|
BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-19 22:51:52 +08:00
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
|
|
{
|
2004-05-18 19:28:13 +08:00
|
|
|
gchar *filename;
|
|
|
|
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-11-19 22:51:52 +08:00
|
|
|
p_save_pointfile (cd, filename);
|
2004-05-18 19:28:13 +08:00
|
|
|
|
|
|
|
g_free (filename);
|
2003-11-19 22:51:52 +08:00
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
gtk_widget_destroy (dialog);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-05-18 19:28:13 +08:00
|
|
|
p_points_load_from_file_response (GtkWidget *dialog,
|
|
|
|
gint response_id,
|
|
|
|
BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-19 22:51:52 +08:00
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
|
|
{
|
2004-05-18 19:28:13 +08:00
|
|
|
gchar *filename;
|
|
|
|
|
|
|
|
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
2003-08-27 13:44:57 +08:00
|
|
|
|
2003-11-19 22:51:52 +08:00
|
|
|
p_load_pointfile (cd, filename);
|
|
|
|
bender_update (cd, UP_ALL);
|
2004-05-18 19:28:13 +08:00
|
|
|
|
|
|
|
g_free (filename);
|
2003-11-19 22:51:52 +08:00
|
|
|
}
|
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
gtk_widget_destroy (dialog);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-11-19 22:51:52 +08:00
|
|
|
bender_load_callback (GtkWidget *w,
|
|
|
|
BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2004-05-18 19:28:13 +08:00
|
|
|
if (! cd->filechooser)
|
2003-11-19 22:51:52 +08:00
|
|
|
{
|
2004-05-18 19:28:13 +08:00
|
|
|
cd->filechooser =
|
2005-08-23 08:18:08 +08:00
|
|
|
gtk_file_chooser_dialog_new (_("Load Curve Points from File"),
|
2004-05-18 19:28:13 +08:00
|
|
|
GTK_WINDOW (gtk_widget_get_toplevel (w)),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
|
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_OPEN, GTK_RESPONSE_OK,
|
|
|
|
|
|
|
|
NULL);
|
|
|
|
|
2005-04-08 01:10:05 +08:00
|
|
|
gtk_dialog_set_alternative_button_order (GTK_DIALOG (cd->filechooser),
|
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
gtk_dialog_set_default_response (GTK_DIALOG (cd->filechooser),
|
|
|
|
GTK_RESPONSE_OK);
|
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
g_signal_connect (cd->filechooser, "response",
|
|
|
|
G_CALLBACK (p_points_load_from_file_response),
|
|
|
|
cd);
|
|
|
|
g_signal_connect (cd->filechooser, "destroy",
|
|
|
|
G_CALLBACK (gtk_widget_destroyed),
|
|
|
|
&cd->filechooser);
|
2003-11-19 22:51:52 +08:00
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
gtk_window_present (GTK_WINDOW (cd->filechooser));
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-11-19 22:51:52 +08:00
|
|
|
bender_save_callback (GtkWidget *w,
|
|
|
|
BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2004-05-18 19:28:13 +08:00
|
|
|
if (! cd->filechooser)
|
2003-11-19 22:51:52 +08:00
|
|
|
{
|
2004-05-18 19:28:13 +08:00
|
|
|
cd->filechooser =
|
2005-08-23 08:18:08 +08:00
|
|
|
gtk_file_chooser_dialog_new (_("Save Curve Points to File"),
|
2004-05-18 19:28:13 +08:00
|
|
|
GTK_WINDOW (gtk_widget_get_toplevel (w)),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
NULL);
|
2003-11-10 06:44:45 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
g_signal_connect (cd->filechooser, "response",
|
|
|
|
G_CALLBACK (p_points_save_to_file_response),
|
|
|
|
cd);
|
|
|
|
g_signal_connect (cd->filechooser, "destroy",
|
|
|
|
G_CALLBACK (gtk_widget_destroyed),
|
|
|
|
&cd->filechooser);
|
|
|
|
|
|
|
|
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (cd->filechooser),
|
|
|
|
"curve_bend.points");
|
|
|
|
}
|
2001-12-29 21:26:29 +08:00
|
|
|
|
2004-05-18 19:28:13 +08:00
|
|
|
gtk_window_present (GTK_WINDOW (cd->filechooser));
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_smoothing_callback (GtkWidget *w,
|
2003-11-19 22:51:52 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) data;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
cd->smoothing = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
if(cd->preview)
|
2003-08-27 13:44:57 +08:00
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_antialias_callback (GtkWidget *w,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) data;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
cd->antialias = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
if (cd->preview)
|
2003-08-27 13:44:57 +08:00
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_work_on_copy_callback (GtkWidget *w,
|
2004-07-31 05:29:45 +08:00
|
|
|
gpointer data)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
BenderDialog *cd = (BenderDialog*) data;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
cd->work_on_copy = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static gboolean
|
1999-07-29 01:44:32 +08:00
|
|
|
bender_graph_events (GtkWidget *widget,
|
2004-07-31 05:29:45 +08:00
|
|
|
GdkEvent *event,
|
|
|
|
BenderDialog *cd)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
static GdkCursorType cursor_type = GDK_TOP_LEFT_ARROW;
|
|
|
|
GdkCursorType new_type;
|
|
|
|
GdkEventButton *bevent;
|
|
|
|
GdkEventMotion *mevent;
|
|
|
|
int i;
|
|
|
|
int tx, ty;
|
|
|
|
int x, y;
|
|
|
|
int closest_point;
|
|
|
|
int distance;
|
|
|
|
int x1, x2, y1, y2;
|
|
|
|
|
|
|
|
new_type = GDK_X_CURSOR;
|
|
|
|
closest_point = 0;
|
|
|
|
|
|
|
|
/* get the pointer position */
|
|
|
|
gdk_window_get_pointer (cd->graph->window, &tx, &ty, NULL);
|
|
|
|
x = CLAMP ((tx - RADIUS), 0, 255);
|
|
|
|
y = CLAMP ((ty - RADIUS), 0, 255);
|
|
|
|
|
|
|
|
distance = G_MAXINT;
|
|
|
|
for (i = 0; i < 17; i++)
|
|
|
|
{
|
|
|
|
if (cd->points[cd->outline][i][0] != -1)
|
2004-07-31 05:29:45 +08:00
|
|
|
if (abs (x - (cd->points[cd->outline][i][0] * 255.0)) < distance)
|
|
|
|
{
|
|
|
|
distance = abs (x - (cd->points[cd->outline][i][0] * 255.0));
|
|
|
|
closest_point = i;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
if (distance > MIN_DISTANCE)
|
|
|
|
closest_point = (x + 8) / 16;
|
|
|
|
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case GDK_EXPOSE:
|
|
|
|
if (cd->pixmap == NULL)
|
2004-07-31 05:29:45 +08:00
|
|
|
cd->pixmap = gdk_pixmap_new (cd->graph->window,
|
|
|
|
GRAPH_WIDTH + RADIUS * 2,
|
|
|
|
GRAPH_HEIGHT + RADIUS * 2, -1);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
bevent = (GdkEventButton *) event;
|
|
|
|
new_type = GDK_TCROSS;
|
|
|
|
|
|
|
|
switch (cd->curve_type)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
case SMOOTH:
|
|
|
|
/* determine the leftmost and rightmost points */
|
|
|
|
cd->leftmost = -1;
|
|
|
|
for (i = closest_point - 1; i >= 0; i--)
|
|
|
|
if (cd->points[cd->outline][i][0] != -1)
|
|
|
|
{
|
|
|
|
cd->leftmost = (cd->points[cd->outline][i][0] * 255.0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cd->rightmost = 256;
|
|
|
|
for (i = closest_point + 1; i < 17; i++)
|
|
|
|
if (cd->points[cd->outline][i][0] != -1)
|
|
|
|
{
|
|
|
|
cd->rightmost = (cd->points[cd->outline][i][0] * 255.0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cd->grab_point = closest_point;
|
|
|
|
cd->points[cd->outline][cd->grab_point][0] = (gdouble)x / 255.0;
|
|
|
|
cd->points[cd->outline][cd->grab_point][1] = (gdouble)(255 - y) / 255.0;
|
|
|
|
|
|
|
|
bender_calculate_curve (cd, 255, 255, TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GFREE:
|
|
|
|
cd->curve[cd->outline][x] = 255 - y;
|
|
|
|
cd->grab_point = x;
|
|
|
|
cd->last = y;
|
|
|
|
break;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
new_type = GDK_FLEUR;
|
|
|
|
cd->grab_point = -1;
|
|
|
|
|
|
|
|
if (cd->preview)
|
2004-07-31 05:29:45 +08:00
|
|
|
bender_update (cd, UP_PREVIEW | UP_DRAW);
|
1999-07-29 01:44:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
mevent = (GdkEventMotion *) event;
|
|
|
|
|
|
|
|
if (mevent->is_hint)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
mevent->x = tx;
|
|
|
|
mevent->y = ty;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
switch (cd->curve_type)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
case SMOOTH:
|
|
|
|
/* If no point is grabbed... */
|
|
|
|
if (cd->grab_point == -1)
|
|
|
|
{
|
|
|
|
if (cd->points[cd->outline][closest_point][0] != -1)
|
|
|
|
new_type = GDK_FLEUR;
|
|
|
|
else
|
|
|
|
new_type = GDK_TCROSS;
|
|
|
|
}
|
|
|
|
/* Else, drag the grabbed point */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_type = GDK_TCROSS;
|
|
|
|
|
|
|
|
cd->points[cd->outline][cd->grab_point][0] = -1;
|
|
|
|
|
|
|
|
if (x > cd->leftmost && x < cd->rightmost)
|
|
|
|
{
|
|
|
|
closest_point = (x + 8) / 16;
|
|
|
|
if (cd->points[cd->outline][closest_point][0] == -1)
|
|
|
|
cd->grab_point = closest_point;
|
|
|
|
cd->points[cd->outline][cd->grab_point][0] = (gdouble)x / 255.0;
|
|
|
|
cd->points[cd->outline][cd->grab_point][1] = (gdouble)(255 - y) / 255.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bender_calculate_curve (cd, 255, 255, TRUE);
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GFREE:
|
|
|
|
if (cd->grab_point != -1)
|
|
|
|
{
|
|
|
|
if (cd->grab_point > x)
|
|
|
|
{
|
|
|
|
x1 = x;
|
|
|
|
x2 = cd->grab_point;
|
|
|
|
y1 = y;
|
|
|
|
y2 = cd->last;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x1 = cd->grab_point;
|
|
|
|
x2 = x;
|
|
|
|
y1 = cd->last;
|
|
|
|
y2 = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x2 != x1)
|
|
|
|
for (i = x1; i <= x2; i++)
|
|
|
|
cd->curve[cd->outline][i] = 255 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1));
|
|
|
|
else
|
|
|
|
cd->curve[cd->outline][x] = 255 - y;
|
|
|
|
|
|
|
|
cd->grab_point = x;
|
|
|
|
cd->last = y;
|
|
|
|
|
|
|
|
bender_update (cd, UP_GRAPH | UP_DRAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mevent->state & GDK_BUTTON1_MASK)
|
|
|
|
new_type = GDK_TCROSS;
|
|
|
|
else
|
|
|
|
new_type = GDK_PENCIL;
|
|
|
|
break;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
if (new_type != cursor_type)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
cursor_type = new_type;
|
|
|
|
/* change_win_cursor (cd->graph->window, cursor_type); */
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bender_CR_compose (CRMatrix a,
|
2004-07-31 05:29:45 +08:00
|
|
|
CRMatrix b,
|
|
|
|
CRMatrix ab)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gint i, j;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
{
|
|
|
|
ab[i][j] = (a[i][0] * b[0][j] +
|
|
|
|
a[i][1] * b[1][j] +
|
|
|
|
a[i][2] * b[2][j] +
|
|
|
|
a[i][3] * b[3][j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2000-01-07 00:40:17 +08:00
|
|
|
p_render_preview (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 layer_id)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2004-07-31 05:29:45 +08:00
|
|
|
guchar l_pixel[4];
|
|
|
|
guchar *l_buf, *l_ptr;
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpDrawable *l_pv_drawable;
|
2004-07-31 05:29:45 +08:00
|
|
|
gint l_x, l_y;
|
|
|
|
gint l_ofx, l_ofy;
|
|
|
|
t_GDRW l_gdrw;
|
|
|
|
t_GDRW *gdrw;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
l_pv_drawable = gimp_drawable_get (layer_id);
|
|
|
|
|
2004-07-31 05:29:45 +08:00
|
|
|
l_ptr = l_buf = g_new (guchar, PREVIEW_BPP * PREVIEW_SIZE_X * PREVIEW_SIZE_Y);
|
1999-07-29 01:44:32 +08:00
|
|
|
gdrw = &l_gdrw;
|
|
|
|
p_init_gdrw(gdrw, l_pv_drawable, FALSE, FALSE);
|
|
|
|
|
|
|
|
/* offsets to set bend layer to preview center */
|
|
|
|
l_ofx = (l_pv_drawable->width / 2) - (PREVIEW_SIZE_X / 2);
|
|
|
|
l_ofy = (l_pv_drawable->height / 2) - (PREVIEW_SIZE_Y / 2);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* render preview */
|
2003-08-27 13:44:57 +08:00
|
|
|
for (l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
for (l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2004-07-31 05:29:45 +08:00
|
|
|
p_get_pixel(gdrw, l_x + l_ofx, l_y + l_ofy, &l_pixel[0]);
|
|
|
|
|
|
|
|
if (cd->color)
|
|
|
|
{
|
|
|
|
l_ptr[0] = l_pixel[0];
|
|
|
|
l_ptr[1] = l_pixel[1];
|
|
|
|
l_ptr[2] = l_pixel[2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l_ptr[0] = l_pixel[0];
|
|
|
|
l_ptr[1] = l_pixel[0];
|
|
|
|
l_ptr[2] = l_pixel[0];
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2004-07-31 05:29:45 +08:00
|
|
|
l_ptr[3] = l_pixel[gdrw->index_alpha];
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
l_ptr += PREVIEW_BPP;
|
|
|
|
}
|
|
|
|
}
|
2004-07-31 05:29:45 +08:00
|
|
|
gimp_preview_area_draw (GIMP_PREVIEW_AREA (cd->pv_widget),
|
|
|
|
0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
|
|
|
|
GIMP_RGBA_IMAGE,
|
|
|
|
l_buf,
|
|
|
|
PREVIEW_BPP * PREVIEW_SIZE_X);
|
|
|
|
g_free (l_buf);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2004-07-31 05:29:45 +08:00
|
|
|
p_end_gdrw(gdrw);
|
|
|
|
} /* end p_render_preview */
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* ===================================================== */
|
|
|
|
/* curve_bend worker procedures */
|
|
|
|
/* ===================================================== */
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_stretch_curves (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 xmax,
|
|
|
|
gint32 ymax)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
gint32 l_x1, l_x2;
|
|
|
|
gdouble l_ya, l_yb;
|
|
|
|
gdouble l_rest;
|
|
|
|
int l_outline;
|
|
|
|
|
|
|
|
for(l_outline = 0; l_outline < 2; l_outline++)
|
|
|
|
{
|
|
|
|
for(l_x1 = 0; l_x1 <= xmax; l_x1++)
|
|
|
|
{
|
|
|
|
l_x2 = (l_x1 * 255) / xmax;
|
|
|
|
if((xmax <= 255) && (l_x2 < 255))
|
|
|
|
{
|
|
|
|
cd->curve_ptr[l_outline][l_x1] = ROUND((cd->curve[l_outline][l_x2] * ymax) / 255);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* interpolate */
|
|
|
|
l_rest = (((gdouble)l_x1 * 255.0) / (gdouble)xmax) - l_x2;
|
|
|
|
l_ya = cd->curve[l_outline][l_x2]; /* y of this point */
|
|
|
|
l_yb = cd->curve[l_outline][l_x2 +1]; /* y of next point */
|
|
|
|
cd->curve_ptr[l_outline][l_x1] = ROUND (((l_ya + ((l_yb -l_ya) * l_rest)) * ymax) / 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int l_debugY;
|
|
|
|
l_debugY = ROUND((cd->curve[l_outline][l_x2] * ymax) / 255);
|
2003-11-06 23:27:05 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
bender_init_min_max (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 xmax)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
cd->min2[i] = 65000;
|
|
|
|
cd->max2[i] = 0;
|
|
|
|
for (j = 0; j <= xmax; j++)
|
|
|
|
{
|
|
|
|
if(cd->curve_ptr[i][j] > cd->max2[i])
|
|
|
|
{
|
|
|
|
cd->max2[i] = cd->curve_ptr[i][j];
|
|
|
|
}
|
|
|
|
if(cd->curve_ptr[i][j] < cd->min2[i])
|
|
|
|
{
|
|
|
|
cd->min2[i] = cd->curve_ptr[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* for UPPER outline : y-zero line is assumed at the min leftmost or rightmost point */
|
|
|
|
cd->zero2[OUTLINE_UPPER] = MIN(cd->curve_ptr[OUTLINE_UPPER][0], cd->curve_ptr[OUTLINE_UPPER][xmax]);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
/* for LOWER outline : y-zero line is assumed at the min leftmost or rightmost point */
|
|
|
|
cd->zero2[OUTLINE_LOWER] = MAX(cd->curve_ptr[OUTLINE_LOWER][0], cd->curve_ptr[OUTLINE_LOWER][xmax]);
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static gint32
|
2003-11-06 23:27:05 +08:00
|
|
|
p_curve_get_dy (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x,
|
|
|
|
gint32 drawable_width,
|
|
|
|
gint32 total_steps,
|
|
|
|
gdouble current_step)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
/* get y values of both upper and lower curve,
|
|
|
|
* and return the iterated value inbetween
|
|
|
|
*/
|
2003-08-27 13:44:57 +08:00
|
|
|
gdouble l_y1, l_y2;
|
|
|
|
gdouble delta;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
l_y1 = cd->zero2[OUTLINE_UPPER] - cd->curve_ptr[OUTLINE_UPPER][x];
|
|
|
|
l_y2 = cd->zero2[OUTLINE_LOWER] - cd->curve_ptr[OUTLINE_LOWER][x];
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
delta = ((double)(l_y2 - l_y1) / (double)(total_steps -1)) * current_step;
|
2003-08-27 13:44:57 +08:00
|
|
|
return SIGNED_ROUND(l_y1 + delta);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static gint32
|
2003-11-06 23:27:05 +08:00
|
|
|
p_upper_curve_extend (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 drawable_width,
|
|
|
|
gint32 drawable_height)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
gint32 l_y1, l_y2;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
l_y1 = cd->max2[OUTLINE_UPPER] - cd->zero2[OUTLINE_UPPER];
|
|
|
|
l_y2 = (cd->max2[OUTLINE_LOWER] - cd->zero2[OUTLINE_LOWER]) - drawable_height;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
return MAX(l_y1, l_y2);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static gint32
|
2003-11-06 23:27:05 +08:00
|
|
|
p_lower_curve_extend (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 drawable_width,
|
|
|
|
gint32 drawable_height)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
gint32 l_y1, l_y2;
|
|
|
|
|
|
|
|
l_y1 = cd->zero2[OUTLINE_LOWER] - cd->min2[OUTLINE_LOWER];
|
|
|
|
l_y2 = (cd->zero2[OUTLINE_UPPER] - cd->min2[OUTLINE_UPPER]) - drawable_height;
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
return MAX(l_y1, l_y2);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2000-02-08 06:23:02 +08:00
|
|
|
p_end_gdrw (t_GDRW *gdrw)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gimp_pixel_fetcher_destroy (gdrw->pft);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2004-03-13 06:46:25 +08:00
|
|
|
p_init_gdrw (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
GimpDrawable *drawable,
|
|
|
|
int dirty,
|
|
|
|
int shadow)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
gdrw->drawable = drawable;
|
2004-03-13 06:46:25 +08:00
|
|
|
gdrw->pft = gimp_pixel_fetcher_new (drawable, FALSE);
|
2003-12-27 01:26:36 +08:00
|
|
|
gimp_pixel_fetcher_set_edge_mode (gdrw->pft, GIMP_PIXEL_FETCHER_EDGE_BLACK);
|
1999-07-29 01:44:32 +08:00
|
|
|
gdrw->tile_width = gimp_tile_width ();
|
|
|
|
gdrw->tile_height = gimp_tile_height ();
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
gimp_drawable_mask_bounds (drawable->drawable_id, &gdrw->x1,
|
2004-07-31 05:29:45 +08:00
|
|
|
&gdrw->y1, &gdrw->x2, &gdrw->y2);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
gdrw->bpp = drawable->bpp;
|
2001-06-15 04:07:38 +08:00
|
|
|
if (gimp_drawable_has_alpha(drawable->drawable_id))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
/* index of the alpha channelbyte {1|3} */
|
|
|
|
gdrw->index_alpha = gdrw->bpp - 1;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
2003-08-27 13:44:57 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
gdrw->index_alpha = 0; /* there is no alpha channel */
|
2003-11-06 23:27:05 +08:00
|
|
|
}
|
2003-08-27 13:44:57 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* get pixel value
|
|
|
|
* return light transparent black gray pixel if out of bounds
|
|
|
|
* (should occur in the previews only)
|
|
|
|
*/
|
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_get_pixel (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x,
|
|
|
|
gint32 y,
|
|
|
|
guchar *pixel)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
pixel[1] = 255;
|
2003-08-27 13:44:57 +08:00
|
|
|
pixel[3] = 255; /* simulate full visible alpha channel */
|
2003-12-27 01:26:36 +08:00
|
|
|
gimp_pixel_fetcher_get_pixel (gdrw->pft, x, y, pixel);
|
2003-08-27 13:44:57 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_put_pixel (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x,
|
|
|
|
gint32 y,
|
|
|
|
guchar *pixel)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
gimp_pixel_fetcher_put_pixel (gdrw->pft, x, y, pixel);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_put_mix_pixel (t_GDRW *gdrw,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 x,
|
|
|
|
gint32 y,
|
|
|
|
guchar *color,
|
|
|
|
gint32 nb_curvy,
|
|
|
|
gint32 nb2_curvy,
|
|
|
|
gint32 curvy)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
guchar l_pixel[4];
|
|
|
|
guchar l_mixmask;
|
|
|
|
gint l_idx;
|
|
|
|
gint l_diff;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
l_mixmask = 255 - 96;
|
|
|
|
l_diff = abs(nb_curvy - curvy);
|
2003-08-27 13:44:57 +08:00
|
|
|
if (l_diff == 0)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
l_mixmask = 255 - 48;
|
|
|
|
l_diff = abs(nb2_curvy - curvy);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (l_diff == 0)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
/* last 2 neighbours were not shifted against current pixel, do not mix */
|
1999-07-29 01:44:32 +08:00
|
|
|
p_put_pixel(gdrw, x, y, color);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
/* get left neighbour pixel */
|
1999-07-29 01:44:32 +08:00
|
|
|
p_get_pixel(gdrw, x-1, y, &l_pixel[0]);
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (l_pixel[gdrw->index_alpha] < 10)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
/* neighbour is (nearly or full) transparent, do not mix */
|
1999-07-29 01:44:32 +08:00
|
|
|
p_put_pixel(gdrw, x, y, color);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for (l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
/* mix in left neighbour color */
|
|
|
|
l_pixel[l_idx] = MIX_CHANNEL(color[l_idx], l_pixel[l_idx], l_mixmask);
|
|
|
|
}
|
|
|
|
|
|
|
|
l_pixel[gdrw->index_alpha] = color[gdrw->index_alpha];
|
|
|
|
p_put_pixel(gdrw, x, y, &l_pixel[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_clear_drawable
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2000-08-22 09:26:57 +08:00
|
|
|
p_clear_drawable (GimpDrawable *drawable)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpPixelRgn pixel_rgn;
|
2004-02-09 22:43:46 +08:00
|
|
|
gpointer pr;
|
|
|
|
guint l_row;
|
|
|
|
guchar *l_ptr;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
gimp_pixel_rgn_init (&pixel_rgn, drawable,
|
2004-07-31 05:29:45 +08:00
|
|
|
0, 0, drawable->width, drawable->height,
|
|
|
|
TRUE, /* dirty */
|
|
|
|
FALSE /* shadow */
|
|
|
|
);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* clear the drawable with 0 Bytes (black full-transparent pixels) */
|
|
|
|
for (pr = gimp_pixel_rgns_register (1, &pixel_rgn);
|
2004-07-31 05:29:45 +08:00
|
|
|
pr != NULL; pr = gimp_pixel_rgns_process (pr))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
l_ptr = pixel_rgn.data;
|
|
|
|
for ( l_row = 0; l_row < pixel_rgn.h; l_row++ )
|
|
|
|
{
|
2004-07-31 05:29:45 +08:00
|
|
|
memset(l_ptr, 0, pixel_rgn.w * drawable->bpp);
|
|
|
|
l_ptr += pixel_rgn.rowstride;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
}
|
2004-07-31 05:29:45 +08:00
|
|
|
} /* end p_clear_drawable */
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_create_pv_image
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
gint32
|
2003-11-06 23:27:05 +08:00
|
|
|
p_create_pv_image (GimpDrawable *src_drawable,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 *layer_id)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2004-02-09 22:43:46 +08:00
|
|
|
gint32 l_new_image_id;
|
|
|
|
guint l_new_width;
|
|
|
|
guint l_new_height;
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpImageType l_type;
|
2004-02-09 22:43:46 +08:00
|
|
|
guint l_x, l_y;
|
|
|
|
double l_scale;
|
|
|
|
guchar l_pixel[4];
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpDrawable *dst_drawable;
|
2004-02-09 22:43:46 +08:00
|
|
|
t_GDRW l_src_gdrw;
|
|
|
|
t_GDRW l_dst_gdrw;
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 21:21:27 +08:00
|
|
|
l_new_image_id = gimp_image_new (PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
|
|
|
|
gimp_image_base_type (gimp_drawable_get_image (src_drawable->drawable_id)));
|
2000-02-08 06:23:02 +08:00
|
|
|
gimp_image_undo_disable (l_new_image_id);
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
l_type = gimp_drawable_type(src_drawable->drawable_id);
|
2003-08-27 13:44:57 +08:00
|
|
|
if (src_drawable->height > src_drawable->width)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
l_new_height = PV_IMG_HEIGHT;
|
|
|
|
l_new_width = (src_drawable->width * l_new_height) / src_drawable->height;
|
|
|
|
l_scale = (float)src_drawable->height / PV_IMG_HEIGHT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l_new_width = PV_IMG_WIDTH;
|
|
|
|
l_new_height = (src_drawable->height * l_new_width) / src_drawable->width;
|
|
|
|
l_scale = (float)src_drawable->width / PV_IMG_WIDTH;
|
|
|
|
}
|
|
|
|
|
|
|
|
*layer_id = gimp_layer_new(l_new_image_id, "preview_original",
|
|
|
|
l_new_width, l_new_height,
|
2003-11-06 23:27:05 +08:00
|
|
|
l_type,
|
1999-07-29 01:44:32 +08:00
|
|
|
100.0, /* opacity */
|
2003-08-27 13:44:57 +08:00
|
|
|
0); /* mode NORMAL */
|
|
|
|
if (!gimp_drawable_has_alpha(*layer_id))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
/* always add alpha channel */
|
|
|
|
gimp_layer_add_alpha(*layer_id);
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
gimp_image_add_layer(l_new_image_id, *layer_id, 0);
|
|
|
|
|
|
|
|
dst_drawable = gimp_drawable_get (*layer_id);
|
|
|
|
p_init_gdrw(&l_src_gdrw, src_drawable, FALSE, FALSE);
|
|
|
|
p_init_gdrw(&l_dst_gdrw, dst_drawable, TRUE, FALSE);
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
for (l_y = 0; l_y < l_new_height; l_y++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-08-27 13:44:57 +08:00
|
|
|
for (l_x = 0; l_x < l_new_width; l_x++)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
p_get_pixel(&l_src_gdrw, l_x * l_scale, l_y * l_scale, &l_pixel[0]);
|
|
|
|
p_put_pixel(&l_dst_gdrw, l_x, l_y, &l_pixel[0]);
|
|
|
|
}
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
p_end_gdrw(&l_src_gdrw);
|
|
|
|
p_end_gdrw(&l_dst_gdrw);
|
|
|
|
|
|
|
|
/* gimp_display_new(l_new_image_id); */
|
2003-08-27 13:44:57 +08:00
|
|
|
return l_new_image_id;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_add_layer
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
2003-11-06 23:27:05 +08:00
|
|
|
static GimpDrawable*
|
|
|
|
p_add_layer (gint width,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint height,
|
|
|
|
GimpDrawable *src_drawable)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpImageType l_type;
|
|
|
|
static GimpDrawable *l_new_drawable;
|
2000-02-08 06:23:02 +08:00
|
|
|
gint32 l_new_layer_id;
|
1999-07-29 01:44:32 +08:00
|
|
|
char *l_name;
|
|
|
|
char *l_name2;
|
|
|
|
gdouble l_opacity;
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpLayerModeEffects l_mode;
|
1999-07-29 01:44:32 +08:00
|
|
|
gint l_visible;
|
|
|
|
gint32 image_id;
|
|
|
|
gint stack_position;
|
|
|
|
|
2003-12-04 21:21:27 +08:00
|
|
|
image_id = gimp_drawable_get_image (src_drawable->drawable_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
stack_position = 0; /* TODO: should be same as src_layer */
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
/* copy type, name, opacity and mode from src_drawable */
|
2003-12-04 00:39:32 +08:00
|
|
|
l_type = gimp_drawable_type (src_drawable->drawable_id);
|
|
|
|
l_visible = gimp_drawable_get_visible (src_drawable->drawable_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
l_name2 = gimp_drawable_get_name (src_drawable->drawable_id);
|
|
|
|
l_name = g_strdup_printf ("%s_b", l_name2);
|
|
|
|
g_free (l_name2);
|
2003-08-27 13:44:57 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
l_mode = gimp_layer_get_mode (src_drawable->drawable_id);
|
|
|
|
l_opacity = gimp_layer_get_opacity (src_drawable->drawable_id); /* full opacity */
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
l_new_layer_id = gimp_layer_new (image_id, l_name,
|
|
|
|
width, height,
|
|
|
|
l_type,
|
|
|
|
l_opacity,
|
|
|
|
l_mode);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
g_free (l_name);
|
2003-12-04 00:39:32 +08:00
|
|
|
if (!gimp_drawable_has_alpha (l_new_layer_id))
|
|
|
|
{
|
|
|
|
/* always add alpha channel */
|
|
|
|
gimp_layer_add_alpha (l_new_layer_id);
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
l_new_drawable = gimp_drawable_get (l_new_layer_id);
|
2003-08-27 13:44:57 +08:00
|
|
|
if (!l_new_drawable)
|
2003-12-04 00:39:32 +08:00
|
|
|
{
|
|
|
|
fprintf (stderr, "p_ad_layer: cant get new_drawable\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* add the copied layer to the temp. working image */
|
2000-02-08 06:23:02 +08:00
|
|
|
gimp_image_add_layer (image_id, l_new_layer_id, stack_position);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* copy visiblity state */
|
2003-12-04 00:39:32 +08:00
|
|
|
gimp_drawable_set_visible (l_new_layer_id, l_visible);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
return l_new_drawable;
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_bender_calculate_iter_curve
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_bender_calculate_iter_curve (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
gint32 xmax,
|
|
|
|
gint32 ymax)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
int l_x;
|
|
|
|
gint l_outline;
|
|
|
|
BenderDialog *cd_from;
|
|
|
|
BenderDialog *cd_to;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
l_outline = cd->outline;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
if ((cd->bval_from == NULL) ||
|
|
|
|
(cd->bval_to == NULL) ||
|
|
|
|
(cd->bval_curr == NULL))
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-04 00:39:32 +08:00
|
|
|
if(gb_debug) printf("p_bender_calculate_iter_curve NORMAL1\n");
|
|
|
|
if (cd->curve_type == SMOOTH)
|
|
|
|
{
|
|
|
|
cd->outline = OUTLINE_UPPER;
|
|
|
|
bender_calculate_curve (cd, xmax, ymax, FALSE);
|
|
|
|
cd->outline = OUTLINE_LOWER;
|
|
|
|
bender_calculate_curve (cd, xmax, ymax, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_stretch_curves(cd, xmax, ymax);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-12-04 00:39:32 +08:00
|
|
|
/* compose curves by iterating between FROM/TO values */
|
|
|
|
if(gb_debug) printf ("p_bender_calculate_iter_curve ITERmode 1\n");
|
|
|
|
|
|
|
|
/* init FROM curves */
|
|
|
|
cd_from = g_new (BenderDialog, 1);
|
|
|
|
p_cd_from_bval (cd_from, cd->bval_from);
|
|
|
|
cd_from->curve_ptr[OUTLINE_UPPER] = g_new (gint32, 1+xmax);
|
|
|
|
cd_from->curve_ptr[OUTLINE_LOWER] = g_new (gint32, 1+xmax);
|
|
|
|
|
|
|
|
/* init TO curves */
|
|
|
|
cd_to = g_new (BenderDialog, 1);
|
|
|
|
p_cd_from_bval (cd_to, cd->bval_to);
|
|
|
|
cd_to->curve_ptr[OUTLINE_UPPER] = g_new (gint32, 1+xmax);
|
|
|
|
cd_to->curve_ptr[OUTLINE_LOWER] = g_new (gint32, 1+xmax);
|
|
|
|
|
|
|
|
if (cd_from->curve_type == SMOOTH)
|
|
|
|
{
|
|
|
|
/* calculate FROM curves */
|
|
|
|
cd_from->outline = OUTLINE_UPPER;
|
|
|
|
bender_calculate_curve (cd_from, xmax, ymax, FALSE);
|
|
|
|
cd_from->outline = OUTLINE_LOWER;
|
|
|
|
bender_calculate_curve (cd_from, xmax, ymax, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_stretch_curves (cd_from, xmax, ymax);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cd_to->curve_type == SMOOTH)
|
|
|
|
{
|
|
|
|
/* calculate TO curves */
|
|
|
|
cd_to->outline = OUTLINE_UPPER;
|
|
|
|
bender_calculate_curve (cd_to, xmax, ymax, FALSE);
|
|
|
|
cd_to->outline = OUTLINE_LOWER;
|
|
|
|
bender_calculate_curve (cd_to, xmax, ymax, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_stretch_curves (cd_to, xmax, ymax);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MIX Y-koords of the curves according to current iteration step */
|
|
|
|
for (l_x = 0; l_x <= xmax; l_x++)
|
|
|
|
{
|
|
|
|
p_delta_gint32 (&cd->curve_ptr[OUTLINE_UPPER][l_x],
|
|
|
|
cd_from->curve_ptr[OUTLINE_UPPER][l_x],
|
|
|
|
cd_to->curve_ptr[OUTLINE_UPPER][l_x],
|
|
|
|
cd->bval_curr->total_steps,
|
|
|
|
cd->bval_curr->current_step);
|
|
|
|
|
|
|
|
p_delta_gint32 (&cd->curve_ptr[OUTLINE_LOWER][l_x],
|
|
|
|
cd_from->curve_ptr[OUTLINE_LOWER][l_x],
|
|
|
|
cd_to->curve_ptr[OUTLINE_LOWER][l_x],
|
|
|
|
cd->bval_curr->total_steps,
|
|
|
|
cd->bval_curr->current_step);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (cd_from->curve_ptr[OUTLINE_UPPER]);
|
|
|
|
g_free (cd_from->curve_ptr[OUTLINE_LOWER]);
|
|
|
|
|
|
|
|
g_free (cd_from);
|
|
|
|
g_free (cd_to);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cd->outline = l_outline;
|
2003-12-04 00:39:32 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_vertical_bend
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
static void
|
2003-11-06 23:27:05 +08:00
|
|
|
p_vertical_bend (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
t_GDRW *src_gdrw,
|
|
|
|
t_GDRW *dst_gdrw)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
2003-12-04 00:39:32 +08:00
|
|
|
gint32 l_row, l_col;
|
|
|
|
gint32 l_first_row, l_first_col, l_last_row, l_last_col;
|
|
|
|
gint32 l_x, l_y;
|
|
|
|
gint32 l_x2, l_y2;
|
|
|
|
gint32 l_curvy, l_nb_curvy, l_nb2_curvy;
|
|
|
|
gint32 l_desty, l_othery;
|
|
|
|
gint32 l_miny, l_maxy;
|
|
|
|
gint32 l_sign, l_dy, l_diff;
|
|
|
|
gint32 l_topshift;
|
|
|
|
float l_progress_step;
|
|
|
|
float l_progress_max;
|
|
|
|
float l_progress;
|
|
|
|
|
|
|
|
t_Last *last_arr;
|
|
|
|
t_Last *first_arr;
|
|
|
|
guchar color[4];
|
|
|
|
guchar mixcolor[4];
|
|
|
|
guchar l_alpha_lo;
|
|
|
|
gint l_alias_dir;
|
|
|
|
guchar l_mixmask;
|
|
|
|
|
|
|
|
l_topshift = p_upper_curve_extend (cd, src_gdrw->drawable->width,
|
|
|
|
src_gdrw->drawable->height);
|
2003-08-27 13:44:57 +08:00
|
|
|
l_diff = l_curvy = l_nb_curvy = l_nb2_curvy= l_miny = l_maxy = 0;
|
|
|
|
l_alpha_lo = 20;
|
|
|
|
|
|
|
|
/* allocate array of last values (one element foreach x koordinate) */
|
|
|
|
last_arr = g_new (t_Last, src_gdrw->x2);
|
|
|
|
first_arr = g_new (t_Last, src_gdrw->x2);
|
|
|
|
|
|
|
|
/* ------------------------------------------------
|
|
|
|
* foreach pixel in the SAMPLE_drawable:
|
|
|
|
* ------------------------------------------------
|
|
|
|
* the inner loops (l_x/l_y) are designed to process
|
|
|
|
* all pixels of one tile in the sample drawable, the outer loops (row/col) do step
|
|
|
|
* to the next tiles. (this was done to reduce tile swapping)
|
|
|
|
*/
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
l_first_row = src_gdrw->y1 / src_gdrw->tile_height;
|
|
|
|
l_last_row = (src_gdrw->y2 / src_gdrw->tile_height);
|
|
|
|
l_first_col = src_gdrw->x1 / src_gdrw->tile_width;
|
|
|
|
l_last_col = (src_gdrw->x2 / src_gdrw->tile_width);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
/* init progress */
|
|
|
|
l_progress_max = (1 + l_last_row - l_first_row) * (1 + l_last_col - l_first_col);
|
|
|
|
l_progress_step = 1.0 / l_progress_max;
|
|
|
|
l_progress = 0.0;
|
2003-11-06 23:27:05 +08:00
|
|
|
if (cd->show_progress)
|
2005-09-30 16:16:10 +08:00
|
|
|
gimp_progress_init ( _("Curve Bend"));
|
2003-08-27 13:44:57 +08:00
|
|
|
|
|
|
|
for (l_row = l_first_row; l_row <= l_last_row; l_row++)
|
|
|
|
{
|
|
|
|
for (l_col = l_first_col; l_col <= l_last_col; l_col++)
|
2004-07-31 05:29:45 +08:00
|
|
|
{
|
|
|
|
if (l_col == l_first_col)
|
|
|
|
l_x = src_gdrw->x1;
|
|
|
|
else
|
|
|
|
l_x = l_col * src_gdrw->tile_width;
|
|
|
|
if (l_col == l_last_col)
|
|
|
|
l_x2 = src_gdrw->x2;
|
|
|
|
else
|
|
|
|
l_x2 = (l_col +1) * src_gdrw->tile_width;
|
|
|
|
|
|
|
|
if (cd->show_progress)
|
|
|
|
gimp_progress_update (l_progress += l_progress_step);
|
|
|
|
|
|
|
|
for( ; l_x < l_x2; l_x++)
|
|
|
|
{
|
|
|
|
if (l_row == l_first_row)
|
|
|
|
l_y = src_gdrw->y1;
|
|
|
|
else
|
|
|
|
l_y = l_row * src_gdrw->tile_height;
|
|
|
|
if(l_row == l_last_row)
|
|
|
|
l_y2 = src_gdrw->y2;
|
|
|
|
else
|
|
|
|
l_y2 = (l_row +1) * src_gdrw->tile_height ;
|
|
|
|
|
|
|
|
for( ; l_y < l_y2; l_y++)
|
|
|
|
{
|
|
|
|
/* ---------- copy SRC_PIXEL to curve position ------ */
|
|
|
|
|
|
|
|
p_get_pixel(src_gdrw, l_x, l_y, color);
|
|
|
|
|
|
|
|
l_curvy = p_curve_get_dy(cd, l_x,
|
|
|
|
(gint32)src_gdrw->drawable->width,
|
|
|
|
(gint32)src_gdrw->drawable->height, (gdouble)l_y);
|
|
|
|
l_desty = l_y + l_topshift + l_curvy;
|
|
|
|
|
|
|
|
/* ----------- SMOOTING ------------------ */
|
|
|
|
if (cd->smoothing && (l_x > 0))
|
|
|
|
{
|
|
|
|
l_nb_curvy = p_curve_get_dy(cd, l_x -1,
|
|
|
|
(gint32)src_gdrw->drawable->width,
|
|
|
|
(gint32)src_gdrw->drawable->height, (gdouble)l_y);
|
|
|
|
if ((l_nb_curvy == l_curvy) && (l_x > 1))
|
|
|
|
{
|
|
|
|
l_nb2_curvy = p_curve_get_dy(cd, l_x -2,
|
|
|
|
(gint32)src_gdrw->drawable->width,
|
|
|
|
(gint32)src_gdrw->drawable->height, (gdouble)l_y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l_nb2_curvy = l_nb_curvy;
|
|
|
|
}
|
|
|
|
p_put_mix_pixel(dst_gdrw, l_x, l_desty, color, l_nb_curvy, l_nb2_curvy, l_curvy );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_put_pixel(dst_gdrw, l_x, l_desty, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------- render ANTIALIAS ------------------ */
|
|
|
|
|
|
|
|
if(cd->antialias)
|
|
|
|
{
|
|
|
|
l_othery = l_desty;
|
|
|
|
|
|
|
|
if(l_y == src_gdrw->y1) /* Upper outline */
|
|
|
|
{
|
|
|
|
first_arr[l_x].y = l_curvy;
|
|
|
|
memcpy(first_arr[l_x].color, color,
|
|
|
|
dst_gdrw->drawable->bpp);
|
|
|
|
|
|
|
|
if (l_x > 0)
|
|
|
|
{
|
|
|
|
memcpy(mixcolor, first_arr[l_x-1].color,
|
|
|
|
dst_gdrw->drawable->bpp);
|
|
|
|
|
|
|
|
l_diff = abs(first_arr[l_x - 1].y - l_curvy) +1;
|
|
|
|
l_miny = MIN(first_arr[l_x - 1].y, l_curvy) -1;
|
|
|
|
l_maxy = MAX(first_arr[l_x - 1].y, l_curvy) +1;
|
|
|
|
|
|
|
|
l_othery = (src_gdrw->y2 -1)
|
|
|
|
+ l_topshift
|
|
|
|
+ p_curve_get_dy(cd, l_x,
|
|
|
|
(gint32)src_gdrw->drawable->width,
|
|
|
|
(gint32)src_gdrw->drawable->height,
|
|
|
|
(gdouble)(src_gdrw->y2 -1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (l_y == src_gdrw->y2 - 1) /* Lower outline */
|
|
|
|
{
|
|
|
|
if (l_x > 0)
|
|
|
|
{
|
|
|
|
memcpy(mixcolor, last_arr[l_x-1].color,
|
|
|
|
dst_gdrw->drawable->bpp);
|
|
|
|
|
|
|
|
l_diff = abs(last_arr[l_x - 1].y - l_curvy) +1;
|
|
|
|
l_maxy = MAX(last_arr[l_x - 1].y, l_curvy) +1;
|
|
|
|
l_miny = MIN(last_arr[l_x - 1].y, l_curvy) -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
l_othery = (src_gdrw->y1)
|
|
|
|
+ l_topshift
|
|
|
|
+ p_curve_get_dy(cd, l_x,
|
|
|
|
(gint32)src_gdrw->drawable->width,
|
|
|
|
(gint32)src_gdrw->drawable->height,
|
|
|
|
(gdouble)(src_gdrw->y1));
|
|
|
|
}
|
|
|
|
|
|
|
|
if(l_desty < l_othery) { l_alias_dir = 1; } /* fade to transp. with descending dy */
|
|
|
|
else if(l_desty > l_othery) { l_alias_dir = -1; } /* fade to transp. with ascending dy */
|
|
|
|
else { l_alias_dir = 0; } /* no antialias at curve crossing point(s) */
|
|
|
|
|
|
|
|
if (l_alias_dir != 0)
|
|
|
|
{
|
|
|
|
l_alpha_lo = 20;
|
|
|
|
if (gimp_drawable_has_alpha(src_gdrw->drawable->drawable_id))
|
|
|
|
{
|
|
|
|
l_alpha_lo = MIN(20, mixcolor[src_gdrw->index_alpha]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for(l_dy = 0; l_dy < l_diff; l_dy++)
|
|
|
|
{
|
|
|
|
/* iterate for fading alpha channel */
|
|
|
|
l_mixmask = 255 * ((gdouble)(l_dy+1) / (gdouble)(l_diff+1));
|
|
|
|
mixcolor[dst_gdrw->index_alpha] = MIX_CHANNEL(color[dst_gdrw->index_alpha], l_alpha_lo, l_mixmask);
|
|
|
|
if(l_alias_dir > 0)
|
|
|
|
{
|
|
|
|
p_put_pixel(dst_gdrw, l_x -1, l_y + l_topshift + l_miny + l_dy, mixcolor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_put_pixel(dst_gdrw, l_x -1, l_y + l_topshift + (l_maxy - l_dy), mixcolor);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------ FILL HOLES ------------------ */
|
|
|
|
|
|
|
|
if (l_y == src_gdrw->y1)
|
|
|
|
{
|
|
|
|
l_diff = 0;
|
|
|
|
l_sign = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l_diff = last_arr[l_x].y - l_curvy;
|
|
|
|
if (l_diff < 0)
|
|
|
|
{
|
|
|
|
l_diff = 0 - l_diff;
|
|
|
|
l_sign = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l_sign = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(mixcolor, color, dst_gdrw->drawable->bpp);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (l_dy = 1; l_dy <= l_diff; l_dy++)
|
|
|
|
{
|
|
|
|
/* y differs more than 1 pixel from last y in the
|
|
|
|
* destination drawable. So we have to fill the empty
|
|
|
|
* space between using a mixed color
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (cd->smoothing)
|
|
|
|
{
|
|
|
|
/* smooting is on, so we are using a mixed color */
|
|
|
|
gulong alpha1 = last_arr[l_x].color[3];
|
|
|
|
gulong alpha2 = color[3];
|
|
|
|
gulong alpha;
|
|
|
|
l_mixmask = 255 * ((gdouble)(l_dy) / (gdouble)(l_diff+1));
|
|
|
|
alpha = alpha1 * l_mixmask + alpha2 * (255 - l_mixmask);
|
|
|
|
mixcolor[3] = alpha/255;
|
|
|
|
if (mixcolor[3])
|
|
|
|
{
|
|
|
|
mixcolor[0] = (alpha1 * l_mixmask * last_arr[l_x].color[0]
|
|
|
|
+ alpha2 * (255 - l_mixmask) * color[0])/alpha;
|
|
|
|
mixcolor[1] = (alpha1 * l_mixmask * last_arr[l_x].color[1]
|
|
|
|
+ alpha2 * (255 - l_mixmask) * color[1])/alpha;
|
|
|
|
mixcolor[2] = (alpha1 * l_mixmask * last_arr[l_x].color[2]
|
|
|
|
+ alpha2 * (255 - l_mixmask) * color[2])/alpha;
|
|
|
|
/*mixcolor[2] = MIX_CHANNEL(last_arr[l_x].color[2], color[2], l_mixmask);*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* smooting is off, so we are using this color or
|
|
|
|
the last color */
|
|
|
|
if (l_dy < l_diff / 2)
|
|
|
|
{
|
|
|
|
memcpy(mixcolor, color,
|
|
|
|
dst_gdrw->drawable->bpp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(mixcolor, last_arr[l_x].color,
|
|
|
|
dst_gdrw->drawable->bpp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cd->smoothing)
|
|
|
|
{
|
|
|
|
p_put_mix_pixel(dst_gdrw, l_x,
|
|
|
|
l_desty + (l_dy * l_sign),
|
|
|
|
mixcolor,
|
|
|
|
l_nb_curvy, l_nb2_curvy, l_curvy );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_put_pixel(dst_gdrw, l_x,
|
|
|
|
l_desty + (l_dy * l_sign), mixcolor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store y and color */
|
|
|
|
last_arr[l_x].y = l_curvy;
|
|
|
|
memcpy(last_arr[l_x].color, color, dst_gdrw->drawable->bpp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-08-27 13:44:57 +08:00
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
* p_main_bend
|
|
|
|
* ============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
gint32
|
2003-11-06 23:27:05 +08:00
|
|
|
p_main_bend (BenderDialog *cd,
|
2004-07-31 05:29:45 +08:00
|
|
|
GimpDrawable *original_drawable,
|
|
|
|
gint work_on_copy)
|
1999-07-29 01:44:32 +08:00
|
|
|
{
|
|
|
|
t_GDRW l_src_gdrw;
|
|
|
|
t_GDRW l_dst_gdrw;
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpDrawable *dst_drawable;
|
|
|
|
GimpDrawable *src_drawable;
|
2000-02-08 06:23:02 +08:00
|
|
|
gint32 l_dst_height;
|
1999-07-29 01:44:32 +08:00
|
|
|
gint32 l_image_id;
|
|
|
|
gint32 l_tmp_layer_id;
|
|
|
|
gint32 l_interpolation;
|
|
|
|
gint l_offset_x, l_offset_y;
|
|
|
|
gint l_center_x, l_center_y;
|
|
|
|
gint32 xmax, ymax;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
l_interpolation = cd->smoothing;
|
2003-12-04 21:21:27 +08:00
|
|
|
l_image_id = gimp_drawable_get_image (original_drawable->drawable_id);
|
2001-06-15 04:07:38 +08:00
|
|
|
gimp_drawable_offsets(original_drawable->drawable_id, &l_offset_x, &l_offset_y);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2001-06-15 04:07:38 +08:00
|
|
|
l_center_x = l_offset_x + (gimp_drawable_width (original_drawable->drawable_id) / 2 );
|
|
|
|
l_center_y = l_offset_y + (gimp_drawable_height (original_drawable->drawable_id) / 2 );
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
/* always copy original_drawable to a tmp src_layer */
|
2001-06-15 04:07:38 +08:00
|
|
|
l_tmp_layer_id = gimp_layer_copy(original_drawable->drawable_id);
|
2003-11-06 23:27:05 +08:00
|
|
|
/* set layer invisible and dummyname and
|
2000-02-17 00:38:36 +08:00
|
|
|
* add at top of the image while working
|
|
|
|
* (for the case of undo the gimp must know,
|
|
|
|
* that the layer was part of the image)
|
|
|
|
*/
|
|
|
|
gimp_image_add_layer (l_image_id, l_tmp_layer_id, 0);
|
2003-12-04 00:39:32 +08:00
|
|
|
gimp_drawable_set_visible (l_tmp_layer_id, FALSE);
|
|
|
|
gimp_drawable_set_name (l_tmp_layer_id, "curve_bend_dummylayer");
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
if(gb_debug) printf("p_main_bend l_tmp_layer_id %d\n", (int)l_tmp_layer_id);
|
|
|
|
|
2003-08-27 13:44:57 +08:00
|
|
|
if (cd->rotation != 0.0)
|
2003-12-04 00:39:32 +08:00
|
|
|
{
|
|
|
|
if(gb_debug) printf("p_main_bend rotate: %f\n", (float)cd->rotation);
|
|
|
|
p_gimp_rotate(l_image_id, l_tmp_layer_id, l_interpolation, cd->rotation);
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
src_drawable = gimp_drawable_get (l_tmp_layer_id);
|
|
|
|
|
|
|
|
xmax = ymax = src_drawable->width -1;
|
2001-12-06 10:28:58 +08:00
|
|
|
cd->curve_ptr[OUTLINE_UPPER] = g_new (gint32, 1+xmax);
|
|
|
|
cd->curve_ptr[OUTLINE_LOWER] = g_new (gint32, 1+xmax);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
p_bender_calculate_iter_curve(cd, xmax, ymax);
|
|
|
|
bender_init_min_max(cd, xmax);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
l_dst_height = src_drawable->height
|
1999-07-29 01:44:32 +08:00
|
|
|
+ p_upper_curve_extend(cd, src_drawable->width, src_drawable->height)
|
|
|
|
+ p_lower_curve_extend(cd, src_drawable->width, src_drawable->height);
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
if(gb_debug) printf("p_main_bend: l_dst_height:%d\n", (int)l_dst_height);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
if(work_on_copy)
|
2003-12-04 00:39:32 +08:00
|
|
|
{
|
|
|
|
dst_drawable = p_add_layer(src_drawable->width, l_dst_height, src_drawable);
|
|
|
|
if(gb_debug) printf("p_main_bend: DONE add layer\n");
|
|
|
|
}
|
1999-07-29 01:44:32 +08:00
|
|
|
else
|
|
|
|
{
|
2003-12-04 00:39:32 +08:00
|
|
|
/* work on the original */
|
|
|
|
gimp_layer_resize(original_drawable->drawable_id,
|
|
|
|
src_drawable->width,
|
|
|
|
l_dst_height,
|
|
|
|
l_offset_x, l_offset_y);
|
|
|
|
if(gb_debug) printf("p_main_bend: DONE layer resize\n");
|
|
|
|
if(!gimp_drawable_has_alpha(original_drawable->drawable_id))
|
|
|
|
{
|
|
|
|
/* always add alpha channel */
|
|
|
|
gimp_layer_add_alpha(original_drawable->drawable_id);
|
|
|
|
}
|
|
|
|
dst_drawable = gimp_drawable_get (original_drawable->drawable_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
p_clear_drawable(dst_drawable);
|
|
|
|
|
|
|
|
p_init_gdrw(&l_src_gdrw, src_drawable, FALSE, FALSE);
|
|
|
|
p_init_gdrw(&l_dst_gdrw, dst_drawable, TRUE, FALSE);
|
|
|
|
|
|
|
|
p_vertical_bend(cd, &l_src_gdrw, &l_dst_gdrw);
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
if(gb_debug) printf("p_main_bend: DONE vertical bend\n");
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
p_end_gdrw(&l_src_gdrw);
|
|
|
|
p_end_gdrw(&l_dst_gdrw);
|
|
|
|
|
|
|
|
if(cd->rotation != 0.0)
|
2003-12-04 00:39:32 +08:00
|
|
|
{
|
|
|
|
p_gimp_rotate (l_image_id, dst_drawable->drawable_id,
|
|
|
|
l_interpolation, (gdouble)(360.0 - cd->rotation));
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
/* TODO: here we should crop dst_drawable to cut off full transparent borderpixels */
|
2003-12-04 22:05:17 +08:00
|
|
|
|
1999-07-29 01:44:32 +08:00
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
/* set offsets of the resulting new layer
|
1999-07-29 01:44:32 +08:00
|
|
|
*(center == center of original_drawable)
|
|
|
|
*/
|
2001-06-15 04:07:38 +08:00
|
|
|
l_offset_x = l_center_x - (gimp_drawable_width (dst_drawable->drawable_id) / 2 );
|
|
|
|
l_offset_y = l_center_y - (gimp_drawable_height (dst_drawable->drawable_id) / 2 );
|
|
|
|
gimp_layer_set_offsets (dst_drawable->drawable_id, l_offset_x, l_offset_y);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
|
|
|
/* delete the temp layer */
|
2003-12-04 00:39:32 +08:00
|
|
|
gimp_image_remove_layer (l_image_id, l_tmp_layer_id);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
g_free (cd->curve_ptr[OUTLINE_UPPER]);
|
|
|
|
g_free (cd->curve_ptr[OUTLINE_LOWER]);
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2003-12-04 00:39:32 +08:00
|
|
|
if (gb_debug) printf("p_main_bend: DONE bend main\n");
|
1999-07-29 01:44:32 +08:00
|
|
|
|
2001-06-15 04:07:38 +08:00
|
|
|
return dst_drawable->drawable_id;
|
2003-12-04 00:39:32 +08:00
|
|
|
}
|