home *** CD-ROM | disk | FTP | other *** search
- /* curve_bend plugin for the GIMP (tested with GIMP 1.1.17, requires gtk+ 1.2) */
-
- /* 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
- * (2000/02/16) v1.1.17b hof: added spinbuttons for rotate entry
- * (2000/02/16) v1.1.17 hof: undo bugfix (#6012)
- * don't call gimp_undo_push_group_end
- * after gimp_displays_flush
- * (1999/09/13) v1.01 hof: PDB-calls updated for gimp 1.1.9
- * (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
- */
-
- #include "config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <gtk/gtk.h>
-
- #include <libgimp/gimp.h>
- #include <libgimp/gimpui.h>
-
- #include "libgimp/stdplugins-intl.h"
-
-
- /* Defines */
- #define PLUG_IN_NAME "plug_in_curve_bend"
- #define PLUG_IN_VERSION "v1.1.17 (2000/02/16)"
- #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_DESCRIPTION "Bends a layer using 2 spline-curves"
-
- #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
- #define PREVIEW_BPP 3
- #define PREVIEW_BG_GRAY1 108
- #define PREVIEW_BG_GRAY2 156
-
- #define SMOOTH 0
- #define GFREE 1
-
- #define RANGE_MASK GDK_EXPOSURE_MASK | \
- GDK_ENTER_NOTIFY_MASK
-
- #define GRAPH_MASK GDK_EXPOSURE_MASK | \
- GDK_POINTER_MOTION_MASK | \
- GDK_POINTER_MOTION_HINT_MASK | \
- GDK_ENTER_NOTIFY_MASK | \
- GDK_BUTTON_PRESS_MASK | \
- GDK_BUTTON_RELEASE_MASK | \
- GDK_BUTTON1_MOTION_MASK
-
-
- #define OUTLINE_UPPER 0
- #define OUTLINE_LOWER 1
-
- typedef struct _BenderValues BenderValues;
- struct _BenderValues
- {
- 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 */
-
- int curve_type;
-
- gint smoothing;
- gint antialias;
- gint work_on_copy;
- gdouble rotation;
-
-
- 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
- {
- GtkWidget *shell;
- GtkWidget *outline_menu;
- GtkWidget *pv_widget;
- GtkWidget *graph;
- GtkAdjustment *rotate_data;
- GdkPixmap *pixmap;
- GtkWidget *filesel;
-
- GimpDrawable *drawable;
- 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 */
- gint32 *curve_ptr[2]; /* 0 <= curve_ptr <= src_drawable_width
- * both arrays are allocated dynamic,
- * depending on drawable width
- */
- gint32 min2[2];
- gint32 max2[2];
- gint32 zero2[2];
-
- gint show_progress;
- gint smoothing;
- gint antialias;
- gint work_on_copy;
- gdouble rotation;
-
-
- gint32 preview_image_id;
- gint32 preview_layer_id1;
- gint32 preview_layer_id2;
-
- BenderValues *bval_from;
- BenderValues *bval_to;
- BenderValues *bval_curr;
-
- gint run;
- };
-
- /* points Coords:
- *
- * 1.0 +----+----+----+----+
- * | . | | |
- * +--.-+--.-+----+----+
- * . | . | |
- * 0.5 +----+----+-.--+----+
- * | | | . .
- * +----+----+----+-.-.+
- * | | | | |
- * 0.0 +----+----+----+----+
- * 0.0 0.5 1.0
- *
- * curve Coords:
- *
- * OUTLINE_UPPER OUTLINE_LOWER
- *
- * 255 +----+----+----+----+ 255 +----+----+----+----+
- * | . | | | --- max | . | | | --- max
- * +--.-+--.-+----+----+ +--.-+--.-+----+----+
- * . | . | | zero ___ . | . | |
- * +----+----+-.--+----+ +----+----+-.--+----+
- * | | | . . --- zero | | | . .
- * +----+----+----+-.-.+ ___ min +----+----+----+-.-.+ ___ min
- * | | | | | | | | | |
- * 0 +----+----+----+----+ 0 +----+----+----+----+
- * 0 255 0 255
- */
-
- typedef double CRMatrix[4][4];
-
-
- /* p_buildmenu Structures */
-
- typedef struct _MenuItem MenuItem;
-
- typedef void (*MenuItemCallback) (GtkWidget *widget,
- gpointer user_data);
- struct _MenuItem
- {
- gchar *label;
- gchar unused_accelerator_key;
- gint unused_accelerator_mods;
- MenuItemCallback callback;
- gpointer user_data;
- MenuItem *unused_subitems;
- GtkWidget *widget;
- };
-
- typedef struct
- {
- GimpDrawable *drawable;
- GimpPixelRgn pr;
- gint x1;
- gint y1;
- gint x2;
- gint y2;
- gint index_alpha; /* 0 == no alpha, 1 == GREYA, 3 == RGBA */
- gint bpp;
- GimpTile *tile;
- gint tile_row;
- gint tile_col;
- gint tile_width;
- gint tile_height;
- gint tile_dirty;
- gint shadow;
- gint32 seldeltax;
- gint32 seldeltay;
- gint32 tile_swapcount;
- } t_GDRW;
-
- typedef struct
- {
- gint32 y;
- guchar color[4];
- } t_Last;
-
-
- /* curves action functions */
- static void query (void);
- static void run (gchar *name,
- gint nparams,
- GimpParam *param,
- gint *nreturn_vals,
- GimpParam **return_vals);
-
- static BenderDialog * bender_new_dialog (GimpDrawable *);
- static void bender_update (BenderDialog *, int);
- static void bender_plot_curve (BenderDialog *,
- int, int, int, int,
- gint32, gint32, gint);
- static void bender_calculate_curve (BenderDialog *, gint32,
- gint32, gint);
- static void bender_rotate_adj_callback (GtkAdjustment *, gpointer);
- static void bender_upper_callback (GtkWidget *, gpointer);
- static void bender_lower_callback (GtkWidget *, gpointer);
- static void bender_smooth_callback (GtkWidget *, gpointer);
- static void bender_free_callback (GtkWidget *, gpointer);
- 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);
- static void bender_ok_callback (GtkWidget *, gpointer);
- static void bender_cancel_callback (GtkWidget *, gpointer);
- 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);
- static void bender_load_callback (GtkWidget *, gpointer);
- static void bender_save_callback (GtkWidget *, gpointer);
- static gint bender_pv_widget_events (GtkWidget *, GdkEvent *,
- BenderDialog *);
- static gint bender_graph_events (GtkWidget *, GdkEvent *,
- BenderDialog *);
- static void bender_CR_compose (CRMatrix, CRMatrix,
- CRMatrix);
- static void bender_init_min_max (BenderDialog *, gint32);
- static BenderDialog * do_dialog (GimpDrawable *);
- GtkWidget * p_buildmenu (MenuItem *);
- static void p_init_gdrw (t_GDRW *gdrw, GimpDrawable *drawable,
- int dirty, int shadow);
- static void p_end_gdrw (t_GDRW *gdrw);
- static gint32 p_main_bend (BenderDialog *, GimpDrawable *, gint);
- static gint32 p_create_pv_image (GimpDrawable *src_drawable, gint32 *layer_id);
- static void p_render_preview (BenderDialog *cd, gint32 layer_id);
- static void p_get_pixel (t_GDRW *gdrw,
- gint32 x, gint32 y, guchar *pixel);
- static void p_put_pixel (t_GDRW *gdrw,
- gint32 x, gint32 y, guchar *pixel);
- static void p_put_mix_pixel (t_GDRW *gdrw,
- gint32 x, gint32 y, guchar *color,
- gint32 nb_curvy, gint32 nb2_curvy,
- gint32 curvy);
- 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);
- static void p_delta_gdouble (double *val, double val_from, double val_to,
- gint32 total_steps, gdouble current_step);
- static void p_delta_gint32 (gint32 *val, gint32 val_from, gint32 val_to,
- gint32 total_steps, gdouble current_step);
- static void p_copy_points (BenderDialog *cd, int outline, int xy,
- int argc, gdouble *floatarray);
- static void p_copy_yval (BenderDialog *cd, int outline,
- int argc, gint8 *int8array);
- static int p_save_pointfile (BenderDialog *cd, char *filename);
-
-
- /* Global Variables */
- GimpPlugInInfo PLUG_IN_INFO =
- {
- 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 },
- };
-
- static MenuItem outline_items[] =
- {
- { N_("Upper"), 0, 0, bender_upper_callback, NULL, NULL, NULL },
- { N_("Lower"), 0, 0, bender_lower_callback, NULL, NULL, NULL },
- { NULL, 0, 0, NULL, NULL, NULL, NULL }
- };
-
- static MenuItem curve_type_items[] =
- {
- { N_("Smooth"), 0, 0, bender_smooth_callback, NULL, NULL, NULL },
- { N_("Free"), 0, 0, bender_free_callback, NULL, NULL, NULL },
- { NULL, 0, 0, NULL, NULL, NULL, NULL }
- };
-
- int gb_debug = FALSE;
-
- /* Functions */
- /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX PDB_STUFF XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-
- /* ============================================================================
- * 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
- * ============================================================================
- */
-
- gint
- p_pdb_procedure_available (char *proc_name)
- {
- 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;
- gint l_rc;
-
- l_rc = 0;
-
- /* Query the gimp application's procedural database
- * regarding a particular procedure.
- */
- if (gimp_procedural_db_proc_info (proc_name,
- &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))
- {
- /* procedure found in PDB */
- return (l_nparams);
- }
-
- printf("Warning: Procedure %s not found.\n", proc_name);
- return -1;
- } /* end p_pdb_procedure_available */
-
-
- /* ============================================================================
- * p_gimp_rotate
- * PDB call of 'gimp_rotate'
- * ============================================================================
- */
-
- gint
- p_gimp_rotate (gint32 image_id,
- gint32 drawable_id,
- gint32 interpolation,
- gdouble angle_deg)
- {
- static char *l_rotate_proc = "gimp_rotate";
- GimpParam *return_vals;
- int nreturn_vals;
- gdouble l_angle_rad;
- int l_nparams;
- int l_rc;
-
- #ifdef ROTATE_OPTIMIZE
- static char *l_rotate_proc2 = "plug_in_rotate";
- gint32 l_angle_step;
-
- 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; }
-
- if(l_angle_step != 0)
- {
- l_nparams = p_pdb_procedure_available(l_rotate_proc2);
- if (l_nparams == 5)
- {
- /* use faster rotate plugin on multiples of 90 degrees */
- return_vals = gimp_run_procedure (l_rotate_proc2,
- &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;
- }
-
- }
-
- }
- #endif
-
- l_rc = -1;
- l_angle_rad = (angle_deg * G_PI) / 180.0;
-
- l_nparams = p_pdb_procedure_available(l_rotate_proc);
- if (l_nparams >= 0)
- {
- /* use the new Interface (Gimp 1.1 style)
- * (1.1 knows the image_id where the drawable belongs to)
- */
- return_vals = gimp_run_procedure (l_rotate_proc,
- &nreturn_vals,
- GIMP_PDB_DRAWABLE, drawable_id,
- GIMP_PDB_INT32, interpolation,
- GIMP_PDB_FLOAT, l_angle_rad,
- GIMP_PDB_END);
- if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
- {
- l_rc = 0;
- }
- else
- {
- printf("Error: %s call failed %d\n", l_rotate_proc, (int)return_vals[0].data.d_status);
- }
-
- gimp_destroy_params (return_vals, nreturn_vals);
- }
- else
- {
- printf("Error: Procedure %s not found.\n",l_rotate_proc);
- }
- return (l_rc);
-
- } /* end p_gimp_rotate */
-
- /* ============================================================================
- * p_gimp_edit_copy
- *
- * ============================================================================
- */
-
- gint32
- p_gimp_edit_copy (gint32 image_id,
- gint32 drawable_id)
- {
- static char *l_procname = "gimp_edit_copy";
- GimpParam *return_vals;
- int nreturn_vals;
-
- if (p_pdb_procedure_available(l_procname) >= 0)
- {
- return_vals = gimp_run_procedure (l_procname,
- &nreturn_vals,
- GIMP_PDB_DRAWABLE, drawable_id,
- GIMP_PDB_END);
-
- if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
- {
- gimp_destroy_params (return_vals, nreturn_vals);
- return 0;
- }
- printf("Error: PDB call of %s failed status:%d\n", l_procname, (int)return_vals[0].data.d_status);
- }
-
- return(-1);
- } /* end p_gimp_edit_copy */
-
- /* ============================================================================
- * p_gimp_edit_paste
- *
- * ============================================================================
- */
-
- gint32
- p_gimp_edit_paste (gint32 image_id,
- gint32 drawable_id,
- gint32 paste_into)
- {
- static char *l_procname = "gimp_edit_paste";
- GimpParam *return_vals;
- int nreturn_vals;
- gint32 fsel_layer_id;
-
- if (p_pdb_procedure_available(l_procname) >= 0)
- {
- return_vals = gimp_run_procedure (l_procname,
- &nreturn_vals,
- GIMP_PDB_DRAWABLE, drawable_id,
- GIMP_PDB_INT32, paste_into,
- GIMP_PDB_END);
-
- if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
- {
- fsel_layer_id = return_vals[1].data.d_layer;
- gimp_destroy_params (return_vals, nreturn_vals);
- return (fsel_layer_id);
- }
- printf("Error: PDB call of %s failed status:%d\n", l_procname, (int)return_vals[0].data.d_status);
- }
-
- return(-1);
- } /* end p_gimp_edit_paste */
-
-
- /* ============================================================================
- * p_if_selection_float_it
- * ============================================================================
- */
-
- gint32
- p_if_selection_float_it (gint32 image_id,
- gint32 layer_id)
- {
- gint32 l_sel_channel_id;
- gint32 l_layer_id;
- gint32 l_x1, l_x2, l_y1, l_y2;
- gint32 non_empty;
-
- l_layer_id = layer_id;
- if(!gimp_layer_is_floating_selection (layer_id) )
- {
- /* check and see if we have a selection mask */
- l_sel_channel_id = gimp_image_get_selection(image_id);
-
- gimp_selection_bounds (image_id, &non_empty, &l_x1, &l_y1, &l_x2, &l_y2);
-
- if (non_empty && l_sel_channel_id >= 0)
- {
- /* selection is TRUE, make a layer (floating selection) from the selection */
- p_gimp_edit_copy(image_id, layer_id);
- l_layer_id = p_gimp_edit_paste(image_id, layer_id, FALSE);
-
- }
- }
-
- return(l_layer_id);
- }
-
- /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX END_PDB_STUFF XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-
- /*
- * M M AAAAA IIIIII N N
- * M M M M A A II NN N
- * M M M AAAAAAA II N N N
- * M M A A II N NN
- * M M A A IIIIII N N
- */
-
- MAIN ()
-
- static void
- query (void)
- {
- static GimpParamDef args[] =
- {
- { 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 }"}
- };
- static gint nargs = sizeof (args) / sizeof (args[0]);
-
- static GimpParamDef return_vals[] =
- {
- { GIMP_PDB_LAYER, "bent_layer", "the handled layer" }
- };
- static gint nreturn_vals = sizeof(return_vals) / sizeof(return_vals[0]);
-
- static GimpParamDef args_iter[] =
- {
- { 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" },
- };
- static gint nargs_iter = sizeof (args_iter) / sizeof (args_iter[0]);
-
- /* the actual installation of the bend plugin */
- gimp_install_procedure (PLUG_IN_NAME,
- PLUG_IN_DESCRIPTION,
- "This plug-in does bend the active layer "
- "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"
- ,
- PLUG_IN_AUTHOR,
- PLUG_IN_COPYRIGHT,
- PLUG_IN_VERSION,
- N_("<Image>/Filters/Distorts/CurveBend..."),
- PLUG_IN_IMAGE_TYPES,
- GIMP_PLUGIN,
- nargs,
- nreturn_vals,
- args,
- return_vals);
-
- /* the installation of the Iterator extension for the bend plugin */
- gimp_install_procedure (PLUG_IN_ITER_NAME,
- "This extension calculates the modified values for one iterationstep for the call of plug_in_curve_bend",
- "",
- PLUG_IN_AUTHOR,
- PLUG_IN_COPYRIGHT,
- PLUG_IN_VERSION,
- NULL, /* do not appear in menus */
- NULL,
- GIMP_EXTENSION,
- nargs_iter, 0,
- args_iter, NULL);
- }
-
- static void
- run (char *name, /* name of plugin */
- int nparams, /* number of in-paramters */
- GimpParam *param, /* in-parameters */
- int *nreturn_vals, /* number of out-parameters */
- GimpParam **return_vals) /* out-parameters */
- {
- char *l_env;
- BenderDialog *cd;
-
- GimpDrawable *l_active_drawable = NULL;
- gint32 l_image_id = -1;
- gint32 l_layer_id = -1;
- gint32 l_layer_mask_id = -1;
- gint32 l_bent_layer_id = -1;
-
- /* Get the runmode from the in-parameters */
- GimpRunModeType run_mode = param[0].data.d_int32;
-
- /* status variable, use it to check for errors in invocation usualy only
- during non-interactive calling */
- GimpPDBStatusType status = GIMP_PDB_SUCCESS;
-
- /*always return at least the status to the caller. */
- static GimpParam values[2];
-
-
- if (run_mode == GIMP_RUN_INTERACTIVE) {
- INIT_I18N_UI();
- } else {
- INIT_I18N();
- }
-
- cd = NULL;
-
- l_env = g_getenv("BEND_DEBUG");
- if(l_env != NULL)
- {
- if((*l_env != 'n') && (*l_env != 'N')) gb_debug = 1;
- }
-
- if(gb_debug) fprintf(stderr, "\n\nDEBUG: run %s\n", name);
-
- /* initialize the return of the status */
- values[0].type = GIMP_PDB_STATUS;
- values[0].data.d_status = status;
- values[1].type = GIMP_PDB_LAYER;
- values[1].data.d_int32 = -1;
- *nreturn_vals = 2;
- *return_vals = values;
-
- if (strcmp (name, PLUG_IN_ITER_NAME) == 0)
- {
- 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))
- {
- total_steps = param[1].data.d_int32;
- current_step = param[2].data.d_float;
- len_struct = param[3].data.d_int32;
-
- 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);
- memcpy(&bval, &bval_from, sizeof(bval));
-
- 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;
-
-
- gimp_set_data(PLUG_IN_NAME, &bval, sizeof(bval));
- }
- else status = GIMP_PDB_CALLING_ERROR;
- }
- else status = GIMP_PDB_CALLING_ERROR;
-
- values[0].data.d_status = status;
- return;
- }
-
-
-
-
- /* get image and drawable */
- l_image_id = param[1].data.d_int32;
- l_layer_id = param[2].data.d_drawable;
-
- gimp_undo_push_group_start (l_image_id);
-
- if(!gimp_drawable_is_layer(l_layer_id))
- {
- gimp_message(_("CurveBend operates on layers only (but was called on channel or mask)"));
- printf("Passed drawable is no Layer\n");
- status = GIMP_PDB_EXECUTION_ERROR;
- }
- /* check for layermask */
- l_layer_mask_id = gimp_layer_get_mask_id(l_layer_id);
- if(l_layer_mask_id >= 0)
- {
- /* apply the layermask
- * some transitions (especially rotate) cant operate proper on
- * layers with masks !
- */
- gimp_image_remove_layer_mask(l_image_id, l_layer_id, 0 /* 0==APPLY */ );
- }
-
- /* if there is a selection, make it the floating selection layer */
- l_active_drawable = gimp_drawable_get (p_if_selection_float_it(l_image_id, l_layer_id));
-
-
- /* how are we running today? */
- if(status == GIMP_PDB_SUCCESS)
- {
- /* how are we running today? */
- switch (run_mode)
- {
- case GIMP_RUN_INTERACTIVE:
- /* Possibly retrieve data from a previous run */
- /* gimp_get_data (PLUG_IN_NAME, &g_bndvals); */
-
- /* 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_malloc (sizeof (BenderDialog));
- cd->run = TRUE;
- cd->show_progress = FALSE;
- 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 = (int) param[7].data.d_int32;
-
- p_copy_points(cd, OUTLINE_UPPER, 0, (int)param[8].data.d_int32, param[9].data.d_floatarray);
- p_copy_points(cd, OUTLINE_UPPER, 1, (int)param[10].data.d_int32, param[11].data.d_floatarray);
- p_copy_points(cd, OUTLINE_LOWER, 0, (int)param[12].data.d_int32, param[13].data.d_floatarray);
- p_copy_points(cd, OUTLINE_LOWER, 1, (int)param[14].data.d_int32, param[15].data.d_floatarray);
-
- p_copy_yval(cd, OUTLINE_UPPER, (int)param[16].data.d_int32, param[17].data.d_int8array);
- p_copy_yval(cd, OUTLINE_UPPER, (int)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_malloc (sizeof (BenderDialog));
- 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;
- }
- }
-
- if (cd == NULL)
- {
- status = GIMP_PDB_EXECUTION_ERROR;
- }
-
- if (status == GIMP_PDB_SUCCESS)
- {
- /* Run the main function */
-
- if(cd->run)
- {
- l_bent_layer_id = p_main_bend(cd, cd->drawable, cd->work_on_copy);
-
- /* Store variable states for next run */
- if (run_mode == GIMP_RUN_INTERACTIVE)
- {
- p_store_values(cd);
- }
- }
- else
- {
- status = GIMP_PDB_EXECUTION_ERROR; /* dialog ended with cancel button */
- }
-
- gimp_undo_push_group_end (l_image_id);
-
- /* If run mode is interactive, flush displays, else (script) don't
- do it, as the screen updates would make the scripts slow */
- if (run_mode != GIMP_RUN_NONINTERACTIVE)
- gimp_displays_flush ();
-
- }
- else
- {
- gimp_undo_push_group_end (l_image_id);
- }
- values[0].data.d_status = status;
- values[1].data.d_int32 = l_bent_layer_id; /* return the id of handled layer */
-
- if (gb_debug)
- printf ("end run curve_bend plugin\n");
-
- } /* end run */
-
-
- /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
- /* Last_VALUEs and ITERATOR stuff */
- /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
- int
- p_save_pointfile (BenderDialog *cd,
- char *filename)
- {
- int j;
- FILE *l_fp;
-
- if(gb_debug) printf("Saving curve to file:%s\n", filename);
-
- l_fp = fopen(filename, "w+");
- if(l_fp == NULL)
- {
- return -1;
- }
-
- 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");
-
- for(j=0; j < 17; j++)
- {
- fprintf(l_fp, "%s %+.6f %+.6f %+.6f %+.6f\n", KEY_POINTS,
- (float)cd->points[OUTLINE_UPPER][j][0],
- (float)cd->points[OUTLINE_UPPER][j][1],
- (float)cd->points[OUTLINE_LOWER][j][0],
- (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");
-
- for(j=0; j < 256; j++)
- {
- fprintf(l_fp, "%s %3d %3d\n", KEY_VAL_Y,
- (int)cd->curve[OUTLINE_UPPER][j],
- (int)cd->curve[OUTLINE_LOWER][j]);
- }
-
- fclose(l_fp);
- return 0; /* OK */
- } /* end p_save_pointfile */
-
-
- int
- p_load_pointfile (BenderDialog *cd,
- char *filename)
- {
- int l_pi, l_ci, l_n, l_len;
- FILE *l_fp;
- char l_buff[2000];
- float l_fux, l_fuy, l_flx, l_fly;
- int l_iuy, l_ily ;
-
- if(gb_debug) printf("Loading curve from file:%s\n", filename);
-
- l_fp = fopen(filename, "r");
- if(l_fp == NULL)
- {
- return -1;
- }
-
- l_pi= 0;
- l_ci= 0;
-
- fgets (l_buff, 2000-1, l_fp);
- if(strncmp(l_buff, KEY_POINTFILE, strlen(KEY_POINTFILE)) == 0)
- {
- while (NULL != fgets (l_buff, 2000-1, l_fp))
- {
- if(gb_debug) printf("FGETS: %s\n", l_buff);
- 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;
- if(gb_debug) printf("OK points[%d]\n", l_pi);
- l_pi++;
- }
- else
- {
- printf("warnig: BAD points[%d] in file %s are ignored\n", l_pi, filename);
- }
- }
- l_len = strlen(KEY_VAL_Y);
- if(strncmp(l_buff, KEY_VAL_Y, l_len) == 0)
- {
- l_n = sscanf(&l_buff[l_len], "%d %d", &l_iuy, &l_ily);
- if((l_n == 2) && (l_ci < 256))
- {
- cd->curve[OUTLINE_UPPER][l_ci] = l_iuy;
- cd->curve[OUTLINE_LOWER][l_ci] = l_ily;
- l_ci++;
- if(gb_debug) printf("OK y_val[%d]\n", l_pi);
- }
- else
- {
- printf("warnig: BAD y_vals[%d] in file %s are ignored\n", l_ci, filename);
- }
- }
-
- }
- }
- fclose(l_fp);
- return 0; /* OK */
- } /* end p_load_pointfile */
-
-
-
- void
- p_cd_to_bval (BenderDialog *cd,
- BenderValues *bval)
- {
- int i,j;
-
- for(i=0; i<2; i++)
- {
- for(j=0; j<256; j++)
- {
- bval->curve[i][j] = cd->curve[i][j];
- }
-
- for(j=0; j<17; j++)
- {
- bval->points[i][j][0] = cd->points[i][j][0]; /* x */
- bval->points[i][j][1] = cd->points[i][j][1]; /* y */
- }
-
- }
-
- 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;
- bval->current_step =0.0;
- }
-
- void
- p_cd_from_bval(BenderDialog *cd, BenderValues *bval)
- {
- int i,j;
-
- for(i=0; i<2; i++)
- {
- for(j=0; j<256; j++)
- {
- cd->curve[i][j] = bval->curve[i][j];
- }
-
- for(j=0; j<17; j++)
- {
- cd->points[i][j][0] = bval->points[i][j][0]; /* x */
- cd->points[i][j][1] = bval->points[i][j][1]; /* y */
- }
-
- }
-
- 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;
-
- }
-
- void
- p_store_values (BenderDialog *cd)
- {
- BenderValues l_bval;
-
- p_cd_to_bval(cd, &l_bval);
- gimp_set_data(PLUG_IN_NAME, &l_bval, sizeof(l_bval));
- }
-
- void
- p_retrieve_values (BenderDialog *cd)
- {
- BenderValues l_bval;
-
- l_bval.total_steps = 0;
- l_bval.current_step = -444.4; /* init with an invalid dummy value */
-
- gimp_get_data (PLUG_IN_NAME, &l_bval);
-
- if(l_bval.total_steps == 0)
- {
- 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
- {
- cd->bval_from = g_malloc(sizeof(BenderValues));
- cd->bval_to = g_malloc(sizeof(BenderValues));
- cd->bval_curr = g_malloc(sizeof(BenderValues));
- memcpy(cd->bval_curr, &l_bval, sizeof(l_bval));
-
- /* 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);
- memcpy(cd->bval_curr, &l_bval, sizeof(l_bval));
- p_cd_from_bval(cd, cd->bval_curr);
- cd->work_on_copy = FALSE;
- }
-
- }
-
-
- static void
- p_delta_gdouble (double *val,
- double val_from,
- double val_to,
- gint32 total_steps,
- gdouble current_step)
- {
- 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;
- }
-
- static void
- p_delta_gint32 (gint32 *val,
- gint32 val_from,
- gint32 val_to,
- gint32 total_steps,
- gdouble current_step)
- {
- 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;
- }
-
-
- void
- p_copy_points (BenderDialog *cd,
- int outline,
- int xy,
- int argc,
- gdouble *floatarray)
- {
- int j;
-
- for(j=0; j < 17; j++)
- {
- cd->points[outline][j][xy] = -1;
- }
- for(j=0; j < argc; j++)
- {
- cd->points[outline][j][xy] = floatarray[j];
- }
- }
-
- void
- p_copy_yval (BenderDialog *cd,
- int outline,
- int argc,
- gint8 *int8array)
- {
- int j;
- guchar fill;
-
- fill = MIDDLE;
- for(j=0; j < 256; j++)
- {
- if(j < argc)
- {
- fill = cd->curve[outline][j] = int8array[j];
- }
- else
- {
- cd->curve[outline][j] = fill;
- }
- }
- }
-
- /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
- /* curves machinery */
- /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-
- BenderDialog *
- do_dialog (GimpDrawable *drawable)
- {
- BenderDialog *cd;
- gint i;
-
- /* Init GTK */
- gimp_ui_init ("curve_bend", TRUE);
-
- /* 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;
-
- /* show the outline menu */
- for (i = 0; i < 2; i++)
- {
- gtk_widget_set_sensitive( outline_items[i].widget, TRUE);
- }
-
- /* set the current selection */
- gtk_option_menu_set_history ( GTK_OPTION_MENU (cd->outline_menu), 0);
-
- if (!GTK_WIDGET_VISIBLE (cd->shell))
- gtk_widget_show (cd->shell);
-
-
- bender_update (cd, UP_GRAPH | UP_DRAW);
-
- 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;
-
- if(gb_debug) printf("do_dialog END\n");
- return cd;
- }
-
-
- /**************************/
- /* Select Curves dialog */
- /**************************/
-
- static BenderDialog *
- bender_new_dialog (GimpDrawable *drawable)
- {
- BenderDialog *cd;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *label;
- GtkWidget *frame;
- GtkWidget *toggle;
- GtkWidget *option_menu;
- GtkWidget *outline_hbox;
- GtkWidget *menu;
- GtkWidget *table;
- GtkWidget *button;
- GtkWidget *spinbutton;
- GtkObject *data;
- int i, j;
-
- cd = g_malloc (sizeof (BenderDialog));
-
- cd->preview = FALSE;
- cd->curve_type = SMOOTH;
- cd->pixmap = NULL;
- cd->filesel = NULL;
- 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;
- cd->color = gimp_drawable_is_rgb (cd->drawable->id);
-
- 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++)
- {
- for (j = 0; j < 17; j++)
- {
- cd->points[i][j][0] = -1;
- cd->points[i][j][1] = -1;
- }
- 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 */
- }
-
-
- p_retrieve_values(cd); /* Possibly retrieve data from a previous run */
-
- for (i = 0; i < 2; i++)
- outline_items [i].user_data = (gpointer) cd;
- for (i = 0; i < 2; i++)
- curve_type_items [i].user_data = (gpointer) cd;
-
- /* The shell and main vbox */
- cd->shell = gimp_dialog_new (_("Curve Bend"), "curve_bend",
- gimp_standard_help_func, "filters/curve_bend.html",
- GTK_WIN_POS_MOUSE,
- FALSE, TRUE, FALSE,
-
- _("Reset"), bender_reset_callback,
- cd, NULL, NULL, FALSE, FALSE,
- _("Copy"), bender_copy_callback,
- cd, NULL, NULL, FALSE, FALSE,
- _("CopyInv"), bender_copy_inv_callback,
- cd, NULL, NULL, FALSE, FALSE,
- _("Swap"), bender_swap_callback,
- cd, NULL, NULL, FALSE, FALSE,
- _("OK"), bender_ok_callback,
- cd, NULL, NULL, TRUE, FALSE,
- _("Cancel"), bender_cancel_callback,
- cd, NULL, NULL, FALSE, TRUE,
-
- NULL);
-
- vbox = gtk_vbox_new (FALSE, 2);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cd->shell)->vbox), vbox,
- TRUE, TRUE, 0);
-
- /* The option menu for selecting outlines */
- outline_hbox = gtk_hbox_new (FALSE, 2+4);
- gtk_box_pack_start (GTK_BOX (vbox), outline_hbox, FALSE, FALSE, 0);
-
- /* The Load button */
- button = gtk_button_new_with_label (_("LoadCurve"));
- gtk_box_pack_start (GTK_BOX (outline_hbox), button, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (bender_load_callback),
- cd);
- gtk_widget_show (button);
-
- /* The Save button */
- button = gtk_button_new_with_label (_("SaveCurve"));
- gtk_box_pack_start (GTK_BOX (outline_hbox), button, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (bender_save_callback),
- cd);
- gtk_widget_show (button);
-
- /* Rotate label & spinbutton */
- label = gtk_label_new (_("Rotate: "));
- gtk_box_pack_start (GTK_BOX (outline_hbox), label, FALSE, FALSE, 0);
-
- data = gtk_adjustment_new (0, 0.0, 360.0, 1, 45, 90);
- cd->rotate_data = GTK_ADJUSTMENT (data);
-
- spinbutton = gtk_spin_button_new (cd->rotate_data, 0.5, 1);
- gtk_widget_set_usize (spinbutton, ENTRY_WIDTH, -1);
- gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
- gtk_box_pack_start (GTK_BOX (outline_hbox), spinbutton, FALSE, FALSE, 2);
-
- gtk_signal_connect (GTK_OBJECT (cd->rotate_data), "value_changed",
- GTK_SIGNAL_FUNC (bender_rotate_adj_callback),
- cd);
-
- gtk_widget_show (spinbutton);
-
-
- label = gtk_label_new (_("Curve for Border: "));
- gtk_box_pack_start (GTK_BOX (outline_hbox), label, FALSE, FALSE, 0);
-
- menu = p_buildmenu (outline_items);
- cd->outline_menu = gtk_option_menu_new ();
- gtk_box_pack_start (GTK_BOX (outline_hbox), cd->outline_menu, FALSE, FALSE, 2);
-
- gtk_widget_show (label);
- gtk_widget_show (cd->outline_menu);
- gtk_widget_show (outline_hbox);
- gtk_option_menu_set_menu (GTK_OPTION_MENU (cd->outline_menu), menu);
-
- /* The option menu for selecting the drawing method */
- label = gtk_label_new (_("Curve Type: "));
- gtk_box_pack_start (GTK_BOX (outline_hbox), label, FALSE, FALSE, 0);
-
- menu = p_buildmenu (curve_type_items);
- option_menu = gtk_option_menu_new ();
- gtk_box_pack_start (GTK_BOX (outline_hbox), option_menu, FALSE, FALSE, 2);
-
- gtk_widget_show (label);
- gtk_widget_show (option_menu);
- gtk_widget_show (outline_hbox);
- gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
-
-
- /* The table for the pv_widget preview */
- table = gtk_table_new (2, 2, FALSE);
- gtk_container_set_border_width (GTK_CONTAINER (table), 2);
- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
-
- /* The range drawing area */
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_table_attach (GTK_TABLE (table), frame, 0, 1, 0, 1,
- GTK_EXPAND, GTK_EXPAND, 0, 0);
-
- cd->pv_widget = gtk_preview_new (GTK_PREVIEW_COLOR);
- gtk_preview_size (GTK_PREVIEW (cd->pv_widget), PREVIEW_SIZE_X, PREVIEW_SIZE_Y);
- gtk_widget_set_events (cd->pv_widget, RANGE_MASK);
- gtk_signal_connect (GTK_OBJECT (cd->pv_widget), "event",
- (GtkSignalFunc) bender_pv_widget_events,
- cd);
- gtk_container_add (GTK_CONTAINER (frame), cd->pv_widget);
- gtk_widget_show (cd->pv_widget);
- gtk_widget_show (frame);
-
- /* The curves graph */
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 0, 1,
- GTK_EXPAND | GTK_SHRINK | GTK_FILL,
- GTK_FILL, 0, 0);
-
- cd->graph = gtk_drawing_area_new ();
- gtk_drawing_area_size (GTK_DRAWING_AREA (cd->graph),
- GRAPH_WIDTH + RADIUS * 2,
- GRAPH_HEIGHT + RADIUS * 2);
- gtk_widget_set_events (cd->graph, GRAPH_MASK);
- gtk_signal_connect (GTK_OBJECT (cd->graph), "event",
- (GtkSignalFunc) bender_graph_events,
- cd);
- gtk_container_add (GTK_CONTAINER (frame), cd->graph);
- gtk_widget_show (cd->graph);
- gtk_widget_show (frame);
-
- gtk_widget_show (table);
-
- /* Horizontal box for preview */
- hbox = gtk_hbox_new (FALSE, 2+3);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-
- /* The preview button */
- button = gtk_button_new_with_label (_("PreviewOnce"));
- gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) bender_preview_update_once,
- cd);
- gtk_widget_show (button);
-
-
- /* The preview toggle */
- toggle = gtk_check_button_new_with_label (_("Preview"));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->preview);
- gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
- (GtkSignalFunc) bender_preview_update,
- cd);
-
- gtk_widget_show (toggle);
-
- /* The smoothing toggle */
- toggle = gtk_check_button_new_with_label (_("Smoothing"));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->smoothing);
- gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
- (GtkSignalFunc) bender_smoothing_callback,
- cd);
-
- gtk_widget_show (toggle);
-
- /* The antialiasing toggle */
- toggle = gtk_check_button_new_with_label (_("Antialiasing"));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->antialias);
- gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
- (GtkSignalFunc) bender_antialias_callback,
- cd);
-
- gtk_widget_show (toggle);
-
- /* The wor_on_copy toggle */
- toggle = gtk_check_button_new_with_label (_("Work on Copy"));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->work_on_copy);
- gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
- (GtkSignalFunc) bender_work_on_copy_callback,
- cd);
-
- gtk_widget_show (toggle);
-
- gtk_widget_show (hbox);
-
- gtk_widget_show (vbox);
-
- return cd;
- }
-
- static void
- bender_update (BenderDialog *cd,
- int update)
- {
- int i;
- int other;
-
- if (update & UP_PREVIEW)
- {
- if (cd->preview_layer_id2 >= 0)
- gimp_image_remove_layer(cd->preview_image_id, cd->preview_layer_id2);
-
- cd->preview_layer_id2 = p_main_bend(cd, gimp_drawable_get (cd->preview_layer_id1), TRUE /* work_on_copy*/ );
- p_render_preview(cd, cd->preview_layer_id2);
-
- if (update & UP_DRAW)
- gtk_widget_draw (cd->pv_widget, NULL);
- }
- if (update & UP_PREVIEW_EXPOSE)
- {
- /* on expose just redraw cd->preview_layer_id2
- * that holds the bent version of the preview (if there is one)
- */
- if (cd->preview_layer_id2 < 0)
- cd->preview_layer_id2 = p_main_bend(cd, gimp_drawable_get (cd->preview_layer_id1), TRUE /* work_on_copy*/ );
- p_render_preview(cd, cd->preview_layer_id2);
-
- if (update & UP_DRAW)
- gtk_widget_draw (cd->pv_widget, NULL);
- }
- 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],
- TRUE, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
-
- /* Draw the grid lines */
- for (i = 0; i < 5; i++)
- {
- 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);
- }
-
- /* Draw the other curve */
- if(cd->outline == 0) { other = 1; }
- else { other = 0; }
-
- for (i = 0; i < 256; i++)
- {
- points[i].x = i + RADIUS;
- points[i].y = 255 - cd->curve[other][i] + RADIUS;
- }
- 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++)
- {
- points[i].x = i + RADIUS;
- points[i].y = 255 - cd->curve[cd->outline][i] + RADIUS;
- }
- gdk_draw_points (cd->pixmap, cd->graph->style->black_gc, points, 256);
-
- /* Draw the points */
- if (cd->curve_type == SMOOTH)
- 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);
- }
-
-
- gdk_draw_pixmap (cd->graph->window, cd->graph->style->black_gc, cd->pixmap,
- 0, 0, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
- }
- }
-
-
- static void
- bender_plot_curve (BenderDialog *cd,
- int p1,
- int p2,
- int p3,
- int p4,
- gint32 xmax,
- gint32 ymax,
- gint fix255)
- {
- 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;
- gint32 ntimes;
- 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);
-
-
- if(fix255)
- {
- cd->curve[cd->outline][lastx] = lasty;
- }
- else
- {
- 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;
- }
- 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);
- }
- }
-
- lastx = newx;
- lasty = newy;
- }
- }
-
- static void
- bender_calculate_curve (BenderDialog *cd,
- gint32 xmax,
- gint32 ymax,
- gint fix255)
- {
- 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++)
- if (cd->points[cd->outline][i][0] != -1)
- points[num_pts++] = i;
-
- xmid = xmax / 2;
- /* Initialize boundary curve points */
- if (num_pts != 0)
- {
-
- if(fix255)
- {
- for (i = 0; i < (cd->points[cd->outline][points[0]][0] * 255); i++)
- cd->curve[cd->outline][i] = (cd->points[cd->outline][points[0]][1] * 255);
- for (i = (cd->points[cd->outline][points[num_pts - 1]][0] * 255); i < 256; i++)
- cd->curve[cd->outline][i] = (cd->points[cd->outline][points[num_pts - 1]][1] * 255);
- }
- else
- {
- 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;
- }
-
- }
- }
-
- for (i = 0; i < num_pts - 1; i++)
- {
- 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)];
-
- bender_plot_curve (cd, p1, p2, p3, p4, xmax, ymax, fix255);
- }
- break;
- }
-
- }
-
- static void
- bender_rotate_adj_callback (GtkAdjustment *adjustment,
- gpointer client_data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) client_data;
-
- if (adjustment->value != cd->rotation)
- {
- cd->rotation = adjustment->value;
- if(cd->preview) bender_update (cd, UP_PREVIEW | UP_DRAW);
- }
- }
-
-
- static void
- bender_upper_callback (GtkWidget *w,
- gpointer client_data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) client_data;
-
- if (cd->outline != OUTLINE_UPPER)
- {
- cd->outline = OUTLINE_UPPER;
- bender_update (cd, UP_GRAPH | UP_DRAW);
- }
- }
-
- static void
- bender_lower_callback (GtkWidget *w,
- gpointer client_data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) client_data;
-
- if (cd->outline != OUTLINE_LOWER)
- {
- cd->outline = OUTLINE_LOWER;
- bender_update (cd, UP_GRAPH | UP_DRAW);
- }
- }
-
-
- static void
- bender_smooth_callback (GtkWidget *w,
- gpointer client_data)
- {
- BenderDialog *cd;
- int i;
- gint32 index;
-
- cd = (BenderDialog *) client_data;
-
- if (cd->curve_type != SMOOTH)
- {
- cd->curve_type = SMOOTH;
-
- /* pick representative points from the curve and make them control points */
- for (i = 0; i <= 8; i++)
- {
- 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;
- }
-
- bender_calculate_curve (cd, 255, 255, TRUE);
- bender_update (cd, UP_GRAPH | UP_DRAW);
-
- if (cd->preview)
- bender_update (cd, UP_PREVIEW | UP_DRAW);
- }
- }
-
- static void
- bender_free_callback (GtkWidget *w,
- gpointer client_data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) client_data;
-
- if (cd->curve_type != GFREE)
- {
- cd->curve_type = GFREE;
- bender_update (cd, UP_GRAPH | UP_DRAW);
- }
- }
-
- static void
- bender_reset_callback (GtkWidget *widget,
- gpointer client_data)
- {
- 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,
- gpointer client_data)
- {
- BenderDialog *cd;
- int i;
- int other;
-
- cd = (BenderDialog *) client_data;
-
- if(cd->outline == 0)
- other = 1;
- else
- other = 0;
-
-
- 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,
- gpointer client_data)
- {
- BenderDialog *cd;
- int i;
- int other;
-
- cd = (BenderDialog *) client_data;
-
- if(cd->outline == 0)
- other = 1;
- else
- other = 0;
-
-
- 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,
- gpointer client_data)
- {
- #define SWAP_VALUE(a, b, h) { h=a; a=b; b=h; }
- BenderDialog *cd;
- int i;
- int other;
- gdouble hd;
- guchar hu;
-
- cd = (BenderDialog *) client_data;
-
- if(cd->outline == 0)
- other = 1;
- else
- other = 0;
-
-
- for (i = 0; i < 17; i++)
- {
- SWAP_VALUE(cd->points[other][i][0], cd->points[cd->outline][i][0], hd); /* x */
- 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
- bender_ok_callback (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
-
- if (GTK_WIDGET_VISIBLE (cd->shell))
- gtk_widget_hide (cd->shell);
-
- cd->run = TRUE;
- gtk_widget_destroy (GTK_WIDGET (cd->shell));
- gtk_main_quit ();
- }
-
- static void
- bender_cancel_callback (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
- gtk_main_quit ();
- }
-
- static void
- bender_preview_update (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
-
- if (GTK_TOGGLE_BUTTON (widget)->active)
- {
- cd->preview = TRUE;
- bender_update (cd, UP_PREVIEW | UP_DRAW);
- }
- else
- {
- cd->preview = FALSE;
- }
- }
-
- static void
- bender_preview_update_once (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
- bender_update (cd, UP_PREVIEW | UP_DRAW);
- }
-
- static void
- p_filesel_close_cb (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
-
- if(gb_debug) printf("p_filesel_close_cb\n");
-
- if(cd->filesel == NULL) return;
-
- gtk_widget_destroy(GTK_WIDGET(cd->filesel));
- cd->filesel = NULL; /* now filesel is closed */
- }
-
- static void
- p_points_save_to_file (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
- char *filename;
-
- if(gb_debug) printf("p_points_save_to_file\n");
- cd = (BenderDialog *) data;
-
- if(cd->filesel == NULL) return;
-
- filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (cd->filesel));
- p_save_pointfile(cd, filename);
- gtk_widget_destroy(GTK_WIDGET(cd->filesel));
- cd->filesel = NULL;
- }
-
- static void
- p_points_load_from_file (GtkWidget *widget,
- gpointer data)
- {
- BenderDialog *cd;
- char *filename;
-
- if(gb_debug) printf("p_points_load_from_file\n");
- cd = (BenderDialog *) data;
-
- if(cd->filesel == NULL) return;
-
- filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (cd->filesel));
- p_load_pointfile(cd, filename);
- gtk_widget_destroy(GTK_WIDGET(cd->filesel));
- cd->filesel = NULL;
- bender_update (cd, UP_ALL);
- }
-
- static void
- bender_load_callback (GtkWidget *w,
- gpointer data)
- {
- BenderDialog *cd;
- GtkWidget *filesel;
-
- cd = (BenderDialog *) data;
- if(cd->filesel != NULL)
- return; /* filesel is already open */
-
- filesel = gtk_file_selection_new ( _("Load Curve Points from file"));
- cd->filesel = filesel;
-
- gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
- "clicked", (GtkSignalFunc) p_points_load_from_file,
- cd);
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
- "clicked", (GtkSignalFunc) p_filesel_close_cb,
- cd);
- gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
- (GtkSignalFunc) p_filesel_close_cb,
- cd);
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel),
- "curve_bend.points");
- gtk_widget_show (filesel);
-
- }
-
- static void
- bender_save_callback (GtkWidget *w,
- gpointer data)
- {
- BenderDialog *cd;
- GtkWidget *filesel;
-
- cd = (BenderDialog *) data;
- if(cd->filesel != NULL)
- return; /* filesel is already open */
-
- filesel = gtk_file_selection_new ( _("Save Curve Points to file"));
- cd->filesel = filesel;
-
- gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
- "clicked", (GtkSignalFunc) p_points_save_to_file,
- cd);
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
- "clicked", (GtkSignalFunc) p_filesel_close_cb,
- cd);
- gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
- (GtkSignalFunc) p_filesel_close_cb,
- cd);
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel),
- "curve_bend.points");
- gtk_widget_show (filesel);
- }
-
- static void
- bender_smoothing_callback (GtkWidget *w,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
-
- if (GTK_TOGGLE_BUTTON (w)->active) { cd->smoothing = TRUE; }
- else { cd->smoothing = FALSE; }
-
- if(cd->preview) bender_update (cd, UP_PREVIEW | UP_DRAW);
- }
-
- static void
- bender_antialias_callback (GtkWidget *w,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
-
- if (GTK_TOGGLE_BUTTON (w)->active) { cd->antialias = TRUE; }
- else { cd->antialias = FALSE; }
-
- if(cd->preview) bender_update (cd, UP_PREVIEW | UP_DRAW);
- }
-
- static void
- bender_work_on_copy_callback (GtkWidget *w,
- gpointer data)
- {
- BenderDialog *cd;
-
- cd = (BenderDialog *) data;
-
- if (GTK_TOGGLE_BUTTON (w)->active) { cd->work_on_copy = TRUE; }
- else { cd->work_on_copy = FALSE; }
- }
-
- static gint
- bender_graph_events (GtkWidget *widget,
- GdkEvent *event,
- BenderDialog *cd)
- {
- 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)
- 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;
- }
- }
- if (distance > MIN_DISTANCE)
- closest_point = (x + 8) / 16;
-
- switch (event->type)
- {
- case GDK_EXPOSE:
- if (cd->pixmap == NULL)
- cd->pixmap = gdk_pixmap_new (cd->graph->window,
- GRAPH_WIDTH + RADIUS * 2,
- GRAPH_HEIGHT + RADIUS * 2, -1);
-
- bender_update (cd, UP_GRAPH | UP_DRAW);
- break;
-
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
- new_type = GDK_TCROSS;
-
- switch (cd->curve_type)
- {
- 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;
- }
-
- bender_update (cd, UP_GRAPH | UP_DRAW);
- break;
-
- case GDK_BUTTON_RELEASE:
- new_type = GDK_FLEUR;
- cd->grab_point = -1;
-
- if (cd->preview)
- bender_update (cd, UP_PREVIEW | UP_DRAW);
- break;
-
- case GDK_MOTION_NOTIFY:
- mevent = (GdkEventMotion *) event;
-
- if (mevent->is_hint)
- {
- mevent->x = tx;
- mevent->y = ty;
- }
-
- switch (cd->curve_type)
- {
- 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;
- }
-
- if (new_type != cursor_type)
- {
- cursor_type = new_type;
- /* change_win_cursor (cd->graph->window, cursor_type); */
- }
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
-
- static gint
- bender_pv_widget_events (GtkWidget *widget,
- GdkEvent *event,
- BenderDialog *cd)
- {
- switch (event->type)
- {
- case GDK_EXPOSE:
- bender_update (cd, UP_PREVIEW_EXPOSE);
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
- static void
- bender_CR_compose (CRMatrix a,
- CRMatrix b,
- CRMatrix ab)
- {
- int i, j;
-
- 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]);
- }
- }
- }
-
-
- /* ============================================================================
- * p_buildmenu
- * build menu widget for all Items passed in the MenuItems Parameter
- * MenuItems is an array of Pointers to Structure MenuItem.
- * The End is marked by a Structure Member where the label is a NULL pointer
- * (simplifyed version of GIMP 1.0.2 bulid_menu procedur)
- * ============================================================================
- */
-
- GtkWidget *
- p_buildmenu (MenuItem *items)
- {
- GtkWidget *menu;
- GtkWidget *menu_item;
-
- menu = gtk_menu_new ();
-
- while (items->label)
- {
- menu_item = gtk_menu_item_new_with_label ( gettext(items->label));
- gtk_container_add (GTK_CONTAINER (menu), menu_item);
-
- if (items->callback)
- gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
- (GtkSignalFunc) items->callback,
- items->user_data);
-
- gtk_widget_show (menu_item);
- items->widget = menu_item;
-
- items++;
- }
-
- return menu;
- } /* end p_buildmenu */
-
- void
- p_render_preview (BenderDialog *cd,
- gint32 layer_id)
- {
- guchar l_rowbuf[PREVIEW_BPP * PREVIEW_SIZE_X];
- guchar l_pixel[4];
- guchar *l_ptr;
- GimpDrawable *l_pv_drawable;
- gint l_x, l_y;
- gint l_ofx, l_ofy;
- gint l_idx;
- guchar l_bg_gray;
- t_GDRW l_gdrw;
- t_GDRW *gdrw;
-
- l_pv_drawable = gimp_drawable_get (layer_id);
-
- 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);
-
- /* render preview */
- for(l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
- {
- l_ptr = &l_rowbuf[0];
-
- for(l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
- {
- p_get_pixel(gdrw, l_x + l_ofx, l_y + l_ofy, &l_pixel[0]);
- if(l_pixel[gdrw->index_alpha] < 255)
- {
- /* for transparent pixels: mix with preview background color */
- if((l_x % 32) < 16)
- {
- l_bg_gray = PREVIEW_BG_GRAY1;
- if ((l_y % 32) < 16) l_bg_gray = PREVIEW_BG_GRAY2;
- }
- else
- {
- l_bg_gray = PREVIEW_BG_GRAY2;
- if ((l_y % 32) < 16) l_bg_gray = PREVIEW_BG_GRAY1;
- }
-
- for(l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
- {
- l_pixel[l_idx] = MIX_CHANNEL(l_pixel[l_idx], l_bg_gray, l_pixel[gdrw->index_alpha]);
- }
- }
-
-
- if(cd->color)
- {
- *l_ptr = l_pixel[0];
- l_ptr[1] = l_pixel[1];
- l_ptr[2] = l_pixel[2];
- }
- else
- {
- *l_ptr = l_pixel[0];
- l_ptr[1] = l_pixel[0];
- l_ptr[2] = l_pixel[0];
- }
-
- l_ptr += PREVIEW_BPP;
- }
-
- gtk_preview_draw_row(GTK_PREVIEW(cd->pv_widget), &l_rowbuf[0], 0, l_y, PREVIEW_SIZE_X);
- }
-
- p_end_gdrw(gdrw);
- } /* end p_render_preview */
-
- /* ===================================================== */
- /* curve_bend worker procedures */
- /* ===================================================== */
-
- void
- p_stretch_curves (BenderDialog *cd,
- gint32 xmax,
- gint32 ymax)
- {
- 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);
- /*
- * printf("_X: %d _X2: %d Y2: %d _Y: %d debugY:%d\n",
- * (int)l_x1, (int)l_x2,
- * (int)cd->curve[l_outline][l_x2],
- * (int)cd->curve_ptr[l_outline][l_x1],
- * l_debugY);
- */
- }
-
- }
- }
- }
-
-
- void
- bender_init_min_max (BenderDialog *cd,
- gint32 xmax)
- {
- 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];
- }
- }
- }
-
- /* 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]);
-
- /* 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]);
-
- if(gb_debug)
- {
- printf("bender_init_min_max: zero2[0]: %d min2[0]:%d max2[0]:%d\n",
- (int)cd->zero2[0],
- (int)cd->min2[0],
- (int)cd->max2[0] );
- printf("bender_init_min_max: zero2[1]: %d min2[1]:%d max2[1]:%d\n",
- (int)cd->zero2[1],
- (int)cd->min2[1],
- (int)cd->max2[1] );
- }
-
- }
-
-
- gint32
- p_curve_get_dy (BenderDialog *cd,
- gint32 x,
- gint32 drawable_width,
- gint32 total_steps,
- gdouble current_step)
- {
- /* get y values of both upper and lower curve,
- * and return the iterated value inbetween
- */
- gint32 l_y;
- double l_y1, l_y2;
- double delta;
-
- l_y1 = cd->zero2[OUTLINE_UPPER] - cd->curve_ptr[OUTLINE_UPPER][x];
- l_y2 = cd->zero2[OUTLINE_LOWER] - cd->curve_ptr[OUTLINE_LOWER][x];
-
- delta = ((double)(l_y2 - l_y1) / (double)(total_steps -1)) * current_step;
- l_y = SIGNED_ROUND(l_y1 + delta);
-
- return l_y;
- }
-
-
- gint32
- p_upper_curve_extend (BenderDialog *cd,
- gint32 drawable_width,
- gint32 drawable_height)
- {
- gint32 l_y1, l_y2;
-
- l_y1 = cd->max2[OUTLINE_UPPER] - cd->zero2[OUTLINE_UPPER];
- l_y2 = (cd->max2[OUTLINE_LOWER] - cd->zero2[OUTLINE_LOWER]) - drawable_height;
-
- return (MAX(l_y1, l_y2));
- }
-
- gint32
- p_lower_curve_extend (BenderDialog *cd,
- gint32 drawable_width,
- gint32 drawable_height)
- {
- 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;
-
- return (MAX(l_y1, l_y2));
- }
-
- void
- p_end_gdrw (t_GDRW *gdrw)
- {
- if(gb_debug)
- printf ("\np_end_gdrw: drawable %x ID: %d\n",
- (int)gdrw->drawable, (int)gdrw->drawable->id);
-
- if(gdrw->tile)
- {
- if(gb_debug) printf("p_end_gdrw: tile unref\n");
- gimp_tile_unref( gdrw->tile, gdrw->tile_dirty);
- gdrw->tile = NULL;
- }
-
- if(gb_debug)
- printf("p_end_gdrw:TILE_SWAPCOUNT: %d\n", (int)gdrw->tile_swapcount);
-
- } /* end p_end_gdrw */
-
-
- void
- p_init_gdrw (t_GDRW *gdrw,
- GimpDrawable *drawable,
- int dirty,
- int shadow)
- {
- gint32 l_image_id;
- gint32 l_sel_channel_id;
- gint l_offsetx, l_offsety;
-
- if(gb_debug) printf("\np_init_gdrw: drawable %x ID: %d\n", (int)drawable, (int)drawable->id);
-
- gdrw->drawable = drawable;
- gdrw->tile = NULL;
- gdrw->tile_dirty = FALSE;
- gdrw->tile_width = gimp_tile_width ();
- gdrw->tile_height = gimp_tile_height ();
- gdrw->shadow = shadow;
- gdrw->tile_swapcount = 0;
- gdrw->seldeltax = 0;
- gdrw->seldeltay = 0;
- gimp_drawable_offsets (drawable->id, &l_offsetx, &l_offsety); /* get offsets within the image */
-
- gimp_drawable_mask_bounds (drawable->id, &gdrw->x1, &gdrw->y1, &gdrw->x2, &gdrw->y2);
-
- /*
- * gimp_pixel_rgn_init (&gdrw->pr, drawable,
- * gdrw->x1, gdrw->y1, gdrw->x2 - gdrw->x1, gdrw->y2 - gdrw->y1,
- * dirty, shadow);
- */
-
-
- gdrw->bpp = drawable->bpp;
- if (gimp_drawable_has_alpha(drawable->id))
- {
- /* index of the alpha channelbyte {1|3} */
- gdrw->index_alpha = gdrw->bpp -1;
- }
- else
- {
- gdrw->index_alpha = 0; /* there is no alpha channel */
- }
-
- if(gb_debug) printf("\np_init_gdrw: bpp %d index_alpha: %d\n", (int)gdrw->bpp, (int)gdrw->index_alpha);
-
- l_image_id = gimp_layer_get_image_id(drawable->id);
-
- /* check and see if we have a selection mask */
- l_sel_channel_id = gimp_image_get_selection(l_image_id);
-
- if(gb_debug)
- {
- printf("p_init_gdrw: image_id %d sel_channel_id: %d\n", (int)l_image_id, (int)l_sel_channel_id);
- printf("p_init_gdrw: BOUNDS x1: %d y1: %d x2:%d y2: %d\n",
- (int)gdrw->x1, (int)gdrw->y1, (int)gdrw->x2,(int)gdrw->y2);
- printf("p_init_gdrw: OFFS x: %d y: %d\n", (int)l_offsetx, (int)l_offsety );
- }
- } /* end p_init_gdrw */
-
-
- static void
- p_provide_tile (t_GDRW *gdrw,
- gint col,
- gint row,
- gint shadow )
- {
- if ( col != gdrw->tile_col || row != gdrw->tile_row || !gdrw->tile )
- {
- if( gdrw->tile )
- {
- gimp_tile_unref( gdrw->tile, gdrw->tile_dirty );
- }
- gdrw->tile_col = col;
- gdrw->tile_row = row;
- gdrw->tile = gimp_drawable_get_tile( gdrw->drawable, shadow, gdrw->tile_row, gdrw->tile_col );
- gdrw->tile_dirty = FALSE;
- gimp_tile_ref( gdrw->tile );
-
- gdrw->tile_swapcount++;
-
- return;
- }
- } /* end p_provide_tile */
-
- /* get pixel value
- * return light transparent black gray pixel if out of bounds
- * (should occur in the previews only)
- */
- static void
- p_get_pixel (t_GDRW *gdrw,
- gint32 x,
- gint32 y,
- guchar *pixel )
- {
- gint row, col;
- gint offx, offy;
- guchar *ptr;
-
- if((x < 0)
- || (x > gdrw->drawable->width -1)
- || (y < 0)
- || (y > gdrw->drawable->height - 1))
- {
- pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
- return;
- }
-
- col = x / gdrw->tile_width;
- row = y / gdrw->tile_height;
- offx = x % gdrw->tile_width;
- offy = y % gdrw->tile_height;
-
- p_provide_tile( gdrw, col, row, gdrw->shadow);
-
- pixel[1] = 255; pixel[3] = 255; /* simulate full visible alpha channel */
- ptr = gdrw->tile->data + ((( offy * gdrw->tile->ewidth) + offx ) * gdrw->bpp);
- memcpy(pixel, ptr, gdrw->bpp);
-
- /* printf("p_get_pixel: x: %d y: %d bpp:%d RGBA:%d %d %d %d\n", (int)x, (int)y, (int)gdrw->bpp, (int)pixel[0], (int)pixel[1], (int)pixel[2], (int)pixel[3]);
- */
- } /* end p_get_pixel */
-
- void
- p_put_pixel (t_GDRW *gdrw,
- gint32 x,
- gint32 y,
- guchar *pixel)
- {
- gint row, col;
- gint offx, offy;
- guchar *ptr;
-
- if (x < gdrw->x1) return;
- if (x > gdrw->x2 - 1) return;
- if (y < gdrw->y1) return;
- if (y > gdrw->y2 - 1) return;
-
- col = x / gdrw->tile_width;
- row = y / gdrw->tile_height;
- offx = x % gdrw->tile_width;
- offy = y % gdrw->tile_height;
-
- p_provide_tile( gdrw, col, row, gdrw->shadow );
-
- ptr = gdrw->tile->data + ((( offy * gdrw->tile->ewidth ) + offx ) * gdrw->bpp);
- memcpy(ptr, pixel, gdrw->bpp);
-
- gdrw->tile_dirty = TRUE;
-
- /* printf("p_put_pixel: x: %d y: %d shadow: %d bpp:%d RGBA:%d %d %d %d\n", (int)x, (int)y, (int)gdrw->shadow, (int)gdrw->bpp, (int)ptr[0], (int)ptr[1], (int)ptr[2], (int)ptr[3]);
- */
- } /* end p_put_pixel */
-
- void
- p_put_mix_pixel (t_GDRW *gdrw,
- gint32 x,
- gint32 y,
- guchar *color,
- gint32 nb_curvy,
- gint32 nb2_curvy,
- gint32 curvy)
- {
- guchar l_pixel[4];
- guchar l_mixmask;
- gint l_idx;
- gint l_diff;
-
- l_mixmask = 255 - 96;
- l_diff = abs(nb_curvy - curvy);
- if(l_diff == 0)
- {
- l_mixmask = 255 - 48;
- l_diff = abs(nb2_curvy - curvy);
-
- if(l_diff == 0)
- {
- /* last 2 neighbours were not shifted against current pixel, do not mix */
- p_put_pixel(gdrw, x, y, color);
- return;
- }
- }
-
- /* get left neighbour pixel */
- p_get_pixel(gdrw, x-1, y, &l_pixel[0]);
-
- if(l_pixel[gdrw->index_alpha] < 10)
- {
- /* neighbour is (nearly or full) transparent, do not mix */
- p_put_pixel(gdrw, x, y, color);
- return;
- }
-
- for(l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
- {
- /* 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]);
- }
-
- void
- p_put_mix_pixel_FIX (t_GDRW *gdrw,
- gint32 x,
- gint32 y,
- guchar *color,
- gint32 nb_curvy,
- gint32 nb2_curvy,
- gint32 curvy)
- {
- guchar l_pixel[4];
- guchar l_mixmask;
- gint l_idx;
-
- l_mixmask = 256 - 64;
-
- /* get left neighbour pixel */
- p_get_pixel(gdrw, x-1, y, &l_pixel[0]);
-
- if(l_pixel[gdrw->index_alpha] < 20)
- {
- /* neighbour is (nearly or full) transparent, do not mix */
- p_put_pixel(gdrw, x, y, color);
- return;
- }
-
- for(l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
- {
- /* 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
- * ============================================================================
- */
-
- void
- p_clear_drawable (GimpDrawable *drawable)
- {
- GimpPixelRgn pixel_rgn;
- gpointer pr;
- gint l_row;
- guchar *l_ptr;
-
-
- gimp_pixel_rgn_init (&pixel_rgn, drawable,
- 0, 0, drawable->width, drawable->height,
- TRUE, /* dirty */
- FALSE /* shadow */
- );
-
- /* clear the drawable with 0 Bytes (black full-transparent pixels) */
- for (pr = gimp_pixel_rgns_register (1, &pixel_rgn);
- pr != NULL; pr = gimp_pixel_rgns_process (pr))
- {
- l_ptr = pixel_rgn.data;
- for ( l_row = 0; l_row < pixel_rgn.h; l_row++ )
- {
- memset(l_ptr, 0, pixel_rgn.w * drawable->bpp);
- l_ptr += pixel_rgn.rowstride;
- }
- }
- } /* end p_clear_drawable */
-
- /* ============================================================================
- * p_create_pv_image
- * ============================================================================
- */
- gint32
- p_create_pv_image (GimpDrawable *src_drawable,
- gint32 *layer_id)
- {
- gint32 l_new_image_id;
- guint l_new_width;
- guint l_new_height;
- GimpImageType l_type;
-
- gint l_x, l_y;
- double l_scale;
- guchar l_pixel[4];
- GimpDrawable *dst_drawable;
- t_GDRW l_src_gdrw;
- t_GDRW l_dst_gdrw;
-
- l_new_image_id = gimp_image_new(PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
- gimp_image_base_type(gimp_layer_get_image_id(src_drawable->id)));
- gimp_image_undo_disable (l_new_image_id);
-
- l_type = gimp_drawable_type(src_drawable->id);
- if(src_drawable->height > src_drawable->width)
- {
- 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,
- l_type,
- 100.0, /* opacity */
- 0 /* mode NORMAL */
- );
- if(!gimp_drawable_has_alpha(*layer_id))
- {
- /* always add alpha channel */
- gimp_layer_add_alpha(*layer_id);
- }
-
- 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);
-
- for(l_y = 0; l_y < l_new_height; l_y++)
- {
- for(l_x = 0; l_x < l_new_width; l_x++)
- {
- 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]);
- }
- }
-
- p_end_gdrw(&l_src_gdrw);
- p_end_gdrw(&l_dst_gdrw);
-
- /* gimp_display_new(l_new_image_id); */
- return (l_new_image_id);
- }
-
- /* ============================================================================
- * p_add_layer
- * ============================================================================
- */
- GimpDrawable*
- p_add_layer (gint width,
- gint height,
- GimpDrawable *src_drawable)
- {
- GimpImageType l_type;
- static GimpDrawable *l_new_drawable;
- gint32 l_new_layer_id;
- char *l_name;
- char *l_name2;
- gdouble l_opacity;
- GimpLayerModeEffects l_mode;
- gint l_visible;
- gint32 image_id;
- gint stack_position;
-
-
- image_id = gimp_layer_get_image_id(src_drawable->id);
- stack_position = 0; /* TODO: should be same as src_layer */
-
- /* copy type, name, opacity and mode from src_drawable */
- l_type = gimp_drawable_type(src_drawable->id);
- l_visible = gimp_layer_get_visible(src_drawable->id);
-
- if (TRUE != TRUE)
- {
- l_name = gimp_layer_get_name(src_drawable->id);
- }
- else
- {
- l_name2 = gimp_layer_get_name(src_drawable->id);
- l_name = g_malloc(strlen(l_name2) + 10);
- if(l_name == NULL)
- return (NULL);
- sprintf(l_name, "%s_b", l_name2);
- g_free(l_name2);
- }
- l_mode = gimp_layer_get_mode(src_drawable->id);
- l_opacity = gimp_layer_get_opacity(src_drawable->id); /* full opacity */
-
- l_new_layer_id = gimp_layer_new(image_id, l_name,
- width, height,
- l_type,
- l_opacity,
- l_mode
- );
-
- if(l_name != NULL) g_free (l_name);
- if(!gimp_drawable_has_alpha(l_new_layer_id))
- {
- /* always add alpha channel */
- gimp_layer_add_alpha(l_new_layer_id);
- }
-
- l_new_drawable = gimp_drawable_get (l_new_layer_id);
- if(l_new_drawable == NULL)
- {
- fprintf(stderr, "p_ad_layer: cant get new_drawable\n");
- return (NULL);
- }
-
- /* add the copied layer to the temp. working image */
- gimp_image_add_layer (image_id, l_new_layer_id, stack_position);
-
- /* copy visiblity state */
- gimp_layer_set_visible(l_new_layer_id, l_visible);
-
- return (l_new_drawable);
- }
-
- /* ============================================================================
- * p_bender_calculate_iter_curve
- * ============================================================================
- */
-
-
- void
- p_bender_calculate_iter_curve (BenderDialog *cd,
- gint32 xmax,
- gint32 ymax)
- {
- int l_x;
- gint l_outline;
- BenderDialog *cd_from;
- BenderDialog *cd_to;
-
- l_outline = cd->outline;
-
- if((cd->bval_from == NULL) || (cd->bval_to == NULL) || (cd->bval_curr == NULL))
- {
- 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);
- }
- }
- else
- {
- /* 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_malloc (sizeof (BenderDialog));
- p_cd_from_bval(cd_from, cd->bval_from);
- cd_from->curve_ptr[OUTLINE_UPPER] = g_malloc(sizeof(gint32) * (1+xmax));
- cd_from->curve_ptr[OUTLINE_LOWER] = g_malloc(sizeof(gint32) * (1+xmax));
-
- /* init TO curves */
- cd_to = g_malloc (sizeof (BenderDialog));
- p_cd_from_bval(cd_to, cd->bval_to);
- cd_to->curve_ptr[OUTLINE_UPPER] = g_malloc(sizeof(gint32) * (1+xmax));
- cd_to->curve_ptr[OUTLINE_LOWER] = g_malloc(sizeof(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);
-
- }
-
- cd->outline = l_outline;
- } /* end p_bender_calculate_iter_curve */
-
- /* ============================================================================
- * p_vertical_bend
- * ============================================================================
- */
-
- int
- p_vertical_bend (BenderDialog *cd,
- t_GDRW *src_gdrw,
- t_GDRW *dst_gdrw)
- {
- 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);
- 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_malloc(sizeof(t_Last) * src_gdrw->x2);
- first_arr = g_malloc(sizeof(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)
- */
-
- 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);
-
- /* 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;
- if(cd->show_progress) gimp_progress_init ( _("Curve Bend..."));
-
- 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++)
- {
- 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 ;
-
- /* printf("X: %4d Y:%4d Y2:%4d\n", (int)l_x, (int)l_y, (int)l_y2); */
-
- for( ; l_y < l_y2; l_y++)
- {
- /* ---------- copy SRC_PIXEL to curve position ------ */
-
- p_get_pixel(src_gdrw, l_x, l_y, &color[0]);
-
- 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 == TRUE) && (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[0], l_nb_curvy, l_nb2_curvy, l_curvy );
- }
- else
- {
- p_put_pixel(dst_gdrw, l_x, l_desty, &color[0]);
- }
-
- /* ----------- 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[0], &color[0], dst_gdrw->drawable->bpp);
-
- if(l_x > 0)
- {
- memcpy(&mixcolor[0], &first_arr[l_x-1].color[0], 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[0], &last_arr[l_x-1].color[0], 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->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[0]);
- }
- else
- {
- p_put_pixel(dst_gdrw, l_x -1, l_y + l_topshift + (l_maxy - l_dy), &mixcolor[0]);
- }
-
- }
- }
- }
-
- /* ------------------ 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[0], &color[0], 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 == TRUE)
- {
- /* smooting is on, so we are using a mixed color */
- l_mixmask = 255 * ((gdouble)(l_dy) / (gdouble)(l_diff+1));
- mixcolor[0] = MIX_CHANNEL(last_arr[l_x].color[0], color[0], l_mixmask);
- mixcolor[1] = MIX_CHANNEL(last_arr[l_x].color[1], color[1], l_mixmask);
- mixcolor[2] = MIX_CHANNEL(last_arr[l_x].color[2], color[2], l_mixmask);
- mixcolor[3] = MIX_CHANNEL(last_arr[l_x].color[3], color[3], l_mixmask);
- }
- else
- {
- /* smooting is off, so we are using this color or the last color */
- if(l_dy < l_diff / 2)
- {
- memcpy(&mixcolor[0], &color[0], dst_gdrw->drawable->bpp);
- }
- else
- {
- memcpy(&mixcolor[0], &last_arr[l_x].color[0], dst_gdrw->drawable->bpp);
- }
- }
-
- if(cd->smoothing == TRUE)
- {
- p_put_mix_pixel(dst_gdrw, l_x, l_desty + (l_dy * l_sign), &mixcolor[0],
- l_nb_curvy, l_nb2_curvy, l_curvy );
- }
- else
- {
- p_put_pixel(dst_gdrw, l_x, l_desty + (l_dy * l_sign), &mixcolor[0]);
- }
- }
-
- /* store y and color */
- last_arr[l_x].y = l_curvy;
- memcpy(&last_arr[l_x].color[0], &color[0], dst_gdrw->drawable->bpp);
-
-
- }
- }
- }
- }
-
- if (gb_debug)
- printf("ROWS: %d - %d COLS: %d - %d\n",
- (int)l_first_row, (int)l_last_row, (int)l_first_col, (int)l_last_col);
-
- return 0;
-
- }
-
- /* ============================================================================
- * p_main_bend
- * ============================================================================
- */
-
- gint32
- p_main_bend (BenderDialog *cd,
- GimpDrawable *original_drawable,
- gint work_on_copy)
- {
- t_GDRW l_src_gdrw;
- t_GDRW l_dst_gdrw;
- GimpDrawable *dst_drawable;
- GimpDrawable *src_drawable;
- gint32 l_dst_height;
- 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;
-
- l_interpolation = cd->smoothing;
- l_image_id = gimp_layer_get_image_id(original_drawable->id);
- gimp_drawable_offsets(original_drawable->id, &l_offset_x, &l_offset_y);
-
- l_center_x = l_offset_x + (gimp_drawable_width (original_drawable->id) / 2 );
- l_center_y = l_offset_y + (gimp_drawable_height (original_drawable->id) / 2 );
-
- /* always copy original_drawable to a tmp src_layer */
- l_tmp_layer_id = gimp_layer_copy(original_drawable->id);
- /* set layer invisible and dummyname and
- * 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);
- gimp_layer_set_visible(l_tmp_layer_id, FALSE);
- gimp_layer_set_name(l_tmp_layer_id, "curve_bend_dummylayer");
-
- if(gb_debug) printf("p_main_bend l_tmp_layer_id %d\n", (int)l_tmp_layer_id);
-
- if(cd->rotation != 0.0)
- {
- 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);
- }
- src_drawable = gimp_drawable_get (l_tmp_layer_id);
-
- xmax = ymax = src_drawable->width -1;
- cd->curve_ptr[OUTLINE_UPPER] = g_malloc(sizeof(gint32) * (1+xmax));
- cd->curve_ptr[OUTLINE_LOWER] = g_malloc(sizeof(gint32) * (1+xmax));
-
- p_bender_calculate_iter_curve(cd, xmax, ymax);
- bender_init_min_max(cd, xmax);
-
- l_dst_height = src_drawable->height
- + p_upper_curve_extend(cd, src_drawable->width, src_drawable->height)
- + p_lower_curve_extend(cd, src_drawable->width, src_drawable->height);
-
- if(gb_debug) printf("p_main_bend: l_dst_height:%d\n", (int)l_dst_height);
-
- if(work_on_copy)
- {
- dst_drawable = p_add_layer(src_drawable->width, l_dst_height, src_drawable);
- if(gb_debug) printf("p_main_bend: DONE add layer\n");
- }
- else
- {
- /* work on the original */
- gimp_layer_resize(original_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->id))
- {
- /* always add alpha channel */
- gimp_layer_add_alpha(original_drawable->id);
- }
- dst_drawable = gimp_drawable_get (original_drawable->id);
- }
- 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);
-
- if(gb_debug) printf("p_main_bend: DONE vertical bend\n");
-
- p_end_gdrw(&l_src_gdrw);
- p_end_gdrw(&l_dst_gdrw);
-
- if(cd->rotation != 0.0)
- {
- p_gimp_rotate(l_image_id, dst_drawable->id, l_interpolation, (gdouble)(360.0 - cd->rotation));
-
- /* TODO: here we should crop dst_drawable to cut off full transparent borderpixels */
-
- }
-
- /* set offsets of the resulting new layer
- *(center == center of original_drawable)
- */
- l_offset_x = l_center_x - (gimp_drawable_width (dst_drawable->id) / 2 );
- l_offset_y = l_center_y - (gimp_drawable_height (dst_drawable->id) / 2 );
- gimp_layer_set_offsets (dst_drawable->id, l_offset_x, l_offset_y);
-
- /* delete the temp layer */
- gimp_image_remove_layer(l_image_id, l_tmp_layer_id);
-
- g_free(cd->curve_ptr[OUTLINE_UPPER]);
- g_free(cd->curve_ptr[OUTLINE_LOWER]);
-
- if(gb_debug) printf("p_main_bend: DONE bend main\n");
-
- return dst_drawable->id;
- } /* end p_main_bend */
-