home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / curve_bend.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  108.6 KB  |  3,664 lines

  1. /* curve_bend plugin for the GIMP (tested with GIMP 1.1.17, requires gtk+ 1.2) */
  2.  
  3. /* The GIMP -- an image manipulation program
  4.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  */
  20.  
  21. /* Revision history
  22.  *  (2000/02/16)  v1.1.17b hof: added spinbuttons for rotate entry
  23.  *  (2000/02/16)  v1.1.17 hof: undo bugfix (#6012)
  24.  *                             don't call gimp_undo_push_group_end 
  25.  *                             after gimp_displays_flush
  26.  *  (1999/09/13)  v1.01  hof: PDB-calls updated for gimp 1.1.9
  27.  *  (1999/05/10)  v1.0   hof: first public release
  28.  *  (1999/04/23)  v0.0   hof: coding started,
  29.  *                            splines and dialog parts are similar to curves.c
  30.  */
  31.  
  32. #include "config.h"
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37.  
  38. #include <gtk/gtk.h>
  39.  
  40. #include <libgimp/gimp.h>
  41. #include <libgimp/gimpui.h>
  42.  
  43. #include "libgimp/stdplugins-intl.h"
  44.  
  45.  
  46. /* Defines */
  47. #define PLUG_IN_NAME        "plug_in_curve_bend"
  48. #define PLUG_IN_VERSION     "v1.1.17 (2000/02/16)"
  49. #define PLUG_IN_IMAGE_TYPES "RGB*, GRAY*"
  50. #define PLUG_IN_AUTHOR      "Wolfgang Hofer (hof@hotbot.com)"
  51. #define PLUG_IN_COPYRIGHT   "Wolfgang Hofer"
  52. #define PLUG_IN_DESCRIPTION "Bends a layer using 2 spline-curves"
  53.  
  54. #define PLUG_IN_ITER_NAME       "plug_in_curve_bend_Iterator"
  55. #define PLUG_IN_DATA_ITER_FROM  "plug_in_curve_bend_ITER_FROM"
  56. #define PLUG_IN_DATA_ITER_TO    "plug_in_curve_bend_ITER_TO"
  57.  
  58. #define KEY_POINTFILE "POINTFILE_CURVE_BEND"
  59. #define KEY_POINTS    "POINTS"
  60. #define KEY_VAL_Y     "VAL_Y"
  61.  
  62. #define MIDDLE 127
  63.  
  64. #define SIGNED_ROUND(x)  ((int) (((x < 0) ? (x) - 0.5 : (x) + 0.5)  ))
  65. #define MIX_CHANNEL(a, b, m)  (((a * m) + (b * (255 - m))) / 255)
  66.  
  67. #define UP_GRAPH              0x1
  68. #define UP_XRANGE_TOP         0x2
  69. #define UP_PREVIEW_EXPOSE     0x4
  70. #define UP_PREVIEW            0x8
  71. #define UP_DRAW               0x10
  72. #define UP_ALL                0xFF
  73.  
  74. #define ENTRY_WIDTH      50
  75. #define GRAPH_WIDTH      256
  76. #define GRAPH_HEIGHT     256
  77. #define PREVIEW_SIZE_X   256
  78. #define PREVIEW_SIZE_Y   256
  79. #define PV_IMG_WIDTH     128
  80. #define PV_IMG_HEIGHT    128
  81. #define RADIUS           3
  82. #define MIN_DISTANCE     8
  83. #define PREVIEW_BPP      3
  84. #define PREVIEW_BG_GRAY1 108
  85. #define PREVIEW_BG_GRAY2 156
  86.  
  87. #define SMOOTH       0
  88. #define GFREE        1
  89.  
  90. #define RANGE_MASK  GDK_EXPOSURE_MASK | \
  91.                     GDK_ENTER_NOTIFY_MASK
  92.  
  93. #define GRAPH_MASK  GDK_EXPOSURE_MASK | \
  94.             GDK_POINTER_MOTION_MASK | \
  95.             GDK_POINTER_MOTION_HINT_MASK | \
  96.                     GDK_ENTER_NOTIFY_MASK | \
  97.             GDK_BUTTON_PRESS_MASK | \
  98.             GDK_BUTTON_RELEASE_MASK | \
  99.             GDK_BUTTON1_MOTION_MASK
  100.  
  101.  
  102. #define OUTLINE_UPPER    0
  103. #define OUTLINE_LOWER    1
  104.  
  105. typedef struct _BenderValues BenderValues;
  106. struct _BenderValues
  107. {
  108.   guchar  curve[2][256];            /* for curve_type freehand mode   0   <= curve  <= 255 */
  109.   gdouble points[2][17][2];         /* for curve_type smooth mode     0.0 <= points <= 1.0 */
  110.  
  111.   int            curve_type;
  112.  
  113.   gint           smoothing;
  114.   gint           antialias;
  115.   gint           work_on_copy;
  116.   gdouble        rotation;
  117.   
  118.   
  119.   gint32         total_steps;
  120.   gdouble        current_step;
  121. };
  122.  
  123.  
  124. typedef struct _Curves Curves;
  125.  
  126. struct _Curves
  127. {
  128.   int x, y;    /*  coords for last mouse click  */
  129. };
  130.  
  131. typedef struct _BenderDialog BenderDialog;
  132.  
  133. struct _BenderDialog
  134. {
  135.   GtkWidget *shell;
  136.   GtkWidget *outline_menu;
  137.   GtkWidget *pv_widget;
  138.   GtkWidget *graph;
  139.   GtkAdjustment *rotate_data;
  140.   GdkPixmap *pixmap;
  141.   GtkWidget *filesel;
  142.  
  143.   GimpDrawable *drawable;
  144.   int        color;
  145.   int        outline;
  146.   gint       preview;
  147.  
  148.   int        grab_point;
  149.   int        last;
  150.   int        leftmost;
  151.   int        rightmost;
  152.   int        curve_type;
  153.   gdouble    points[2][17][2];    /*  0.0 <= points    <= 1.0 */
  154.   guchar     curve[2][256];       /*  0   <= curve     <= 255 */
  155.   gint32    *curve_ptr[2];        /*  0   <= curve_ptr <= src_drawable_width 
  156.                    *  both arrays are allocated dynamic,
  157.                    *  depending on drawable width
  158.                    */
  159.   gint32     min2[2];
  160.   gint32     max2[2];
  161.   gint32     zero2[2];
  162.     
  163.   gint       show_progress;
  164.   gint       smoothing;
  165.   gint       antialias;
  166.   gint       work_on_copy;
  167.   gdouble    rotation;
  168.   
  169.   
  170.   gint32     preview_image_id;
  171.   gint32     preview_layer_id1;
  172.   gint32     preview_layer_id2;
  173.   
  174.   BenderValues  *bval_from;
  175.   BenderValues  *bval_to;
  176.   BenderValues  *bval_curr;
  177.  
  178.   gint           run;
  179. };
  180.  
  181. /* points Coords:
  182.  *
  183.  *  1.0 +----+----+----+----+ 
  184.  *      |    .    |    |    | 
  185.  *      +--.-+--.-+----+----+ 
  186.  *      .    |    .    |    |  
  187.  *  0.5 +----+----+-.--+----+ 
  188.  *      |    |    |    .    . 
  189.  *      +----+----+----+-.-.+ 
  190.  *      |    |    |    |    | 
  191.  *  0.0 +----+----+----+----+ 
  192.  *      0.0      0.5       1.0
  193.  *
  194.  * curve Coords:
  195.  *
  196.  *      OUTLINE_UPPER                                       OUTLINE_LOWER
  197.  *
  198.  *  255 +----+----+----+----+                          255 +----+----+----+----+
  199.  *      |    .    |    |    |  ---   max               |    .    |    |    |  ---    max
  200.  *      +--.-+--.-+----+----+                       +--.-+--.-+----+----+
  201.  *      .    |    .    |    |             zero ___  .    |    .    |    |                 
  202.  *      +----+----+-.--+----+                      +----+----+-.--+----+
  203.  *      |    |    |    .    .  ---   zero                     |    |    |    .    .  
  204.  *      +----+----+----+-.-.+  ___   min               +----+----+----+-.-.+  ___    min
  205.  *      |    |    |    |    |                       |    |    |    |    |
  206.  *    0 +----+----+----+----+                     0 +----+----+----+----+
  207.  *      0                   255                    0               255
  208.  */
  209.  
  210. typedef double CRMatrix[4][4];
  211.  
  212.  
  213. /* p_buildmenu Structures */
  214.  
  215. typedef struct _MenuItem   MenuItem;
  216.  
  217. typedef void (*MenuItemCallback) (GtkWidget *widget,
  218.                   gpointer   user_data);
  219. struct _MenuItem
  220. {
  221.   gchar *label;
  222.   gchar  unused_accelerator_key;
  223.   gint   unused_accelerator_mods;
  224.   MenuItemCallback callback;
  225.   gpointer user_data;
  226.   MenuItem *unused_subitems;
  227.   GtkWidget *widget;
  228. };
  229.  
  230. typedef struct
  231. {
  232.   GimpDrawable *drawable;
  233.   GimpPixelRgn  pr;
  234.   gint       x1;
  235.   gint       y1;
  236.   gint       x2;
  237.   gint       y2;
  238.   gint       index_alpha;   /* 0 == no alpha, 1 == GREYA, 3 == RGBA */
  239.   gint       bpp;
  240.   GimpTile     *tile;
  241.   gint       tile_row;
  242.   gint       tile_col;
  243.   gint       tile_width;
  244.   gint       tile_height;
  245.   gint       tile_dirty;
  246.   gint       shadow;
  247.   gint32     seldeltax;
  248.   gint32     seldeltay;
  249.   gint32     tile_swapcount;   
  250. } t_GDRW;
  251.  
  252. typedef struct
  253. {
  254.   gint32 y;
  255.   guchar color[4];
  256. } t_Last;
  257.  
  258.  
  259. /*  curves action functions  */
  260. static void  query (void);
  261. static void  run   (gchar   *name,
  262.             gint     nparams,
  263.             GimpParam  *param,
  264.             gint    *nreturn_vals,
  265.             GimpParam **return_vals);
  266.  
  267. static BenderDialog *  bender_new_dialog              (GimpDrawable *);
  268. static void            bender_update                  (BenderDialog *, int);
  269. static void            bender_plot_curve              (BenderDialog *,
  270.                                int, int, int, int,
  271.                                gint32, gint32, gint);
  272. static void            bender_calculate_curve         (BenderDialog *, gint32,
  273.                                gint32, gint);
  274. static void            bender_rotate_adj_callback     (GtkAdjustment *, gpointer);
  275. static void            bender_upper_callback          (GtkWidget *, gpointer);
  276. static void            bender_lower_callback          (GtkWidget *, gpointer);
  277. static void            bender_smooth_callback         (GtkWidget *, gpointer);
  278. static void            bender_free_callback           (GtkWidget *, gpointer);
  279. static void            bender_reset_callback          (GtkWidget *, gpointer);
  280. static void            bender_copy_callback           (GtkWidget *, gpointer);
  281. static void            bender_copy_inv_callback       (GtkWidget *, gpointer);
  282. static void            bender_swap_callback           (GtkWidget *, gpointer);
  283. static void            bender_ok_callback             (GtkWidget *, gpointer);
  284. static void            bender_cancel_callback         (GtkWidget *, gpointer);
  285. static void            bender_smoothing_callback      (GtkWidget *, gpointer);
  286. static void            bender_antialias_callback      (GtkWidget *, gpointer);
  287. static void            bender_work_on_copy_callback   (GtkWidget *, gpointer);
  288. static void            bender_preview_update          (GtkWidget *, gpointer);
  289. static void            bender_preview_update_once     (GtkWidget *, gpointer);
  290. static void            bender_load_callback           (GtkWidget *, gpointer);
  291. static void            bender_save_callback           (GtkWidget *, gpointer);
  292. static gint            bender_pv_widget_events        (GtkWidget *, GdkEvent *,
  293.                                BenderDialog *);
  294. static gint            bender_graph_events            (GtkWidget *, GdkEvent *,
  295.                                BenderDialog *);
  296. static void            bender_CR_compose              (CRMatrix, CRMatrix,
  297.                                CRMatrix);
  298. static void            bender_init_min_max            (BenderDialog *, gint32);
  299. static BenderDialog *  do_dialog                      (GimpDrawable *);
  300. GtkWidget           *  p_buildmenu                    (MenuItem *);
  301. static void            p_init_gdrw                    (t_GDRW *gdrw, GimpDrawable *drawable, 
  302.                                int dirty, int shadow);
  303. static void            p_end_gdrw                     (t_GDRW *gdrw);
  304. static gint32          p_main_bend                    (BenderDialog *, GimpDrawable *, gint);
  305. static gint32          p_create_pv_image              (GimpDrawable *src_drawable, gint32 *layer_id);
  306. static void            p_render_preview               (BenderDialog *cd, gint32 layer_id);
  307. static void            p_get_pixel                    (t_GDRW *gdrw, 
  308.                                gint32 x, gint32 y, guchar *pixel);
  309. static void            p_put_pixel                    (t_GDRW *gdrw, 
  310.                                gint32 x, gint32 y, guchar *pixel);
  311. static void            p_put_mix_pixel                (t_GDRW *gdrw, 
  312.                                gint32 x, gint32 y, guchar *color, 
  313.                                gint32 nb_curvy, gint32 nb2_curvy, 
  314.                                gint32 curvy);
  315. static void            p_stretch_curves               (BenderDialog *cd, gint32 xmax, gint32 ymax);
  316. static void            p_cd_to_bval                   (BenderDialog *cd, BenderValues *bval);
  317. static void            p_cd_from_bval                 (BenderDialog *cd, BenderValues *bval);
  318. static void            p_store_values                 (BenderDialog *cd);
  319. static void            p_retrieve_values              (BenderDialog *cd);
  320. static void            p_bender_calculate_iter_curve  (BenderDialog *cd, gint32 xmax, gint32 ymax);
  321. static void            p_delta_gdouble                (double *val, double val_from, double val_to, 
  322.                                gint32 total_steps, gdouble current_step);
  323. static void            p_delta_gint32                 (gint32 *val, gint32 val_from, gint32 val_to, 
  324.                                gint32 total_steps, gdouble current_step);
  325. static void            p_copy_points                  (BenderDialog *cd, int outline, int xy,  
  326.                                int argc, gdouble *floatarray);
  327. static void            p_copy_yval                    (BenderDialog *cd, int outline,  
  328.                                int argc, gint8 *int8array);
  329. static int             p_save_pointfile               (BenderDialog *cd, char *filename);
  330.  
  331.  
  332. /* Global Variables */
  333. GimpPlugInInfo PLUG_IN_INFO =
  334. {
  335.   NULL,   /* init_proc  */
  336.   NULL,   /* quit_proc  */
  337.   query,  /* query_proc */
  338.   run     /* run_proc   */
  339. };
  340.  
  341. static CRMatrix CR_basis =
  342. {
  343.   { -0.5,  1.5, -1.5,  0.5 },
  344.   {  1.0, -2.5,  2.0, -0.5 },
  345.   { -0.5,  0.0,  0.5,  0.0 },
  346.   {  0.0,  1.0,  0.0,  0.0 },
  347. };
  348.  
  349. static MenuItem outline_items[] =
  350. {
  351.   { N_("Upper"), 0, 0, bender_upper_callback, NULL, NULL, NULL },
  352.   { N_("Lower"), 0, 0, bender_lower_callback, NULL, NULL, NULL },
  353.   { NULL, 0, 0, NULL, NULL, NULL, NULL }
  354. };
  355.  
  356. static MenuItem curve_type_items[] =
  357. {
  358.   { N_("Smooth"), 0, 0, bender_smooth_callback, NULL, NULL, NULL },
  359.   { N_("Free"), 0, 0, bender_free_callback, NULL, NULL, NULL },
  360.   { NULL, 0, 0, NULL, NULL, NULL, NULL }
  361. };
  362.  
  363. int gb_debug = FALSE;
  364.  
  365. /* Functions */
  366. /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX PDB_STUFF XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
  367.  
  368. /* ============================================================================
  369.  * p_pdb_procedure_available
  370.  *   if requested procedure is available in the PDB return the number of args
  371.  *      (0 upto n) that are needed to call the procedure.
  372.  *   if not available return -1
  373.  * ============================================================================
  374.  */
  375.  
  376. gint 
  377. p_pdb_procedure_available (char *proc_name)
  378. {    
  379.   gint             l_nparams;
  380.   gint             l_nreturn_vals;
  381.   GimpPDBProcType  l_proc_type;
  382.   gchar           *l_proc_blurb;
  383.   gchar           *l_proc_help;
  384.   gchar           *l_proc_author;
  385.   gchar           *l_proc_copyright;
  386.   gchar           *l_proc_date;
  387.   GimpParamDef    *l_params;
  388.   GimpParamDef    *l_return_vals;
  389.   gint             l_rc;
  390.  
  391.   l_rc = 0;
  392.   
  393.   /* Query the gimp application's procedural database
  394.    *  regarding a particular procedure.
  395.    */
  396.   if (gimp_procedural_db_proc_info (proc_name,
  397.                     &l_proc_blurb,
  398.                     &l_proc_help,
  399.                     &l_proc_author,
  400.                     &l_proc_copyright,
  401.                     &l_proc_date,
  402.                     &l_proc_type,
  403.                     &l_nparams, &l_nreturn_vals,
  404.                     &l_params, &l_return_vals))
  405.   {
  406.      /* procedure found in PDB */
  407.      return (l_nparams);
  408.   }
  409.  
  410.   printf("Warning: Procedure %s not found.\n", proc_name);
  411.   return -1;
  412. }    /* end p_pdb_procedure_available */
  413.  
  414.  
  415. /* ============================================================================
  416.  * p_gimp_rotate
  417.  *  PDB call of 'gimp_rotate'
  418.  * ============================================================================
  419.  */
  420.  
  421. gint 
  422. p_gimp_rotate (gint32  image_id, 
  423.            gint32  drawable_id, 
  424.            gint32  interpolation, 
  425.            gdouble angle_deg)
  426. {
  427.    static char     *l_rotate_proc = "gimp_rotate";
  428.    GimpParam          *return_vals;
  429.    int              nreturn_vals;
  430.    gdouble          l_angle_rad;
  431.    int              l_nparams;
  432.    int              l_rc;
  433.  
  434. #ifdef ROTATE_OPTIMIZE
  435.    static char     *l_rotate_proc2 = "plug_in_rotate";
  436.    gint32 l_angle_step;
  437.  
  438.    if     (angle_deg == 90.0)  { l_angle_step = 1; }
  439.    else if(angle_deg == 180.0) { l_angle_step = 2; }
  440.    else if(angle_deg == 270.0) { l_angle_step = 3; }   
  441.    else                        { l_angle_step = 0; }
  442.  
  443.    if(l_angle_step != 0)
  444.    {
  445.       l_nparams = p_pdb_procedure_available(l_rotate_proc2);
  446.       if (l_nparams == 5)
  447.       {
  448.         /* use faster rotate plugin on multiples of 90 degrees */
  449.         return_vals = gimp_run_procedure (l_rotate_proc2,
  450.                                           &nreturn_vals,
  451.                               GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE,
  452.                               GIMP_PDB_IMAGE, image_id,
  453.                                           GIMP_PDB_DRAWABLE, drawable_id,
  454.                               GIMP_PDB_INT32, l_angle_step,
  455.                               GIMP_PDB_INT32, FALSE,         /* dont rotate the whole image */
  456.                                           GIMP_PDB_END);
  457.         if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  458.         {
  459.           return 0;
  460.         }
  461.       
  462.       }
  463.    
  464.    }
  465. #endif
  466.  
  467.    l_rc = -1;
  468.    l_angle_rad = (angle_deg * G_PI) / 180.0;
  469.  
  470.    l_nparams = p_pdb_procedure_available(l_rotate_proc);
  471.    if (l_nparams >= 0)
  472.    {
  473.          /* use the new Interface (Gimp 1.1 style)
  474.           * (1.1 knows the image_id where the drawable belongs to)
  475.           */
  476.         return_vals = gimp_run_procedure (l_rotate_proc,
  477.                                           &nreturn_vals,
  478.                                           GIMP_PDB_DRAWABLE, drawable_id,
  479.                               GIMP_PDB_INT32, interpolation,
  480.                               GIMP_PDB_FLOAT, l_angle_rad,
  481.                                           GIMP_PDB_END);
  482.      if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  483.      {
  484.         l_rc = 0;
  485.      }
  486.      else
  487.      {
  488.        printf("Error: %s call failed %d\n", l_rotate_proc, (int)return_vals[0].data.d_status);
  489.      }
  490.  
  491.      gimp_destroy_params (return_vals, nreturn_vals);
  492.    }
  493.    else
  494.    {
  495.       printf("Error: Procedure %s not found.\n",l_rotate_proc);
  496.    }
  497.    return (l_rc);
  498.  
  499. }  /* end p_gimp_rotate */
  500.  
  501. /* ============================================================================
  502.  * p_gimp_edit_copy
  503.  *   
  504.  * ============================================================================
  505.  */
  506.  
  507. gint32  
  508. p_gimp_edit_copy (gint32 image_id, 
  509.           gint32 drawable_id)
  510. {
  511.    static char     *l_procname = "gimp_edit_copy";
  512.    GimpParam          *return_vals;
  513.    int              nreturn_vals;
  514.  
  515.    if (p_pdb_procedure_available(l_procname) >= 0)
  516.    {
  517.       return_vals = gimp_run_procedure (l_procname,
  518.                                     &nreturn_vals,
  519.                                     GIMP_PDB_DRAWABLE,  drawable_id,
  520.                                     GIMP_PDB_END);
  521.                                     
  522.       if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  523.       {
  524.          gimp_destroy_params (return_vals, nreturn_vals);
  525.          return 0;
  526.       }
  527.       printf("Error: PDB call of %s failed status:%d\n", l_procname, (int)return_vals[0].data.d_status);
  528.    }
  529.  
  530.    return(-1);
  531. }    /* end p_gimp_edit_copy */
  532.  
  533. /* ============================================================================
  534.  * p_gimp_edit_paste
  535.  *   
  536.  * ============================================================================
  537.  */
  538.  
  539. gint32  
  540. p_gimp_edit_paste (gint32 image_id, 
  541.            gint32 drawable_id, 
  542.            gint32 paste_into)
  543. {
  544.    static char     *l_procname = "gimp_edit_paste";
  545.    GimpParam          *return_vals;
  546.    int              nreturn_vals;
  547.    gint32           fsel_layer_id;
  548.  
  549.    if (p_pdb_procedure_available(l_procname) >= 0)
  550.    {
  551.       return_vals = gimp_run_procedure (l_procname,
  552.                                     &nreturn_vals,
  553.                                     GIMP_PDB_DRAWABLE,  drawable_id,
  554.                                     GIMP_PDB_INT32,     paste_into,
  555.                                     GIMP_PDB_END);
  556.                                     
  557.       if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  558.       {
  559.          fsel_layer_id = return_vals[1].data.d_layer;
  560.          gimp_destroy_params (return_vals, nreturn_vals);
  561.          return (fsel_layer_id);
  562.       }
  563.       printf("Error: PDB call of %s failed status:%d\n", l_procname, (int)return_vals[0].data.d_status);
  564.    }
  565.  
  566.    return(-1);
  567. }    /* end p_gimp_edit_paste */
  568.  
  569.  
  570. /* ============================================================================
  571.  * p_if_selection_float_it
  572.  * ============================================================================
  573.  */
  574.  
  575. gint32
  576. p_if_selection_float_it (gint32 image_id, 
  577.              gint32 layer_id)
  578. {
  579.   gint32   l_sel_channel_id;
  580.   gint32   l_layer_id;
  581.   gint32   l_x1, l_x2, l_y1, l_y2;
  582.   gint32   non_empty;
  583.  
  584.   l_layer_id = layer_id;
  585.   if(!gimp_layer_is_floating_selection (layer_id)  )
  586.   {
  587.     /* check and see if we have a selection mask */
  588.     l_sel_channel_id  = gimp_image_get_selection(image_id);     
  589.  
  590.     gimp_selection_bounds (image_id, &non_empty, &l_x1, &l_y1, &l_x2, &l_y2);
  591.     
  592.     if (non_empty && l_sel_channel_id >= 0)
  593.     {
  594.     /* selection is TRUE, make a layer (floating selection) from the selection  */
  595.         p_gimp_edit_copy(image_id, layer_id);
  596.     l_layer_id = p_gimp_edit_paste(image_id, layer_id, FALSE);
  597.  
  598.     }
  599.   }
  600.  
  601.   return(l_layer_id);
  602. }
  603.  
  604. /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX END_PDB_STUFF XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
  605.  
  606. /*
  607.  *    M      M    AAAAA    IIIIII    N     N
  608.  *    M M  M M   A     A     II      NN    N
  609.  *    M  M   M   AAAAAAA     II      N  N  N 
  610.  *    M      M   A     A     II      N    NN
  611.  *    M      M   A     A   IIIIII    N     N
  612.  */
  613.  
  614. MAIN ()
  615.  
  616. static void 
  617. query (void)
  618. {
  619.   static GimpParamDef args[] =
  620.   {
  621.     { GIMP_PDB_INT32,      "run_mode", "Interactive, non-interactive"},
  622.     { GIMP_PDB_IMAGE,      "image", "Input image" },
  623.     { GIMP_PDB_DRAWABLE,   "drawable", "Input drawable (must be a layer without layermask)"},
  624.     { GIMP_PDB_FLOAT,      "rotation", "Direction {angle 0 to 360 degree } of the bend effect"},
  625.     { GIMP_PDB_INT32,      "smoothing", "Smoothing { TRUE, FALSE }"},
  626.     { GIMP_PDB_INT32,      "antialias", "Antialias { TRUE, FALSE }"},
  627.     { GIMP_PDB_INT32,      "work_on_copy", "{ TRUE, FALSE } TRUE: copy the drawable and bend the copy"},
  628.     { GIMP_PDB_INT32,      "curve_type", " { 0, 1 } 0 == smooth (use 17 points), 1 == freehand (use 256 val_y) "},
  629.     { GIMP_PDB_INT32,      "argc_upper_point_x", "{2 <= argc <= 17} "},
  630.     { GIMP_PDB_FLOATARRAY, "upper_point_x", "array of 17 x point_koords { 0.0 <= x <= 1.0 or -1 for unused point }"},
  631.     { GIMP_PDB_INT32,      "argc_upper_point_y", "{2 <= argc <= 17} "},
  632.     { GIMP_PDB_FLOATARRAY, "upper_point_y", "array of 17 y point_koords { 0.0 <= y <= 1.0 or -1 for unused point }"},
  633.     { GIMP_PDB_INT32,      "argc_lower_point_x", "{2 <= argc <= 17} "},
  634.     { GIMP_PDB_FLOATARRAY, "lower_point_x", "array of 17 x point_koords { 0.0 <= x <= 1.0 or -1 for unused point }"},
  635.     { GIMP_PDB_INT32,      "argc_lower_point_y", "{2 <= argc <= 17} "},
  636.     { GIMP_PDB_FLOATARRAY, "lower_point_y", "array of 17 y point_koords { 0.0 <= y <= 1.0 or -1 for unused point }"},
  637.     { GIMP_PDB_INT32,      "argc_upper_val_y", "{ 256 } "},
  638.     { GIMP_PDB_INT8ARRAY,  "upper_val_y",   "array of 256 y freehand koord { 0 <= y <= 255 }"},
  639.     { GIMP_PDB_INT32,      "argc_lower_val_y", "{ 256 } "},
  640.     { GIMP_PDB_INT8ARRAY,  "lower_val_y",   "array of 256 y freehand koord { 0 <= y <= 255 }"}
  641.   };
  642.   static gint nargs = sizeof (args) / sizeof (args[0]);
  643.   
  644.   static GimpParamDef return_vals[] =
  645.   {
  646.     { GIMP_PDB_LAYER, "bent_layer", "the handled layer" }
  647.   };
  648.   static gint nreturn_vals = sizeof(return_vals) / sizeof(return_vals[0]);
  649.  
  650.   static GimpParamDef args_iter[] =
  651.   {
  652.     { GIMP_PDB_INT32, "run_mode", "non-interactive" },
  653.     { GIMP_PDB_INT32, "total_steps", "total number of steps (# of layers-1 to apply the related plug-in)" },
  654.     { GIMP_PDB_FLOAT, "current_step", "current (for linear iterations this is the layerstack position, otherwise some value inbetween)" },
  655.     { GIMP_PDB_INT32, "len_struct", "length of stored data structure with id is equal to the plug_in  proc_name" },
  656.   };
  657.   static gint nargs_iter = sizeof (args_iter) / sizeof (args_iter[0]);
  658.  
  659.   /* the actual installation of the bend plugin */
  660.   gimp_install_procedure (PLUG_IN_NAME,
  661.                           PLUG_IN_DESCRIPTION,
  662.                           "This plug-in does bend the active layer "
  663.               "If there is a current selection it is copied to floating selection "
  664.               "and the curve_bend distortion is done on the floating selection. "
  665.                           "If work_on_copy parameter is TRUE, the curve_bend distortion is done "
  666.               "on a copy of the active layer (or floating selection). "
  667.                           "The upper and lower edges are bent in shape of 2 spline curves. "
  668.                           "both (upper and lower) curves are determined by upto 17 points "
  669.                           "or by 256 Y-Values if curve_type == 1 (freehand mode) "
  670.                           "If rotation is not 0, the layer is rotated before "
  671.                           "and rotated back after the bend operation. This enables "
  672.                           "bending in other directions than vertical."
  673.                           "bending usually changes the size of the handled layer."
  674.                           "this plugin sets the offsets of the handled layer to keep its center at the same position"
  675.                           ,
  676.                           PLUG_IN_AUTHOR,
  677.                           PLUG_IN_COPYRIGHT,
  678.                           PLUG_IN_VERSION,
  679.                           N_("<Image>/Filters/Distorts/CurveBend..."),
  680.                           PLUG_IN_IMAGE_TYPES,
  681.                           GIMP_PLUGIN,
  682.                           nargs,
  683.                           nreturn_vals,
  684.                           args,
  685.                           return_vals);
  686.  
  687.    /* the installation of the Iterator extension for the bend plugin */
  688.   gimp_install_procedure (PLUG_IN_ITER_NAME,
  689.                           "This extension calculates the modified values for one iterationstep for the call of plug_in_curve_bend",
  690.                           "",
  691.                           PLUG_IN_AUTHOR,
  692.                           PLUG_IN_COPYRIGHT,
  693.                           PLUG_IN_VERSION,
  694.                           NULL,    /* do not appear in menus */
  695.                           NULL,
  696.                           GIMP_EXTENSION,
  697.                           nargs_iter, 0,
  698.                           args_iter, NULL);
  699. }
  700.  
  701. static void
  702. run (char    *name,           /* name of plugin */
  703.      int      nparams,        /* number of in-paramters */
  704.      GimpParam  *param,          /* in-parameters */
  705.      int     *nreturn_vals,   /* number of out-parameters */
  706.      GimpParam **return_vals)    /* out-parameters */
  707. {
  708.   char       *l_env;
  709.   BenderDialog *cd;
  710.   
  711.   GimpDrawable *l_active_drawable = NULL;
  712.   gint32    l_image_id = -1;
  713.   gint32    l_layer_id = -1;
  714.   gint32    l_layer_mask_id = -1;
  715.   gint32    l_bent_layer_id = -1;
  716.   
  717.   /* Get the runmode from the in-parameters */
  718.   GimpRunModeType run_mode = param[0].data.d_int32;
  719.  
  720.   /* status variable, use it to check for errors in invocation usualy only
  721.      during non-interactive calling */
  722.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  723.  
  724.   /*always return at least the status to the caller. */
  725.   static GimpParam values[2];
  726.  
  727.  
  728.   if (run_mode == GIMP_RUN_INTERACTIVE) {
  729.     INIT_I18N_UI();
  730.   } else {
  731.     INIT_I18N();
  732.   }
  733.  
  734.    cd = NULL;
  735.  
  736.   l_env = g_getenv("BEND_DEBUG");
  737.   if(l_env != NULL)
  738.   {
  739.     if((*l_env != 'n') && (*l_env != 'N')) gb_debug = 1;
  740.   }
  741.   
  742.   if(gb_debug) fprintf(stderr, "\n\nDEBUG: run %s\n", name);
  743.  
  744.   /* initialize the return of the status */
  745.   values[0].type = GIMP_PDB_STATUS;
  746.   values[0].data.d_status = status;
  747.   values[1].type = GIMP_PDB_LAYER;
  748.   values[1].data.d_int32 = -1;
  749.   *nreturn_vals = 2;
  750.   *return_vals = values;
  751.  
  752.   if (strcmp (name, PLUG_IN_ITER_NAME) == 0)
  753.   {
  754.      gint32  len_struct;
  755.      gint32  total_steps;
  756.      gdouble current_step;
  757.      BenderValues   bval;                  /* current values while iterating */
  758.      BenderValues   bval_from, bval_to;    /* start and end values */
  759.  
  760.         /* Iterator procedure for animated calls is usually called from
  761.          * "plug_in_gap_layers_run_animfilter"
  762.          * (always run noninteractive)
  763.          */
  764.         if ((run_mode == GIMP_RUN_NONINTERACTIVE) && (nparams == 4))
  765.         {
  766.           total_steps  =  param[1].data.d_int32;
  767.           current_step =  param[2].data.d_float;
  768.           len_struct   =  param[3].data.d_int32;
  769.  
  770.           if(len_struct == sizeof(bval))
  771.           {
  772.             /* get _FROM and _TO data, 
  773.              * This data was stored by plug_in_gap_layers_run_animfilter
  774.              */
  775.  
  776.  
  777.                gimp_get_data(PLUG_IN_DATA_ITER_FROM, &bval_from); 
  778.                gimp_get_data(PLUG_IN_DATA_ITER_TO,   &bval_to); 
  779.                memcpy(&bval, &bval_from, sizeof(bval));
  780.     
  781.                p_delta_gdouble(&bval.rotation, bval_from.rotation, bval_to.rotation, total_steps, current_step);
  782.                /* note: iteration of curve and points arrays would not give useful results.
  783.                 *       (there might be different number of points in the from/to bender values )
  784.                 *       the iteration is done later, (see p_bender_calculate_iter_curve)
  785.                 *       when the curve is calculated.
  786.                 */
  787.  
  788.                bval.total_steps = total_steps;
  789.                bval.current_step = current_step;
  790.  
  791.  
  792.                gimp_set_data(PLUG_IN_NAME, &bval, sizeof(bval));
  793.           }
  794.           else status = GIMP_PDB_CALLING_ERROR;
  795.         }
  796.         else status = GIMP_PDB_CALLING_ERROR;
  797.  
  798.         values[0].data.d_status = status;
  799.         return;
  800.   }
  801.  
  802.  
  803.  
  804.  
  805.   /* get image and drawable */
  806.   l_image_id = param[1].data.d_int32;
  807.   l_layer_id = param[2].data.d_drawable;
  808.  
  809.   gimp_undo_push_group_start (l_image_id);
  810.   
  811.   if(!gimp_drawable_is_layer(l_layer_id))
  812.   {
  813.      gimp_message(_("CurveBend operates on layers only (but was called on channel or mask)"));
  814.      printf("Passed drawable is no Layer\n");
  815.      status = GIMP_PDB_EXECUTION_ERROR; 
  816.   }
  817.   /* check for layermask */
  818.   l_layer_mask_id = gimp_layer_get_mask_id(l_layer_id);
  819.   if(l_layer_mask_id >= 0)
  820.   {
  821.      /* apply the layermask
  822.       *   some transitions (especially rotate) cant operate proper on
  823.       *   layers with masks !
  824.       */
  825.       gimp_image_remove_layer_mask(l_image_id, l_layer_id, 0 /* 0==APPLY */ );
  826.   }
  827.  
  828.   /* if there is a selection, make it the floating selection layer */
  829.   l_active_drawable = gimp_drawable_get (p_if_selection_float_it(l_image_id, l_layer_id));
  830.  
  831.  
  832.   /* how are we running today? */
  833.   if(status == GIMP_PDB_SUCCESS)
  834.   {
  835.     /* how are we running today? */
  836.     switch (run_mode)
  837.      {
  838.       case GIMP_RUN_INTERACTIVE:
  839.         /* Possibly retrieve data from a previous run */
  840.         /* gimp_get_data (PLUG_IN_NAME, &g_bndvals); */
  841.  
  842.         /* Get information from the dialog */
  843.         cd = do_dialog(l_active_drawable);
  844.         cd->show_progress = TRUE;
  845.         break;
  846.  
  847.       case GIMP_RUN_NONINTERACTIVE:
  848.         /* check to see if invoked with the correct number of parameters */
  849.         if (nparams >= 20)
  850.         {
  851.            cd = g_malloc (sizeof (BenderDialog));
  852.            cd->run = TRUE;
  853.            cd->show_progress = FALSE;
  854.            cd->drawable = l_active_drawable;
  855.  
  856.            cd->rotation      = (gdouble) param[3].data.d_float;
  857.            cd->smoothing     = (gint) param[4].data.d_int32;
  858.            cd->antialias     = (gint) param[5].data.d_int32;
  859.            cd->work_on_copy  = (gint) param[6].data.d_int32;
  860.            cd->curve_type    = (int)  param[7].data.d_int32;
  861.  
  862.            p_copy_points(cd, OUTLINE_UPPER, 0, (int)param[8].data.d_int32,  param[9].data.d_floatarray);
  863.            p_copy_points(cd, OUTLINE_UPPER, 1, (int)param[10].data.d_int32,  param[11].data.d_floatarray);
  864.            p_copy_points(cd, OUTLINE_LOWER, 0, (int)param[12].data.d_int32,  param[13].data.d_floatarray);
  865.            p_copy_points(cd, OUTLINE_LOWER, 1, (int)param[14].data.d_int32,  param[15].data.d_floatarray);
  866.  
  867.            p_copy_yval(cd, OUTLINE_UPPER, (int)param[16].data.d_int32, param[17].data.d_int8array);
  868.            p_copy_yval(cd, OUTLINE_UPPER, (int)param[18].data.d_int32, param[19].data.d_int8array);
  869.  
  870.         }
  871.         else
  872.         {
  873.           status = GIMP_PDB_CALLING_ERROR;
  874.         }
  875.  
  876.         break;
  877.  
  878.       case GIMP_RUN_WITH_LAST_VALS:
  879.         cd = g_malloc (sizeof (BenderDialog));
  880.         cd->run = TRUE;
  881.         cd->show_progress = TRUE;
  882.         cd->drawable = l_active_drawable;
  883.         p_retrieve_values(cd);  /* Possibly retrieve data from a previous run */
  884.         break;
  885.  
  886.       default:
  887.         break;
  888.     }
  889.   }
  890.  
  891.   if (cd == NULL)
  892.   {
  893.     status = GIMP_PDB_EXECUTION_ERROR;
  894.   }
  895.  
  896.   if (status == GIMP_PDB_SUCCESS)
  897.   {
  898.     /* Run the main function */
  899.  
  900.      if(cd->run)
  901.      {
  902.         l_bent_layer_id = p_main_bend(cd, cd->drawable, cd->work_on_copy);
  903.  
  904.     /* Store variable states for next run */
  905.     if (run_mode == GIMP_RUN_INTERACTIVE)
  906.     {
  907.             p_store_values(cd);
  908.     }     
  909.     }
  910.     else
  911.     {
  912.       status = GIMP_PDB_EXECUTION_ERROR;       /* dialog ended with cancel button */
  913.     }
  914.  
  915.     gimp_undo_push_group_end (l_image_id);
  916.  
  917.     /* If run mode is interactive, flush displays, else (script) don't
  918.        do it, as the screen updates would make the scripts slow */
  919.     if (run_mode != GIMP_RUN_NONINTERACTIVE)
  920.       gimp_displays_flush ();
  921.  
  922.   }
  923.   else
  924.   {
  925.     gimp_undo_push_group_end (l_image_id);
  926.   }
  927.   values[0].data.d_status = status;
  928.   values[1].data.d_int32 = l_bent_layer_id;   /* return the id of handled layer */
  929.  
  930.   if (gb_debug) 
  931.     printf ("end run curve_bend plugin\n");
  932.   
  933. }    /* end run */
  934.  
  935.  
  936. /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
  937. /*  Last_VALUEs and ITERATOR stuff   */
  938. /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
  939. int
  940. p_save_pointfile (BenderDialog *cd, 
  941.           char         *filename)
  942. {
  943.   int j;
  944.   FILE *l_fp;
  945.  
  946.   if(gb_debug) printf("Saving curve to file:%s\n", filename);
  947.  
  948.   l_fp = fopen(filename, "w+");
  949.   if(l_fp == NULL)
  950.   {
  951.     return -1;
  952.   }
  953.  
  954.   fprintf(l_fp, "%s\n", KEY_POINTFILE);
  955.   fprintf(l_fp, "VERSION 1.0\n\n");
  956.  
  957.   fprintf(l_fp, "# points for upper and lower smooth curve (0.0 <= pt <= 1.0)\n");
  958.   fprintf(l_fp, "# there are upto 17 points where unused points are set to -1\n");
  959.   fprintf(l_fp, "#       UPPERX     UPPERY      LOWERX    LOWERY\n");
  960.   fprintf(l_fp, "\n");
  961.  
  962.   for(j=0; j < 17; j++)
  963.   {
  964.       fprintf(l_fp, "%s %+.6f  %+.6f   %+.6f  %+.6f\n", KEY_POINTS,
  965.                   (float)cd->points[OUTLINE_UPPER][j][0], 
  966.                   (float)cd->points[OUTLINE_UPPER][j][1],
  967.                   (float)cd->points[OUTLINE_LOWER][j][0], 
  968.                   (float)cd->points[OUTLINE_LOWER][j][1] );
  969.   }
  970.  
  971.   fprintf(l_fp, "\n");
  972.   fprintf(l_fp, "# y values for upper/lower freehand curve (0 <= y <= 255) \n");
  973.   fprintf(l_fp, "# there must be exactly 256 y values \n");
  974.   fprintf(l_fp, "#     UPPER_Y  LOWER_Y\n");
  975.   fprintf(l_fp, "\n");
  976.  
  977.   for(j=0; j < 256; j++)
  978.   {
  979.     fprintf(l_fp, "%s %3d  %3d\n", KEY_VAL_Y, 
  980.                (int)cd->curve[OUTLINE_UPPER][j],
  981.                (int)cd->curve[OUTLINE_LOWER][j]);
  982.   }
  983.  
  984.   fclose(l_fp);
  985.   return 0; /* OK */
  986. }    /* end p_save_pointfile */
  987.  
  988.  
  989. int
  990. p_load_pointfile (BenderDialog *cd, 
  991.           char         *filename)
  992. {
  993.   int   l_pi, l_ci, l_n, l_len;
  994.   FILE *l_fp;
  995.   char  l_buff[2000];
  996.   float l_fux, l_fuy, l_flx, l_fly;
  997.   int   l_iuy, l_ily ;
  998.   
  999.   if(gb_debug) printf("Loading curve from file:%s\n", filename);
  1000.  
  1001.   l_fp = fopen(filename, "r");
  1002.   if(l_fp == NULL)
  1003.   {
  1004.     return -1;
  1005.   }
  1006.  
  1007.   l_pi= 0;
  1008.   l_ci= 0;
  1009.  
  1010.   fgets (l_buff, 2000-1, l_fp);
  1011.   if(strncmp(l_buff, KEY_POINTFILE, strlen(KEY_POINTFILE)) == 0)
  1012.   {
  1013.      while (NULL != fgets (l_buff, 2000-1, l_fp))
  1014.      {
  1015.         if(gb_debug) printf("FGETS: %s\n", l_buff);
  1016.         l_len = strlen(KEY_POINTS);
  1017.         if(strncmp(l_buff, KEY_POINTS, l_len) == 0)
  1018.         {
  1019.            l_n = sscanf(&l_buff[l_len], "%f %f %f %f", &l_fux, &l_fuy, &l_flx, &l_fly);
  1020.            if((l_n == 4) && (l_pi < 17))
  1021.            {
  1022.              cd->points[OUTLINE_UPPER][l_pi][0] = l_fux;
  1023.              cd->points[OUTLINE_UPPER][l_pi][1] = l_fuy;
  1024.              cd->points[OUTLINE_LOWER][l_pi][0] = l_flx;
  1025.              cd->points[OUTLINE_LOWER][l_pi][1] = l_fly;
  1026.              if(gb_debug) printf("OK points[%d]\n", l_pi);     
  1027.              l_pi++;
  1028.            }
  1029.        else
  1030.        {
  1031.           printf("warnig: BAD points[%d] in file %s are ignored\n", l_pi, filename);
  1032.        }
  1033.         }
  1034.         l_len = strlen(KEY_VAL_Y);
  1035.         if(strncmp(l_buff, KEY_VAL_Y, l_len) == 0)
  1036.         {
  1037.            l_n = sscanf(&l_buff[l_len], "%d %d", &l_iuy, &l_ily);
  1038.            if((l_n == 2) && (l_ci < 256))
  1039.            {
  1040.              cd->curve[OUTLINE_UPPER][l_ci] = l_iuy;
  1041.              cd->curve[OUTLINE_LOWER][l_ci] = l_ily;
  1042.              l_ci++;
  1043.              if(gb_debug) printf("OK y_val[%d]\n", l_pi);     
  1044.            }
  1045.        else
  1046.        {
  1047.           printf("warnig: BAD y_vals[%d] in file %s are ignored\n", l_ci, filename);
  1048.        }
  1049.         }
  1050.  
  1051.      }
  1052.   }
  1053.   fclose(l_fp);
  1054.   return 0; /* OK */
  1055. }    /* end p_load_pointfile */
  1056.  
  1057.  
  1058.  
  1059. void
  1060. p_cd_to_bval (BenderDialog *cd, 
  1061.           BenderValues *bval)
  1062. {
  1063.   int i,j;
  1064.  
  1065.   for(i=0; i<2; i++)
  1066.   {
  1067.     for(j=0; j<256; j++)
  1068.     {
  1069.       bval->curve[i][j] = cd->curve[i][j];
  1070.     }
  1071.  
  1072.     for(j=0; j<17; j++)
  1073.     {
  1074.       bval->points[i][j][0] = cd->points[i][j][0];  /* x */
  1075.       bval->points[i][j][1] = cd->points[i][j][1];  /* y */
  1076.     }
  1077.   
  1078.   }
  1079.   
  1080.   bval->curve_type = cd->curve_type;
  1081.   bval->smoothing = cd->smoothing;
  1082.   bval->antialias = cd->antialias;
  1083.   bval->work_on_copy = cd->work_on_copy;
  1084.   bval->rotation = cd->rotation;
  1085.  
  1086.   bval->total_steps = 0;
  1087.   bval->current_step =0.0;
  1088. }
  1089.  
  1090. void
  1091. p_cd_from_bval(BenderDialog *cd, BenderValues *bval)
  1092. {
  1093.   int i,j;
  1094.  
  1095.   for(i=0; i<2; i++)
  1096.   {
  1097.     for(j=0; j<256; j++)
  1098.     {
  1099.       cd->curve[i][j] = bval->curve[i][j];
  1100.     }
  1101.  
  1102.     for(j=0; j<17; j++)
  1103.     {
  1104.       cd->points[i][j][0] = bval->points[i][j][0];  /* x */
  1105.       cd->points[i][j][1] = bval->points[i][j][1];  /* y */
  1106.     }
  1107.   
  1108.   }
  1109.   
  1110.   cd->curve_type = bval->curve_type;
  1111.   cd->smoothing = bval->smoothing;
  1112.   cd->antialias = bval->antialias;
  1113.   cd->work_on_copy = bval->work_on_copy;
  1114.   cd->rotation = bval->rotation;
  1115.  
  1116. }
  1117.  
  1118. void
  1119. p_store_values (BenderDialog *cd)
  1120. {
  1121.   BenderValues l_bval;
  1122.   
  1123.   p_cd_to_bval(cd, &l_bval);
  1124.   gimp_set_data(PLUG_IN_NAME, &l_bval, sizeof(l_bval));
  1125. }
  1126.  
  1127. void
  1128. p_retrieve_values (BenderDialog *cd)
  1129. {
  1130.   BenderValues l_bval;
  1131.  
  1132.   l_bval.total_steps = 0;
  1133.   l_bval.current_step = -444.4;  /* init with an invalid  dummy value */
  1134.   
  1135.   gimp_get_data (PLUG_IN_NAME, &l_bval);
  1136.  
  1137.   if(l_bval.total_steps == 0)
  1138.   {
  1139.     cd->bval_from = NULL;
  1140.     cd->bval_to = NULL;
  1141.     if(l_bval.current_step != -444.4)
  1142.     {
  1143.        /* last_value data was retrieved (and dummy value was overwritten) */
  1144.        p_cd_from_bval(cd, &l_bval);
  1145.     }
  1146.   }
  1147.   else
  1148.   {
  1149.     cd->bval_from = g_malloc(sizeof(BenderValues));
  1150.     cd->bval_to   = g_malloc(sizeof(BenderValues));
  1151.     cd->bval_curr  = g_malloc(sizeof(BenderValues));
  1152.     memcpy(cd->bval_curr, &l_bval, sizeof(l_bval));
  1153.    
  1154.     /* it seems that we are called from GAP with "Varying Values" */
  1155.     gimp_get_data(PLUG_IN_DATA_ITER_FROM, cd->bval_from);
  1156.     gimp_get_data(PLUG_IN_DATA_ITER_TO,   cd->bval_to);
  1157.     memcpy(cd->bval_curr, &l_bval, sizeof(l_bval));
  1158.     p_cd_from_bval(cd, cd->bval_curr);
  1159.     cd->work_on_copy = FALSE;
  1160.   }
  1161.   
  1162. }
  1163.  
  1164.  
  1165. static void 
  1166. p_delta_gdouble (double  *val, 
  1167.          double   val_from, 
  1168.          double   val_to, 
  1169.          gint32   total_steps, 
  1170.          gdouble  current_step)
  1171. {
  1172.     double     delta;
  1173.  
  1174.     if(total_steps < 1) return;
  1175.  
  1176.     delta = ((double)(val_to - val_from) / (double)total_steps) * ((double)total_steps - current_step);
  1177.     *val  = val_from + delta;
  1178. }
  1179.  
  1180. static void 
  1181. p_delta_gint32 (gint32  *val, 
  1182.         gint32   val_from, 
  1183.         gint32   val_to, 
  1184.         gint32   total_steps, 
  1185.         gdouble  current_step)
  1186. {
  1187.     double     delta;
  1188.  
  1189.     if(total_steps < 1) return;
  1190.  
  1191.     delta = ((double)(val_to - val_from) / (double)total_steps) * ((double)total_steps - current_step);
  1192.     *val  = val_from + delta;
  1193. }
  1194.  
  1195.  
  1196. void
  1197. p_copy_points (BenderDialog *cd, 
  1198.            int           outline, 
  1199.            int           xy, 
  1200.            int           argc, 
  1201.            gdouble      *floatarray)
  1202. {
  1203.    int j;
  1204.    
  1205.    for(j=0; j < 17; j++)
  1206.    {
  1207.      cd->points[outline][j][xy] = -1;
  1208.    }
  1209.    for(j=0; j < argc; j++)
  1210.    {
  1211.      cd->points[outline][j][xy] = floatarray[j];
  1212.    }
  1213. }
  1214.  
  1215. void
  1216. p_copy_yval (BenderDialog *cd, 
  1217.          int           outline, 
  1218.          int           argc, 
  1219.          gint8        *int8array)
  1220. {
  1221.    int j;
  1222.    guchar fill;
  1223.    
  1224.    fill = MIDDLE;
  1225.    for(j=0; j < 256; j++)
  1226.    {
  1227.      if(j < argc) 
  1228.      {
  1229.         fill = cd->curve[outline][j] = int8array[j];
  1230.      }
  1231.      else
  1232.      {
  1233.         cd->curve[outline][j] = fill;
  1234.      }
  1235.    }
  1236. }
  1237.  
  1238. /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
  1239. /*  curves machinery  */
  1240. /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
  1241.  
  1242. BenderDialog *
  1243. do_dialog (GimpDrawable *drawable)
  1244. {
  1245.   BenderDialog *cd;
  1246.   gint  i;
  1247.  
  1248.   /* Init GTK  */
  1249.   gimp_ui_init ("curve_bend", TRUE);
  1250.  
  1251.   /*  The curve_bend dialog  */
  1252.   cd = bender_new_dialog (drawable);
  1253.  
  1254.   /* create temporary image (with a small copy of drawable) for the preview */
  1255.   cd->preview_image_id = p_create_pv_image(drawable, &cd->preview_layer_id1);
  1256.   cd->preview_layer_id2 = -1;
  1257.   
  1258.   /* show the outline menu   */
  1259.   for (i = 0; i < 2; i++)
  1260.   {
  1261.        gtk_widget_set_sensitive( outline_items[i].widget, TRUE);
  1262.   }
  1263.   
  1264.   /* set the current selection */
  1265.   gtk_option_menu_set_history ( GTK_OPTION_MENU (cd->outline_menu), 0);
  1266.  
  1267.   if (!GTK_WIDGET_VISIBLE (cd->shell))
  1268.     gtk_widget_show (cd->shell);
  1269.  
  1270.  
  1271.   bender_update (cd, UP_GRAPH | UP_DRAW);
  1272.  
  1273.   gtk_main ();
  1274.   gdk_flush ();
  1275.  
  1276.   gimp_image_delete(cd->preview_image_id);
  1277.   cd->preview_image_id = -1;
  1278.   cd->preview_layer_id1 = -1;
  1279.   cd->preview_layer_id2 = -1;
  1280.   
  1281.   if(gb_debug) printf("do_dialog END\n");  
  1282.   return cd;
  1283. }
  1284.  
  1285.  
  1286. /**************************/
  1287. /*  Select Curves dialog  */
  1288. /**************************/
  1289.  
  1290. static BenderDialog *
  1291. bender_new_dialog (GimpDrawable *drawable)
  1292. {
  1293.   BenderDialog *cd;
  1294.   GtkWidget *vbox;
  1295.   GtkWidget *hbox;
  1296.   GtkWidget *label;
  1297.   GtkWidget *frame;
  1298.   GtkWidget *toggle;
  1299.   GtkWidget *option_menu;
  1300.   GtkWidget *outline_hbox;
  1301.   GtkWidget *menu;
  1302.   GtkWidget *table;
  1303.   GtkWidget *button;
  1304.   GtkWidget *spinbutton;
  1305.   GtkObject *data;
  1306.   int i, j;
  1307.  
  1308.   cd = g_malloc (sizeof (BenderDialog));
  1309.  
  1310.   cd->preview = FALSE;
  1311.   cd->curve_type = SMOOTH;
  1312.   cd->pixmap = NULL;
  1313.   cd->filesel = NULL;
  1314.   cd->outline = OUTLINE_UPPER;
  1315.   cd->show_progress = FALSE;
  1316.   cd->smoothing = TRUE;
  1317.   cd->antialias = TRUE;
  1318.   cd->work_on_copy = FALSE;
  1319.   cd->rotation = 0.0;       /* vertical bend */
  1320.  
  1321.   cd->drawable = drawable;
  1322.   cd->color = gimp_drawable_is_rgb (cd->drawable->id);
  1323.  
  1324.   cd->run = FALSE;
  1325.   cd->bval_from = NULL;
  1326.   cd->bval_to = NULL;
  1327.   cd->bval_curr = NULL;
  1328.  
  1329.   for (i = 0; i < 2; i++)
  1330.     for (j = 0; j < 256; j++)
  1331.       cd->curve[i][j] = MIDDLE;
  1332.  
  1333.   cd->grab_point = -1;
  1334.   for (i = 0; i < 2; i++)
  1335.   {
  1336.       for (j = 0; j < 17; j++)
  1337.       {
  1338.       cd->points[i][j][0] = -1;
  1339.       cd->points[i][j][1] = -1;
  1340.       }
  1341.       cd->points[i][0][0] = 0.0;        /* x */
  1342.       cd->points[i][0][1] = 0.5;        /* y */
  1343.       cd->points[i][16][0] = 1.0;       /* x */
  1344.       cd->points[i][16][1] = 0.5;       /* y */
  1345.   }
  1346.  
  1347.  
  1348.   p_retrieve_values(cd);       /* Possibly retrieve data from a previous run */
  1349.  
  1350.   for (i = 0; i < 2; i++)
  1351.     outline_items [i].user_data = (gpointer) cd;
  1352.   for (i = 0; i < 2; i++)
  1353.     curve_type_items [i].user_data = (gpointer) cd;
  1354.  
  1355.   /*  The shell and main vbox  */
  1356.   cd->shell = gimp_dialog_new (_("Curve Bend"), "curve_bend",
  1357.                    gimp_standard_help_func, "filters/curve_bend.html",
  1358.                    GTK_WIN_POS_MOUSE,
  1359.                    FALSE, TRUE, FALSE,
  1360.  
  1361.                    _("Reset"), bender_reset_callback,
  1362.                    cd, NULL, NULL, FALSE, FALSE,
  1363.                    _("Copy"), bender_copy_callback,
  1364.                    cd, NULL, NULL, FALSE, FALSE,
  1365.                    _("CopyInv"), bender_copy_inv_callback,
  1366.                    cd, NULL, NULL, FALSE, FALSE,
  1367.                    _("Swap"), bender_swap_callback,
  1368.                    cd, NULL, NULL, FALSE, FALSE,
  1369.                    _("OK"), bender_ok_callback,
  1370.                    cd, NULL, NULL, TRUE, FALSE,
  1371.                    _("Cancel"), bender_cancel_callback,
  1372.                    cd, NULL, NULL, FALSE, TRUE,
  1373.  
  1374.                    NULL);
  1375.  
  1376.   vbox = gtk_vbox_new (FALSE, 2);
  1377.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  1378.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cd->shell)->vbox), vbox,
  1379.               TRUE, TRUE, 0);
  1380.  
  1381.   /*  The option menu for selecting outlines  */
  1382.   outline_hbox = gtk_hbox_new (FALSE, 2+4);
  1383.   gtk_box_pack_start (GTK_BOX (vbox), outline_hbox, FALSE, FALSE, 0);
  1384.  
  1385.   /*  The Load button  */
  1386.   button = gtk_button_new_with_label (_("LoadCurve"));
  1387.   gtk_box_pack_start (GTK_BOX (outline_hbox), button, TRUE, FALSE, 0);
  1388.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1389.               GTK_SIGNAL_FUNC (bender_load_callback),
  1390.               cd);
  1391.   gtk_widget_show (button);
  1392.  
  1393.   /*  The Save button  */
  1394.   button = gtk_button_new_with_label (_("SaveCurve"));
  1395.   gtk_box_pack_start (GTK_BOX (outline_hbox), button, TRUE, FALSE, 0);
  1396.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1397.               GTK_SIGNAL_FUNC (bender_save_callback),
  1398.               cd);
  1399.   gtk_widget_show (button);
  1400.  
  1401.   /*  Rotate label & spinbutton  */
  1402.   label = gtk_label_new (_("Rotate: "));
  1403.   gtk_box_pack_start (GTK_BOX (outline_hbox), label, FALSE, FALSE, 0);
  1404.  
  1405.   data = gtk_adjustment_new (0, 0.0, 360.0, 1, 45, 90);
  1406.   cd->rotate_data = GTK_ADJUSTMENT (data);
  1407.  
  1408.   spinbutton = gtk_spin_button_new (cd->rotate_data, 0.5, 1);
  1409.   gtk_widget_set_usize (spinbutton, ENTRY_WIDTH, -1);
  1410.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  1411.   gtk_box_pack_start (GTK_BOX (outline_hbox), spinbutton, FALSE, FALSE, 2);
  1412.  
  1413.   gtk_signal_connect (GTK_OBJECT (cd->rotate_data), "value_changed",
  1414.                       GTK_SIGNAL_FUNC (bender_rotate_adj_callback),
  1415.                       cd);
  1416.  
  1417.   gtk_widget_show (spinbutton);
  1418.  
  1419.  
  1420.   label = gtk_label_new (_("Curve for Border: "));
  1421.   gtk_box_pack_start (GTK_BOX (outline_hbox), label, FALSE, FALSE, 0);
  1422.  
  1423.   menu = p_buildmenu (outline_items);
  1424.   cd->outline_menu = gtk_option_menu_new ();
  1425.   gtk_box_pack_start (GTK_BOX (outline_hbox), cd->outline_menu, FALSE, FALSE, 2);
  1426.  
  1427.   gtk_widget_show (label);
  1428.   gtk_widget_show (cd->outline_menu);
  1429.   gtk_widget_show (outline_hbox);
  1430.   gtk_option_menu_set_menu (GTK_OPTION_MENU (cd->outline_menu), menu);
  1431.  
  1432.   /*  The option menu for selecting the drawing method  */
  1433.   label = gtk_label_new (_("Curve Type: "));
  1434.   gtk_box_pack_start (GTK_BOX (outline_hbox), label, FALSE, FALSE, 0);
  1435.  
  1436.   menu = p_buildmenu (curve_type_items);
  1437.   option_menu = gtk_option_menu_new ();
  1438.   gtk_box_pack_start (GTK_BOX (outline_hbox), option_menu, FALSE, FALSE, 2);
  1439.  
  1440.   gtk_widget_show (label);
  1441.   gtk_widget_show (option_menu);
  1442.   gtk_widget_show (outline_hbox);
  1443.   gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
  1444.  
  1445.  
  1446.   /*  The table for the pv_widget preview  */
  1447.   table = gtk_table_new (2, 2, FALSE);
  1448.   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  1449.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  1450.  
  1451.   /*  The range drawing area  */
  1452.   frame = gtk_frame_new (NULL);
  1453.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1454.   gtk_table_attach (GTK_TABLE (table), frame, 0, 1, 0, 1,
  1455.             GTK_EXPAND, GTK_EXPAND, 0, 0);
  1456.  
  1457.   cd->pv_widget = gtk_preview_new (GTK_PREVIEW_COLOR);
  1458.   gtk_preview_size (GTK_PREVIEW (cd->pv_widget), PREVIEW_SIZE_X, PREVIEW_SIZE_Y);
  1459.   gtk_widget_set_events (cd->pv_widget, RANGE_MASK);
  1460.   gtk_signal_connect (GTK_OBJECT (cd->pv_widget), "event",
  1461.               (GtkSignalFunc) bender_pv_widget_events,
  1462.               cd);
  1463.   gtk_container_add (GTK_CONTAINER (frame), cd->pv_widget);
  1464.   gtk_widget_show (cd->pv_widget);
  1465.   gtk_widget_show (frame);
  1466.  
  1467.   /*  The curves graph  */
  1468.   frame = gtk_frame_new (NULL);
  1469.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1470.   gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 0, 1,
  1471.             GTK_EXPAND | GTK_SHRINK | GTK_FILL,
  1472.             GTK_FILL, 0, 0);
  1473.  
  1474.   cd->graph = gtk_drawing_area_new ();
  1475.   gtk_drawing_area_size (GTK_DRAWING_AREA (cd->graph),
  1476.              GRAPH_WIDTH + RADIUS * 2,
  1477.              GRAPH_HEIGHT + RADIUS * 2);
  1478.   gtk_widget_set_events (cd->graph, GRAPH_MASK);
  1479.   gtk_signal_connect (GTK_OBJECT (cd->graph), "event",
  1480.               (GtkSignalFunc) bender_graph_events,
  1481.               cd);
  1482.   gtk_container_add (GTK_CONTAINER (frame), cd->graph);
  1483.   gtk_widget_show (cd->graph);
  1484.   gtk_widget_show (frame);
  1485.  
  1486.   gtk_widget_show (table);
  1487.  
  1488.   /*  Horizontal box for preview  */
  1489.   hbox = gtk_hbox_new (FALSE, 2+3);
  1490.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  1491.  
  1492.  
  1493.   /*  The preview button  */
  1494.   button = gtk_button_new_with_label (_("PreviewOnce"));
  1495.   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 0);
  1496.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1497.                 (GtkSignalFunc) bender_preview_update_once,
  1498.                 cd);
  1499.   gtk_widget_show (button);
  1500.  
  1501.  
  1502.   /*  The preview toggle  */
  1503.   toggle = gtk_check_button_new_with_label (_("Preview"));
  1504.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->preview);
  1505.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
  1506.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1507.               (GtkSignalFunc) bender_preview_update,
  1508.               cd);
  1509.  
  1510.   gtk_widget_show (toggle);
  1511.  
  1512.   /*  The smoothing toggle  */
  1513.   toggle = gtk_check_button_new_with_label (_("Smoothing"));
  1514.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->smoothing);
  1515.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
  1516.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1517.               (GtkSignalFunc) bender_smoothing_callback,
  1518.               cd);
  1519.  
  1520.   gtk_widget_show (toggle);
  1521.  
  1522.   /*  The antialiasing toggle  */
  1523.   toggle = gtk_check_button_new_with_label (_("Antialiasing"));
  1524.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->antialias);
  1525.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
  1526.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1527.               (GtkSignalFunc) bender_antialias_callback,
  1528.               cd);
  1529.  
  1530.   gtk_widget_show (toggle);
  1531.  
  1532.   /*  The wor_on_copy toggle  */
  1533.   toggle = gtk_check_button_new_with_label (_("Work on Copy"));
  1534.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->work_on_copy);
  1535.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, FALSE, 0);
  1536.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1537.               (GtkSignalFunc) bender_work_on_copy_callback,
  1538.               cd);
  1539.  
  1540.   gtk_widget_show (toggle);
  1541.  
  1542.   gtk_widget_show (hbox);
  1543.  
  1544.   gtk_widget_show (vbox);
  1545.  
  1546.   return cd;
  1547. }
  1548.  
  1549. static void
  1550. bender_update (BenderDialog *cd,
  1551.            int           update)
  1552. {
  1553.   int i;
  1554.   int other;
  1555.  
  1556.   if (update & UP_PREVIEW)
  1557.     {
  1558.       if (cd->preview_layer_id2 >= 0)
  1559.          gimp_image_remove_layer(cd->preview_image_id, cd->preview_layer_id2);
  1560.  
  1561.       cd->preview_layer_id2 = p_main_bend(cd, gimp_drawable_get (cd->preview_layer_id1), TRUE /* work_on_copy*/ ); 
  1562.       p_render_preview(cd, cd->preview_layer_id2);
  1563.       
  1564.       if (update & UP_DRAW)
  1565.     gtk_widget_draw (cd->pv_widget, NULL);
  1566.     }
  1567.   if (update & UP_PREVIEW_EXPOSE)
  1568.     {
  1569.       /* on expose just redraw cd->preview_layer_id2 
  1570.        * that holds the bent version of the preview (if there is one) 
  1571.        */
  1572.       if (cd->preview_layer_id2 < 0)
  1573.          cd->preview_layer_id2 = p_main_bend(cd, gimp_drawable_get (cd->preview_layer_id1), TRUE /* work_on_copy*/ ); 
  1574.       p_render_preview(cd, cd->preview_layer_id2);
  1575.       
  1576.       if (update & UP_DRAW)
  1577.     gtk_widget_draw (cd->pv_widget, NULL);
  1578.     }
  1579.   if ((update & UP_GRAPH) && (update & UP_DRAW) && cd->pixmap != NULL)
  1580.     {
  1581.       GdkPoint points[256];
  1582.  
  1583.       /*  Clear the pixmap  */
  1584.       gdk_draw_rectangle (cd->pixmap, cd->graph->style->bg_gc[GTK_STATE_NORMAL],
  1585.               TRUE, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
  1586.  
  1587.       /*  Draw the grid lines  */
  1588.       for (i = 0; i < 5; i++)
  1589.     {
  1590.       gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL],
  1591.              RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS,
  1592.              GRAPH_WIDTH + RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS);
  1593.       gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL],
  1594.              i * (GRAPH_WIDTH / 4) + RADIUS, RADIUS,
  1595.              i * (GRAPH_WIDTH / 4) + RADIUS, GRAPH_HEIGHT + RADIUS);
  1596.     }
  1597.  
  1598.       /*  Draw the other curve  */
  1599.       if(cd->outline == 0) { other = 1; }
  1600.       else                 { other = 0; }
  1601.       
  1602.       for (i = 0; i < 256; i++)
  1603.     {
  1604.       points[i].x = i + RADIUS;
  1605.       points[i].y = 255 - cd->curve[other][i] + RADIUS;
  1606.     }
  1607.       gdk_draw_points (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL], points, 256);
  1608.  
  1609.  
  1610.       /*  Draw the active curve  */
  1611.       for (i = 0; i < 256; i++)
  1612.     {
  1613.       points[i].x = i + RADIUS;
  1614.       points[i].y = 255 - cd->curve[cd->outline][i] + RADIUS;
  1615.     }
  1616.       gdk_draw_points (cd->pixmap, cd->graph->style->black_gc, points, 256);
  1617.  
  1618.       /*  Draw the points  */
  1619.       if (cd->curve_type == SMOOTH)
  1620.     for (i = 0; i < 17; i++)
  1621.       {
  1622.         if (cd->points[cd->outline][i][0] != -1)
  1623.           gdk_draw_arc (cd->pixmap, cd->graph->style->black_gc, TRUE,
  1624.                 (cd->points[cd->outline][i][0] * 255.0),
  1625.                 255 - (cd->points[cd->outline][i][1] * 255.0),
  1626.                 RADIUS * 2, RADIUS * 2, 0, 23040);
  1627.       }
  1628.  
  1629.  
  1630.       gdk_draw_pixmap (cd->graph->window, cd->graph->style->black_gc, cd->pixmap,
  1631.                0, 0, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
  1632.     }
  1633. }
  1634.  
  1635.  
  1636. static void
  1637. bender_plot_curve (BenderDialog *cd,
  1638.            int           p1,
  1639.            int           p2,
  1640.            int           p3,
  1641.            int           p4,
  1642.            gint32        xmax,
  1643.            gint32        ymax,
  1644.            gint          fix255)
  1645. {
  1646.   CRMatrix geometry;
  1647.   CRMatrix tmp1, tmp2;
  1648.   CRMatrix deltas;
  1649.   double x, dx, dx2, dx3;
  1650.   double y, dy, dy2, dy3;
  1651.   double d, d2, d3;
  1652.   int lastx, lasty;
  1653.   gint32 newx, newy;
  1654.   gint32 ntimes; 
  1655.   gint32 i;
  1656.  
  1657.   /* construct the geometry matrix from the segment */
  1658.   for (i = 0; i < 4; i++)
  1659.   {
  1660.       geometry[i][2] = 0;
  1661.       geometry[i][3] = 0;
  1662.   }
  1663.  
  1664.   geometry[0][0] = (cd->points[cd->outline][p1][0] * xmax);
  1665.   geometry[1][0] = (cd->points[cd->outline][p2][0] * xmax);
  1666.   geometry[2][0] = (cd->points[cd->outline][p3][0] * xmax);
  1667.   geometry[3][0] = (cd->points[cd->outline][p4][0] * xmax);
  1668.  
  1669.   geometry[0][1] = (cd->points[cd->outline][p1][1] * ymax);
  1670.   geometry[1][1] = (cd->points[cd->outline][p2][1] * ymax);
  1671.   geometry[2][1] = (cd->points[cd->outline][p3][1] * ymax);
  1672.   geometry[3][1] = (cd->points[cd->outline][p4][1] * ymax);
  1673.  
  1674.   /* subdivide the curve ntimes (1000) times */
  1675.   ntimes = 4 * xmax;
  1676.   /* ntimes can be adjusted to give a finer or coarser curve */
  1677.   d = 1.0 / ntimes;
  1678.   d2 = d * d;
  1679.   d3 = d * d * d;
  1680.  
  1681.   /* construct a temporary matrix for determining the forward differencing deltas */
  1682.   tmp2[0][0] = 0;     tmp2[0][1] = 0;     tmp2[0][2] = 0;    tmp2[0][3] = 1;
  1683.   tmp2[1][0] = d3;    tmp2[1][1] = d2;    tmp2[1][2] = d;    tmp2[1][3] = 0;
  1684.   tmp2[2][0] = 6*d3;  tmp2[2][1] = 2*d2;  tmp2[2][2] = 0;    tmp2[2][3] = 0;
  1685.   tmp2[3][0] = 6*d3;  tmp2[3][1] = 0;     tmp2[3][2] = 0;    tmp2[3][3] = 0;
  1686.  
  1687.   /* compose the basis and geometry matrices */
  1688.   bender_CR_compose (CR_basis, geometry, tmp1);
  1689.  
  1690.   /* compose the above results to get the deltas matrix */
  1691.   bender_CR_compose (tmp2, tmp1, deltas);
  1692.  
  1693.   /* extract the x deltas */
  1694.   x = deltas[0][0];
  1695.   dx = deltas[1][0];
  1696.   dx2 = deltas[2][0];
  1697.   dx3 = deltas[3][0];
  1698.  
  1699.   /* extract the y deltas */
  1700.   y = deltas[0][1];
  1701.   dy = deltas[1][1];
  1702.   dy2 = deltas[2][1];
  1703.   dy3 = deltas[3][1];
  1704.  
  1705.   lastx = CLAMP (x, 0, xmax);
  1706.   lasty = CLAMP (y, 0, ymax);
  1707.  
  1708.  
  1709.   if(fix255)
  1710.   {
  1711.     cd->curve[cd->outline][lastx] = lasty;
  1712.   }
  1713.   else  
  1714.   {
  1715.     cd->curve_ptr[cd->outline][lastx] = lasty;
  1716.     if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax);
  1717.   }
  1718.  
  1719.   /* loop over the curve */
  1720.   for (i = 0; i < ntimes; i++)
  1721.     {
  1722.       /* increment the x values */
  1723.       x += dx;
  1724.       dx += dx2;
  1725.       dx2 += dx3;
  1726.  
  1727.       /* increment the y values */
  1728.       y += dy;
  1729.       dy += dy2;
  1730.       dy2 += dy3;
  1731.  
  1732.       newx = CLAMP ((ROUND (x)), 0, xmax);
  1733.       newy = CLAMP ((ROUND (y)), 0, ymax);
  1734.  
  1735.       /* if this point is different than the last one...then draw it */
  1736.       if ((lastx != newx) || (lasty != newy))
  1737.       {
  1738.         if(fix255)
  1739.         {
  1740.           /* use fixed array size (for the curve graph) */
  1741.           cd->curve[cd->outline][newx] = newy;
  1742.     }
  1743.     else
  1744.     {
  1745.       /* use dynamic allocated curve_ptr (for the real curve) */
  1746.       cd->curve_ptr[cd->outline][newx] = newy;
  1747.       
  1748.       if(gb_debug) printf("outline: %d  cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy);      
  1749.     }
  1750.       }
  1751.  
  1752.       lastx = newx;
  1753.       lasty = newy;
  1754.     }
  1755. }
  1756.  
  1757. static void
  1758. bender_calculate_curve (BenderDialog *cd, 
  1759.             gint32        xmax, 
  1760.             gint32        ymax, 
  1761.             gint          fix255)
  1762. {
  1763.   int i;
  1764.   int points[17];
  1765.   int num_pts;
  1766.   int p1, p2, p3, p4;
  1767.   int xmid;
  1768.   int yfirst, ylast;
  1769.  
  1770.   switch (cd->curve_type)
  1771.   {
  1772.     case GFREE:
  1773.       break;
  1774.     case SMOOTH:
  1775.       /*  cycle through the curves  */
  1776.       num_pts = 0;
  1777.       for (i = 0; i < 17; i++)
  1778.     if (cd->points[cd->outline][i][0] != -1)
  1779.       points[num_pts++] = i;
  1780.  
  1781.       xmid = xmax / 2;
  1782.       /*  Initialize boundary curve points */
  1783.       if (num_pts != 0)
  1784.       {
  1785.         
  1786.         if(fix255)
  1787.         {
  1788.           for (i = 0; i < (cd->points[cd->outline][points[0]][0] * 255); i++)
  1789.         cd->curve[cd->outline][i] = (cd->points[cd->outline][points[0]][1] * 255);
  1790.           for (i = (cd->points[cd->outline][points[num_pts - 1]][0] * 255); i < 256; i++)
  1791.         cd->curve[cd->outline][i] = (cd->points[cd->outline][points[num_pts - 1]][1] * 255);
  1792.         }
  1793.         else
  1794.         {
  1795.         yfirst  = cd->points[cd->outline][points[0]][1] * ymax;
  1796.         ylast   = cd->points[cd->outline][points[num_pts - 1]][1] * ymax;
  1797.         
  1798.         for (i = 0; i < xmid; i++)
  1799.         {
  1800.            cd->curve_ptr[cd->outline][i] = yfirst;
  1801.         }
  1802.         for (i = xmid; i <= xmax; i++)
  1803.         {
  1804.            cd->curve_ptr[cd->outline][i] = ylast;
  1805.         }
  1806.           
  1807.         }
  1808.       }
  1809.  
  1810.       for (i = 0; i < num_pts - 1; i++)
  1811.       {
  1812.       p1 = (i == 0) ? points[i] : points[(i - 1)];
  1813.       p2 = points[i];
  1814.       p3 = points[(i + 1)];
  1815.       p4 = (i == (num_pts - 2)) ? points[(num_pts - 1)] : points[(i + 2)];
  1816.  
  1817.       bender_plot_curve (cd, p1, p2, p3, p4, xmax, ymax, fix255);
  1818.       }
  1819.       break;
  1820.   }
  1821.  
  1822. }
  1823.  
  1824. static void
  1825. bender_rotate_adj_callback (GtkAdjustment *adjustment,
  1826.                   gpointer   client_data)
  1827. {
  1828.   BenderDialog *cd;
  1829.  
  1830.   cd = (BenderDialog *) client_data;
  1831.  
  1832.   if (adjustment->value != cd->rotation)
  1833.   {
  1834.     cd->rotation = adjustment->value;
  1835.     if(cd->preview) bender_update (cd, UP_PREVIEW | UP_DRAW);
  1836.   }
  1837. }
  1838.  
  1839.  
  1840. static void
  1841. bender_upper_callback (GtkWidget *w,
  1842.                gpointer   client_data)
  1843. {
  1844.   BenderDialog *cd;
  1845.  
  1846.   cd = (BenderDialog *) client_data;
  1847.  
  1848.   if (cd->outline != OUTLINE_UPPER)
  1849.     {
  1850.       cd->outline = OUTLINE_UPPER;
  1851.       bender_update (cd, UP_GRAPH | UP_DRAW);
  1852.     }
  1853. }
  1854.  
  1855. static void
  1856. bender_lower_callback (GtkWidget *w,
  1857.                gpointer   client_data)
  1858. {
  1859.   BenderDialog *cd;
  1860.  
  1861.   cd = (BenderDialog *) client_data;
  1862.  
  1863.   if (cd->outline != OUTLINE_LOWER)
  1864.     {
  1865.       cd->outline = OUTLINE_LOWER;
  1866.       bender_update (cd, UP_GRAPH | UP_DRAW);
  1867.     }
  1868. }
  1869.  
  1870.  
  1871. static void
  1872. bender_smooth_callback (GtkWidget *w,
  1873.             gpointer   client_data)
  1874. {
  1875.   BenderDialog *cd;
  1876.   int i;
  1877.   gint32 index;
  1878.  
  1879.   cd = (BenderDialog *) client_data;
  1880.  
  1881.   if (cd->curve_type != SMOOTH)
  1882.     {
  1883.       cd->curve_type = SMOOTH;
  1884.  
  1885.       /*  pick representative points from the curve and make them control points  */
  1886.       for (i = 0; i <= 8; i++)
  1887.     {
  1888.       index = CLAMP ((i * 32), 0, 255);
  1889.       cd->points[cd->outline][i * 2][0] = (gdouble)index / 255.0;
  1890.       cd->points[cd->outline][i * 2][1] = (gdouble)cd->curve[cd->outline][index] / 255.0;
  1891.     }
  1892.  
  1893.       bender_calculate_curve (cd, 255, 255, TRUE);
  1894.       bender_update (cd, UP_GRAPH | UP_DRAW);
  1895.  
  1896.       if (cd->preview)
  1897.     bender_update (cd, UP_PREVIEW | UP_DRAW);
  1898.     }
  1899. }
  1900.  
  1901. static void
  1902. bender_free_callback (GtkWidget *w,
  1903.               gpointer   client_data)
  1904. {
  1905.   BenderDialog *cd;
  1906.  
  1907.   cd = (BenderDialog *) client_data;
  1908.  
  1909.   if (cd->curve_type != GFREE)
  1910.     {
  1911.       cd->curve_type = GFREE;
  1912.       bender_update (cd, UP_GRAPH | UP_DRAW);
  1913.     }
  1914. }
  1915.  
  1916. static void
  1917. bender_reset_callback (GtkWidget *widget,
  1918.                gpointer   client_data)
  1919. {
  1920.   BenderDialog *cd;
  1921.   int i;
  1922.  
  1923.   cd = (BenderDialog *) client_data;
  1924.  
  1925.   /*  Initialize the values  */
  1926.   for (i = 0; i < 256; i++)
  1927.     cd->curve[cd->outline][i] = MIDDLE;
  1928.  
  1929.   cd->grab_point = -1;
  1930.   for (i = 0; i < 17; i++)
  1931.     {
  1932.       cd->points[cd->outline][i][0] = -1;
  1933.       cd->points[cd->outline][i][1] = -1;
  1934.     }
  1935.   cd->points[cd->outline][0][0] = 0.0;       /* x */
  1936.   cd->points[cd->outline][0][1] = 0.5;       /* y */
  1937.   cd->points[cd->outline][16][0] = 1.0;      /* x */
  1938.   cd->points[cd->outline][16][1] = 0.5;      /* y */
  1939.  
  1940.   bender_update (cd, UP_GRAPH | UP_DRAW);
  1941.   if (cd->preview)
  1942.     bender_update (cd, UP_PREVIEW | UP_DRAW);
  1943. }
  1944.  
  1945. static void
  1946. bender_copy_callback (GtkWidget *widget,
  1947.               gpointer   client_data)
  1948. {
  1949.   BenderDialog *cd;
  1950.   int i;
  1951.   int other;
  1952.  
  1953.   cd = (BenderDialog *) client_data;
  1954.  
  1955.   if(cd->outline == 0)
  1956.      other = 1;
  1957.   else
  1958.      other = 0;
  1959.  
  1960.  
  1961.   for (i = 0; i < 17; i++)
  1962.     {
  1963.       cd->points[other][i][0] = cd->points[cd->outline][i][0];
  1964.       cd->points[other][i][1] = cd->points[cd->outline][i][1];
  1965.     }
  1966.  
  1967.   for (i= 0; i < 256; i++)
  1968.     {
  1969.       cd->curve[other][i] = cd->curve[cd->outline][i];
  1970.     }
  1971.  
  1972.   bender_update (cd, UP_GRAPH | UP_DRAW);
  1973.   if (cd->preview)
  1974.     bender_update (cd, UP_PREVIEW | UP_DRAW);
  1975. }
  1976.  
  1977. static void
  1978. bender_copy_inv_callback (GtkWidget *widget,
  1979.               gpointer   client_data)
  1980. {
  1981.   BenderDialog *cd;
  1982.   int i;
  1983.   int other;
  1984.  
  1985.   cd = (BenderDialog *) client_data;
  1986.  
  1987.   if(cd->outline == 0)
  1988.      other = 1;
  1989.   else
  1990.      other = 0;
  1991.  
  1992.  
  1993.   for (i = 0; i < 17; i++)
  1994.     {
  1995.       cd->points[other][i][0] = cd->points[cd->outline][i][0];        /* x */
  1996.       cd->points[other][i][1] = 1.0 - cd->points[cd->outline][i][1];  /* y */
  1997.     }
  1998.  
  1999.   for (i= 0; i < 256; i++)
  2000.     {
  2001.       cd->curve[other][i] = 255 - cd->curve[cd->outline][i];
  2002.     }
  2003.  
  2004.   bender_update (cd, UP_GRAPH | UP_DRAW);
  2005.   if (cd->preview)
  2006.     bender_update (cd, UP_PREVIEW | UP_DRAW);
  2007. }
  2008.  
  2009.  
  2010. static void
  2011. bender_swap_callback (GtkWidget *widget,
  2012.               gpointer   client_data)
  2013. {
  2014. #define SWAP_VALUE(a, b, h) { h=a; a=b; b=h; }
  2015.   BenderDialog *cd;
  2016.   int i;
  2017.   int other;
  2018.   gdouble hd;
  2019.   guchar  hu;
  2020.  
  2021.   cd = (BenderDialog *) client_data;
  2022.  
  2023.   if(cd->outline == 0)
  2024.      other = 1;
  2025.   else
  2026.      other = 0;
  2027.  
  2028.  
  2029.   for (i = 0; i < 17; i++)
  2030.     {
  2031.       SWAP_VALUE(cd->points[other][i][0], cd->points[cd->outline][i][0], hd);  /* x */    
  2032.       SWAP_VALUE(cd->points[other][i][1], cd->points[cd->outline][i][1], hd);  /* y */
  2033.     }
  2034.  
  2035.   for (i= 0; i < 256; i++)
  2036.     {
  2037.       SWAP_VALUE(cd->curve[other][i], cd->curve[cd->outline][i], hu);
  2038.     }
  2039.  
  2040.   bender_update (cd, UP_GRAPH | UP_DRAW);
  2041.   if (cd->preview)
  2042.     bender_update (cd, UP_PREVIEW | UP_DRAW);
  2043. }
  2044.  
  2045. static void
  2046. bender_ok_callback (GtkWidget *widget,
  2047.             gpointer   data)
  2048. {
  2049.   BenderDialog *cd;
  2050.  
  2051.   cd = (BenderDialog *) data;
  2052.  
  2053.   if (GTK_WIDGET_VISIBLE (cd->shell))
  2054.     gtk_widget_hide (cd->shell);
  2055.  
  2056.   cd->run = TRUE;
  2057.   gtk_widget_destroy (GTK_WIDGET (cd->shell));
  2058.   gtk_main_quit ();
  2059. }
  2060.  
  2061. static void
  2062. bender_cancel_callback (GtkWidget *widget,
  2063.             gpointer   data)
  2064. {
  2065.   BenderDialog *cd;
  2066.  
  2067.   cd = (BenderDialog *) data;
  2068.   gtk_main_quit ();
  2069. }
  2070.  
  2071. static void
  2072. bender_preview_update (GtkWidget *widget,
  2073.                gpointer   data)
  2074. {
  2075.   BenderDialog *cd;
  2076.  
  2077.   cd = (BenderDialog *) data;
  2078.   
  2079.   if (GTK_TOGGLE_BUTTON (widget)->active)
  2080.   {
  2081.       cd->preview = TRUE;
  2082.       bender_update (cd, UP_PREVIEW | UP_DRAW);
  2083.   }
  2084.   else
  2085.   {
  2086.     cd->preview = FALSE;
  2087.   }
  2088. }
  2089.  
  2090. static void
  2091. bender_preview_update_once (GtkWidget *widget,
  2092.                 gpointer   data)
  2093. {
  2094.   BenderDialog *cd;
  2095.  
  2096.   cd = (BenderDialog *) data;  
  2097.   bender_update (cd, UP_PREVIEW | UP_DRAW);
  2098. }
  2099.  
  2100. static void
  2101. p_filesel_close_cb (GtkWidget *widget,
  2102.             gpointer   data)
  2103. {
  2104.   BenderDialog *cd;
  2105.  
  2106.   cd = (BenderDialog *) data;  
  2107.  
  2108.   if(gb_debug) printf("p_filesel_close_cb\n");
  2109.  
  2110.   if(cd->filesel == NULL) return;
  2111.  
  2112.   gtk_widget_destroy(GTK_WIDGET(cd->filesel));
  2113.   cd->filesel = NULL;   /* now filesel is closed */
  2114. }
  2115.  
  2116. static void
  2117. p_points_save_to_file (GtkWidget *widget,
  2118.                gpointer     data)
  2119. {
  2120.   BenderDialog *cd;
  2121.   char        *filename;
  2122.  
  2123.   if(gb_debug) printf("p_points_save_to_file\n");
  2124.   cd = (BenderDialog *) data;  
  2125.   
  2126.   if(cd->filesel == NULL) return;
  2127.   
  2128.   filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (cd->filesel));
  2129.   p_save_pointfile(cd, filename);
  2130.   gtk_widget_destroy(GTK_WIDGET(cd->filesel));
  2131.   cd->filesel = NULL;
  2132. }
  2133.  
  2134. static void
  2135. p_points_load_from_file (GtkWidget *widget,
  2136.              gpointer   data)
  2137. {
  2138.   BenderDialog *cd;
  2139.   char        *filename;
  2140.  
  2141.   if(gb_debug) printf("p_points_load_from_file\n");
  2142.   cd = (BenderDialog *) data;  
  2143.   
  2144.   if(cd->filesel == NULL) return;
  2145.   
  2146.   filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (cd->filesel));
  2147.   p_load_pointfile(cd, filename);
  2148.   gtk_widget_destroy(GTK_WIDGET(cd->filesel));
  2149.   cd->filesel = NULL;
  2150.   bender_update (cd, UP_ALL);
  2151. }
  2152.  
  2153. static void
  2154. bender_load_callback (GtkWidget *w,
  2155.               gpointer   data)
  2156. {
  2157.   BenderDialog *cd;
  2158.   GtkWidget *filesel;
  2159.  
  2160.   cd = (BenderDialog *) data;
  2161.   if(cd->filesel != NULL)
  2162.      return;   /* filesel is already open */
  2163.   
  2164.   filesel = gtk_file_selection_new ( _("Load Curve Points from file"));
  2165.   cd->filesel = filesel;
  2166.   
  2167.   gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
  2168.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
  2169.               "clicked", (GtkSignalFunc) p_points_load_from_file,
  2170.               cd);
  2171.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
  2172.               "clicked", (GtkSignalFunc) p_filesel_close_cb,
  2173.               cd);
  2174.   gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
  2175.               (GtkSignalFunc) p_filesel_close_cb,
  2176.               cd);
  2177.   gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel),
  2178.                    "curve_bend.points");
  2179.   gtk_widget_show (filesel);
  2180.  
  2181. }
  2182.  
  2183. static void
  2184. bender_save_callback (GtkWidget *w,
  2185.               gpointer   data)
  2186. {
  2187.   BenderDialog *cd;
  2188.   GtkWidget *filesel;
  2189.  
  2190.   cd = (BenderDialog *) data;
  2191.   if(cd->filesel != NULL)
  2192.      return;   /* filesel is already open */
  2193.   
  2194.   filesel = gtk_file_selection_new ( _("Save Curve Points to file"));
  2195.   cd->filesel = filesel;
  2196.   
  2197.   gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
  2198.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
  2199.               "clicked", (GtkSignalFunc) p_points_save_to_file,
  2200.               cd);
  2201.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
  2202.               "clicked", (GtkSignalFunc) p_filesel_close_cb,
  2203.               cd);
  2204.   gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
  2205.               (GtkSignalFunc) p_filesel_close_cb,
  2206.               cd);
  2207.   gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel),
  2208.                    "curve_bend.points");
  2209.   gtk_widget_show (filesel);
  2210. }
  2211.  
  2212. static void
  2213. bender_smoothing_callback (GtkWidget *w,
  2214.                gpointer   data)
  2215. {
  2216.   BenderDialog *cd;
  2217.  
  2218.   cd = (BenderDialog *) data;
  2219.   
  2220.   if (GTK_TOGGLE_BUTTON (w)->active) { cd->smoothing = TRUE;  }
  2221.   else                               { cd->smoothing = FALSE; }
  2222.  
  2223.   if(cd->preview) bender_update (cd, UP_PREVIEW | UP_DRAW);
  2224. }
  2225.  
  2226. static void
  2227. bender_antialias_callback (GtkWidget *w,
  2228.                gpointer   data)
  2229. {
  2230.   BenderDialog *cd;
  2231.  
  2232.   cd = (BenderDialog *) data;
  2233.   
  2234.   if (GTK_TOGGLE_BUTTON (w)->active) { cd->antialias = TRUE; }
  2235.   else                               { cd->antialias = FALSE; }
  2236.  
  2237.   if(cd->preview) bender_update (cd, UP_PREVIEW | UP_DRAW);
  2238. }
  2239.  
  2240. static void
  2241. bender_work_on_copy_callback (GtkWidget *w,
  2242.                   gpointer   data)
  2243. {
  2244.   BenderDialog *cd;
  2245.  
  2246.   cd = (BenderDialog *) data;
  2247.   
  2248.   if (GTK_TOGGLE_BUTTON (w)->active) { cd->work_on_copy = TRUE;  }
  2249.   else                               { cd->work_on_copy = FALSE; }
  2250. }
  2251.  
  2252. static gint
  2253. bender_graph_events (GtkWidget    *widget,
  2254.              GdkEvent     *event,
  2255.              BenderDialog *cd)
  2256. {
  2257.   static GdkCursorType cursor_type = GDK_TOP_LEFT_ARROW;
  2258.   GdkCursorType new_type;
  2259.   GdkEventButton *bevent;
  2260.   GdkEventMotion *mevent;
  2261.   int i;
  2262.   int tx, ty;
  2263.   int x, y;
  2264.   int closest_point;
  2265.   int distance;
  2266.   int x1, x2, y1, y2;
  2267.  
  2268.   new_type      = GDK_X_CURSOR;
  2269.   closest_point = 0;
  2270.  
  2271.   /*  get the pointer position  */
  2272.   gdk_window_get_pointer (cd->graph->window, &tx, &ty, NULL);
  2273.   x = CLAMP ((tx - RADIUS), 0, 255);
  2274.   y = CLAMP ((ty - RADIUS), 0, 255);
  2275.  
  2276.   distance = G_MAXINT;
  2277.   for (i = 0; i < 17; i++)
  2278.     {
  2279.       if (cd->points[cd->outline][i][0] != -1)
  2280.     if (abs (x - (cd->points[cd->outline][i][0] * 255.0)) < distance)
  2281.       {
  2282.         distance = abs (x - (cd->points[cd->outline][i][0] * 255.0));
  2283.         closest_point = i;
  2284.       }
  2285.     }
  2286.   if (distance > MIN_DISTANCE)
  2287.     closest_point = (x + 8) / 16;
  2288.  
  2289.   switch (event->type)
  2290.     {
  2291.     case GDK_EXPOSE:
  2292.       if (cd->pixmap == NULL)
  2293.     cd->pixmap = gdk_pixmap_new (cd->graph->window,
  2294.                      GRAPH_WIDTH + RADIUS * 2,
  2295.                      GRAPH_HEIGHT + RADIUS * 2, -1);
  2296.  
  2297.       bender_update (cd, UP_GRAPH | UP_DRAW);
  2298.       break;
  2299.  
  2300.     case GDK_BUTTON_PRESS:
  2301.       bevent = (GdkEventButton *) event;
  2302.       new_type = GDK_TCROSS;
  2303.  
  2304.       switch (cd->curve_type)
  2305.     {
  2306.     case SMOOTH:
  2307.       /*  determine the leftmost and rightmost points  */
  2308.       cd->leftmost = -1;
  2309.       for (i = closest_point - 1; i >= 0; i--)
  2310.         if (cd->points[cd->outline][i][0] != -1)
  2311.           {
  2312.         cd->leftmost = (cd->points[cd->outline][i][0] * 255.0);
  2313.         break;
  2314.           }
  2315.       cd->rightmost = 256;
  2316.       for (i = closest_point + 1; i < 17; i++)
  2317.         if (cd->points[cd->outline][i][0] != -1)
  2318.           {
  2319.         cd->rightmost = (cd->points[cd->outline][i][0] * 255.0);
  2320.         break;
  2321.           }
  2322.  
  2323.       cd->grab_point = closest_point;
  2324.       cd->points[cd->outline][cd->grab_point][0] = (gdouble)x / 255.0;
  2325.       cd->points[cd->outline][cd->grab_point][1] = (gdouble)(255 - y) / 255.0;
  2326.  
  2327.       bender_calculate_curve (cd, 255, 255, TRUE);
  2328.       break;
  2329.  
  2330.     case GFREE:
  2331.       cd->curve[cd->outline][x] = 255 - y;
  2332.       cd->grab_point = x;
  2333.       cd->last = y;
  2334.       break;
  2335.     }
  2336.  
  2337.       bender_update (cd, UP_GRAPH | UP_DRAW);
  2338.       break;
  2339.  
  2340.     case GDK_BUTTON_RELEASE:
  2341.       new_type = GDK_FLEUR;
  2342.       cd->grab_point = -1;
  2343.  
  2344.       if (cd->preview)
  2345.     bender_update (cd, UP_PREVIEW | UP_DRAW);
  2346.       break;
  2347.  
  2348.     case GDK_MOTION_NOTIFY:
  2349.       mevent = (GdkEventMotion *) event;
  2350.  
  2351.       if (mevent->is_hint)
  2352.     {
  2353.       mevent->x = tx;
  2354.       mevent->y = ty;
  2355.     }
  2356.  
  2357.       switch (cd->curve_type)
  2358.     {
  2359.     case SMOOTH:
  2360.       /*  If no point is grabbed...  */
  2361.       if (cd->grab_point == -1)
  2362.         {
  2363.           if (cd->points[cd->outline][closest_point][0] != -1)
  2364.         new_type = GDK_FLEUR;
  2365.           else
  2366.         new_type = GDK_TCROSS;
  2367.         }
  2368.       /*  Else, drag the grabbed point  */
  2369.       else
  2370.         {
  2371.           new_type = GDK_TCROSS;
  2372.  
  2373.           cd->points[cd->outline][cd->grab_point][0] = -1;
  2374.  
  2375.           if (x > cd->leftmost && x < cd->rightmost)
  2376.         {
  2377.           closest_point = (x + 8) / 16;
  2378.           if (cd->points[cd->outline][closest_point][0] == -1)
  2379.             cd->grab_point = closest_point;
  2380.           cd->points[cd->outline][cd->grab_point][0] = (gdouble)x / 255.0;
  2381.           cd->points[cd->outline][cd->grab_point][1] = (gdouble)(255 - y) / 255.0;
  2382.         }
  2383.  
  2384.           bender_calculate_curve (cd, 255, 255, TRUE);
  2385.           bender_update (cd, UP_GRAPH | UP_DRAW);
  2386.         }
  2387.       break;
  2388.  
  2389.     case GFREE:
  2390.       if (cd->grab_point != -1)
  2391.         {
  2392.           if (cd->grab_point > x)
  2393.         {
  2394.           x1 = x;
  2395.           x2 = cd->grab_point;
  2396.           y1 = y;
  2397.           y2 = cd->last;
  2398.         }
  2399.           else
  2400.         {
  2401.           x1 = cd->grab_point;
  2402.           x2 = x;
  2403.           y1 = cd->last;
  2404.           y2 = y;
  2405.         }
  2406.  
  2407.           if (x2 != x1)
  2408.         for (i = x1; i <= x2; i++)
  2409.           cd->curve[cd->outline][i] = 255 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1));
  2410.           else
  2411.         cd->curve[cd->outline][x] = 255 - y;
  2412.  
  2413.           cd->grab_point = x;
  2414.           cd->last = y;
  2415.  
  2416.           bender_update (cd, UP_GRAPH | UP_DRAW);
  2417.         }
  2418.  
  2419.       if (mevent->state & GDK_BUTTON1_MASK)
  2420.         new_type = GDK_TCROSS;
  2421.       else
  2422.         new_type = GDK_PENCIL;
  2423.       break;
  2424.     }
  2425.  
  2426.       if (new_type != cursor_type)
  2427.     {
  2428.       cursor_type = new_type;
  2429.       /* change_win_cursor (cd->graph->window, cursor_type); */
  2430.     }
  2431.       break;
  2432.  
  2433.     default:
  2434.       break;
  2435.     }
  2436.  
  2437.   return FALSE;
  2438. }
  2439.  
  2440.  
  2441. static gint
  2442. bender_pv_widget_events (GtkWidget    *widget,
  2443.              GdkEvent     *event,
  2444.              BenderDialog *cd)
  2445. {
  2446.   switch (event->type)
  2447.     {
  2448.     case GDK_EXPOSE:
  2449.       bender_update (cd, UP_PREVIEW_EXPOSE);
  2450.       break;
  2451.  
  2452.     default:
  2453.       break;
  2454.     }
  2455.  
  2456.   return FALSE;
  2457. }
  2458.  
  2459. static void
  2460. bender_CR_compose (CRMatrix a,
  2461.            CRMatrix b,
  2462.            CRMatrix ab)
  2463. {
  2464.   int i, j;
  2465.  
  2466.   for (i = 0; i < 4; i++)
  2467.     {
  2468.       for (j = 0; j < 4; j++)
  2469.         {
  2470.           ab[i][j] = (a[i][0] * b[0][j] +
  2471.                       a[i][1] * b[1][j] +
  2472.                       a[i][2] * b[2][j] +
  2473.                       a[i][3] * b[3][j]);
  2474.         }
  2475.     }
  2476. }
  2477.  
  2478.  
  2479. /* ============================================================================
  2480.  * p_buildmenu
  2481.  *    build menu widget for all Items passed in the MenuItems Parameter
  2482.  *    MenuItems is an array of Pointers to Structure MenuItem.
  2483.  *    The End is marked by a Structure Member where the label is a NULL pointer
  2484.  *    (simplifyed version of GIMP 1.0.2 bulid_menu procedur)
  2485.  * ============================================================================
  2486.  */
  2487.  
  2488. GtkWidget *
  2489. p_buildmenu (MenuItem *items)
  2490. {
  2491.   GtkWidget *menu;
  2492.   GtkWidget *menu_item;
  2493.  
  2494.   menu = gtk_menu_new ();
  2495.  
  2496.   while (items->label)
  2497.   {
  2498.       menu_item = gtk_menu_item_new_with_label ( gettext(items->label));
  2499.       gtk_container_add (GTK_CONTAINER (menu), menu_item);
  2500.  
  2501.       if (items->callback)
  2502.     gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  2503.                 (GtkSignalFunc) items->callback,
  2504.                 items->user_data);
  2505.  
  2506.       gtk_widget_show (menu_item);
  2507.       items->widget = menu_item;
  2508.  
  2509.       items++;
  2510.   }
  2511.  
  2512.   return menu;
  2513. }    /* end p_buildmenu */
  2514.  
  2515. void
  2516. p_render_preview (BenderDialog *cd,
  2517.           gint32        layer_id)
  2518. {
  2519.    guchar  l_rowbuf[PREVIEW_BPP * PREVIEW_SIZE_X];
  2520.    guchar  l_pixel[4];
  2521.    guchar *l_ptr;
  2522.    GimpDrawable *l_pv_drawable;
  2523.    gint    l_x, l_y;
  2524.    gint    l_ofx, l_ofy;
  2525.    gint    l_idx;
  2526.    guchar  l_bg_gray;
  2527.    t_GDRW  l_gdrw;
  2528.    t_GDRW  *gdrw;
  2529.  
  2530.    l_pv_drawable = gimp_drawable_get (layer_id);
  2531.  
  2532.    gdrw = &l_gdrw;
  2533.    p_init_gdrw(gdrw, l_pv_drawable, FALSE, FALSE);
  2534.  
  2535.   /* offsets to set bend layer to preview center */
  2536.   l_ofx = (l_pv_drawable->width / 2) - (PREVIEW_SIZE_X / 2);
  2537.   l_ofy = (l_pv_drawable->height / 2) - (PREVIEW_SIZE_Y / 2);
  2538.   
  2539.   /* render preview */
  2540.   for(l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
  2541.   {
  2542.      l_ptr = &l_rowbuf[0];
  2543.  
  2544.      for(l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
  2545.      {
  2546.     p_get_pixel(gdrw, l_x + l_ofx, l_y + l_ofy, &l_pixel[0]);
  2547.     if(l_pixel[gdrw->index_alpha] < 255)
  2548.     {
  2549.        /* for transparent pixels: mix with preview background color */
  2550.        if((l_x % 32) < 16)
  2551.        {
  2552.           l_bg_gray = PREVIEW_BG_GRAY1;
  2553.           if ((l_y % 32) < 16)   l_bg_gray = PREVIEW_BG_GRAY2;
  2554.        }
  2555.        else
  2556.        {
  2557.           l_bg_gray = PREVIEW_BG_GRAY2;
  2558.           if ((l_y % 32) < 16)   l_bg_gray = PREVIEW_BG_GRAY1;
  2559.        }
  2560.        
  2561.        for(l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
  2562.        {
  2563.           l_pixel[l_idx] = MIX_CHANNEL(l_pixel[l_idx], l_bg_gray, l_pixel[gdrw->index_alpha]);
  2564.        }
  2565.     }
  2566.       
  2567.         
  2568.     if(cd->color)
  2569.     {
  2570.       *l_ptr    = l_pixel[0];
  2571.        l_ptr[1] = l_pixel[1];
  2572.        l_ptr[2] = l_pixel[2];
  2573.     }
  2574.     else
  2575.     {
  2576.       *l_ptr    = l_pixel[0];
  2577.        l_ptr[1] = l_pixel[0];
  2578.        l_ptr[2] = l_pixel[0];
  2579.         }
  2580.  
  2581.         l_ptr += PREVIEW_BPP;
  2582.      }
  2583.  
  2584.      gtk_preview_draw_row(GTK_PREVIEW(cd->pv_widget), &l_rowbuf[0], 0, l_y, PREVIEW_SIZE_X);
  2585.   }
  2586.  
  2587.    p_end_gdrw(gdrw);
  2588. }    /* end p_render_preview */
  2589.  
  2590. /* ===================================================== */
  2591. /* curve_bend worker procedures                          */
  2592. /* ===================================================== */
  2593.  
  2594. void
  2595. p_stretch_curves (BenderDialog *cd, 
  2596.           gint32        xmax, 
  2597.           gint32        ymax)
  2598. {
  2599.   gint32   l_x1, l_x2;
  2600.   gdouble  l_ya, l_yb;
  2601.   gdouble  l_rest;
  2602.   int      l_outline;
  2603.  
  2604.   for(l_outline = 0; l_outline < 2; l_outline++)
  2605.   {
  2606.     for(l_x1 = 0; l_x1 <= xmax; l_x1++)
  2607.     {
  2608.        l_x2 = (l_x1 * 255) / xmax;
  2609.        if((xmax <= 255) && (l_x2 < 255))
  2610.        {
  2611.          cd->curve_ptr[l_outline][l_x1] = ROUND((cd->curve[l_outline][l_x2] * ymax) / 255);
  2612.        }
  2613.        else
  2614.        {
  2615.          /* interpolate */
  2616.          l_rest = (((gdouble)l_x1 * 255.0) / (gdouble)xmax) - l_x2;
  2617.          l_ya = cd->curve[l_outline][l_x2];        /* y of this point */
  2618.          l_yb = cd->curve[l_outline][l_x2 +1];     /* y of next point */
  2619.          cd->curve_ptr[l_outline][l_x1] = ROUND (((l_ya + ((l_yb -l_ya) * l_rest)) * ymax) / 255);
  2620.        }
  2621.  
  2622.        {
  2623.         int      l_debugY;
  2624.         l_debugY = ROUND((cd->curve[l_outline][l_x2] * ymax) / 255);
  2625. /*
  2626.  *            printf("_X: %d  _X2: %d Y2: %d _Y: %d debugY:%d\n",
  2627.  *                   (int)l_x1, (int)l_x2,
  2628.  *                   (int)cd->curve[l_outline][l_x2],
  2629.  *                   (int)cd->curve_ptr[l_outline][l_x1], 
  2630.  *                   l_debugY);
  2631.  */
  2632.        }      
  2633.  
  2634.     }
  2635.   }
  2636. }
  2637.  
  2638.  
  2639. void
  2640. bender_init_min_max (BenderDialog *cd, 
  2641.              gint32        xmax)
  2642. {
  2643.   int i, j;
  2644.  
  2645.   for (i = 0; i < 2; i++)
  2646.   {
  2647.     cd->min2[i] = 65000;
  2648.     cd->max2[i] = 0;
  2649.     for (j = 0; j <= xmax; j++)
  2650.     {
  2651.        if(cd->curve_ptr[i][j] > cd->max2[i])
  2652.        {
  2653.           cd->max2[i] = cd->curve_ptr[i][j];
  2654.        }
  2655.        if(cd->curve_ptr[i][j] < cd->min2[i])
  2656.        {
  2657.           cd->min2[i] = cd->curve_ptr[i][j];
  2658.        }
  2659.     }
  2660.   }
  2661.   
  2662.   /* for UPPER outline : y-zero line is assumed at the min leftmost or rightmost point */
  2663.   cd->zero2[OUTLINE_UPPER] = MIN(cd->curve_ptr[OUTLINE_UPPER][0], cd->curve_ptr[OUTLINE_UPPER][xmax]);
  2664.  
  2665.   /* for LOWER outline : y-zero line is assumed at the min leftmost or rightmost point */
  2666.   cd->zero2[OUTLINE_LOWER] = MAX(cd->curve_ptr[OUTLINE_LOWER][0], cd->curve_ptr[OUTLINE_LOWER][xmax]);
  2667.   
  2668.   if(gb_debug)
  2669.   {
  2670.     printf("bender_init_min_max: zero2[0]: %d min2[0]:%d max2[0]:%d\n",
  2671.         (int)cd->zero2[0],
  2672.     (int)cd->min2[0],
  2673.     (int)cd->max2[0]  );
  2674.     printf("bender_init_min_max: zero2[1]: %d min2[1]:%d max2[1]:%d\n",
  2675.         (int)cd->zero2[1],
  2676.     (int)cd->min2[1],
  2677.     (int)cd->max2[1]  );
  2678.   }
  2679.     
  2680. }
  2681.  
  2682.  
  2683. gint32
  2684. p_curve_get_dy (BenderDialog *cd, 
  2685.         gint32        x, 
  2686.         gint32        drawable_width, 
  2687.         gint32        total_steps, 
  2688.         gdouble       current_step)
  2689. {
  2690.   /* get y values of both upper and lower curve,
  2691.    * and return the iterated value inbetween
  2692.    */
  2693.   gint32     l_y; 
  2694.   double     l_y1,  l_y2;
  2695.   double     delta;
  2696.  
  2697.   l_y1 = cd->zero2[OUTLINE_UPPER] - cd->curve_ptr[OUTLINE_UPPER][x];
  2698.   l_y2 = cd->zero2[OUTLINE_LOWER] - cd->curve_ptr[OUTLINE_LOWER][x];
  2699.   
  2700.   delta = ((double)(l_y2 - l_y1) / (double)(total_steps -1)) * current_step;
  2701.   l_y = SIGNED_ROUND(l_y1 + delta);
  2702.   
  2703.   return l_y;
  2704. }
  2705.  
  2706.  
  2707. gint32
  2708. p_upper_curve_extend (BenderDialog *cd, 
  2709.               gint32        drawable_width, 
  2710.               gint32        drawable_height)
  2711. {
  2712.    gint32  l_y1,  l_y2;
  2713.    
  2714.    l_y1 = cd->max2[OUTLINE_UPPER] - cd->zero2[OUTLINE_UPPER];
  2715.    l_y2 = (cd->max2[OUTLINE_LOWER] - cd->zero2[OUTLINE_LOWER]) - drawable_height;
  2716.    
  2717.    return (MAX(l_y1, l_y2));  
  2718. }
  2719.  
  2720. gint32
  2721. p_lower_curve_extend (BenderDialog *cd, 
  2722.               gint32        drawable_width, 
  2723.               gint32        drawable_height)
  2724. {
  2725.    gint32  l_y1,  l_y2;
  2726.  
  2727.    l_y1 = cd->zero2[OUTLINE_LOWER] - cd->min2[OUTLINE_LOWER];
  2728.    l_y2 = (cd->zero2[OUTLINE_UPPER] - cd->min2[OUTLINE_UPPER]) - drawable_height;
  2729.  
  2730.    return (MAX(l_y1, l_y2));  
  2731. }
  2732.  
  2733. void
  2734. p_end_gdrw (t_GDRW *gdrw)
  2735. {
  2736.   if(gb_debug)  
  2737.     printf ("\np_end_gdrw: drawable %x  ID: %d\n", 
  2738.         (int)gdrw->drawable, (int)gdrw->drawable->id);
  2739.  
  2740.   if(gdrw->tile)
  2741.   {
  2742.      if(gb_debug)  printf("p_end_gdrw: tile unref\n");
  2743.      gimp_tile_unref( gdrw->tile, gdrw->tile_dirty);
  2744.      gdrw->tile = NULL;
  2745.   }
  2746.  
  2747.   if(gb_debug)  
  2748.     printf("p_end_gdrw:TILE_SWAPCOUNT: %d\n", (int)gdrw->tile_swapcount);
  2749.  
  2750. }    /* end p_end_gdrw */
  2751.  
  2752.  
  2753. void
  2754. p_init_gdrw (t_GDRW    *gdrw, 
  2755.          GimpDrawable *drawable, 
  2756.          int        dirty, 
  2757.          int        shadow)
  2758. {
  2759.   gint32 l_image_id;
  2760.   gint32 l_sel_channel_id;
  2761.   gint    l_offsetx, l_offsety;
  2762.  
  2763.   if(gb_debug)  printf("\np_init_gdrw: drawable %x  ID: %d\n", (int)drawable, (int)drawable->id);
  2764.  
  2765.   gdrw->drawable = drawable;
  2766.   gdrw->tile = NULL;
  2767.   gdrw->tile_dirty = FALSE;
  2768.   gdrw->tile_width = gimp_tile_width ();
  2769.   gdrw->tile_height = gimp_tile_height ();
  2770.   gdrw->shadow = shadow;
  2771.   gdrw->tile_swapcount = 0;
  2772.   gdrw->seldeltax = 0;
  2773.   gdrw->seldeltay = 0;
  2774.   gimp_drawable_offsets (drawable->id, &l_offsetx, &l_offsety);  /* get offsets within the image */
  2775.   
  2776.   gimp_drawable_mask_bounds (drawable->id, &gdrw->x1, &gdrw->y1, &gdrw->x2, &gdrw->y2);
  2777.  
  2778. /*
  2779.  *   gimp_pixel_rgn_init (&gdrw->pr, drawable,
  2780.  *                       gdrw->x1, gdrw->y1, gdrw->x2 - gdrw->x1, gdrw->y2 - gdrw->y1,
  2781.  *                       dirty, shadow);
  2782.  */
  2783.  
  2784.  
  2785.   gdrw->bpp = drawable->bpp;
  2786.   if (gimp_drawable_has_alpha(drawable->id))
  2787.   {
  2788.      /* index of the alpha channelbyte {1|3} */
  2789.      gdrw->index_alpha = gdrw->bpp -1;
  2790.   }
  2791.   else
  2792.   {
  2793.      gdrw->index_alpha = 0;      /* there is no alpha channel */
  2794.   }
  2795.   
  2796.   if(gb_debug)  printf("\np_init_gdrw: bpp %d  index_alpha: %d\n", (int)gdrw->bpp, (int)gdrw->index_alpha);
  2797.   
  2798.   l_image_id = gimp_layer_get_image_id(drawable->id);
  2799.  
  2800.   /* check and see if we have a selection mask */
  2801.   l_sel_channel_id  = gimp_image_get_selection(l_image_id);     
  2802.  
  2803.   if(gb_debug)  
  2804.   {
  2805.      printf("p_init_gdrw: image_id %d sel_channel_id: %d\n", (int)l_image_id, (int)l_sel_channel_id);
  2806.      printf("p_init_gdrw: BOUNDS     x1: %d y1: %d x2:%d y2: %d\n",
  2807.         (int)gdrw->x1,  (int)gdrw->y1, (int)gdrw->x2,(int)gdrw->y2);
  2808.      printf("p_init_gdrw: OFFS       x: %d y: %d\n", (int)l_offsetx, (int)l_offsety );
  2809.   }
  2810. }    /* end p_init_gdrw */
  2811.  
  2812.  
  2813. static void
  2814. p_provide_tile (t_GDRW *gdrw, 
  2815.         gint    col, 
  2816.         gint    row, 
  2817.         gint    shadow )
  2818. {
  2819.     if ( col != gdrw->tile_col || row != gdrw->tile_row || !gdrw->tile )
  2820.     {
  2821.        if( gdrw->tile ) 
  2822.        {
  2823.      gimp_tile_unref( gdrw->tile, gdrw->tile_dirty );
  2824.        }
  2825.        gdrw->tile_col = col;
  2826.        gdrw->tile_row = row;
  2827.        gdrw->tile = gimp_drawable_get_tile( gdrw->drawable, shadow, gdrw->tile_row, gdrw->tile_col );
  2828.        gdrw->tile_dirty = FALSE;
  2829.        gimp_tile_ref( gdrw->tile );
  2830.  
  2831.        gdrw->tile_swapcount++;
  2832.  
  2833.        return;
  2834.     }
  2835. }    /* end p_provide_tile */
  2836.  
  2837. /* get pixel value
  2838.  *   return light transparent black gray pixel if out of bounds
  2839.  *   (should occur in the previews only)
  2840.  */
  2841. static void
  2842. p_get_pixel (t_GDRW *gdrw, 
  2843.          gint32  x, 
  2844.          gint32  y, 
  2845.          guchar *pixel )
  2846. {
  2847.     gint   row, col;
  2848.     gint   offx, offy;
  2849.     guchar  *ptr;
  2850.  
  2851.     if((x < 0)
  2852.     || (x > gdrw->drawable->width   -1)
  2853.     || (y < 0)
  2854.     || (y > gdrw->drawable->height - 1))
  2855.     {
  2856.       pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
  2857.       return;
  2858.     }
  2859.  
  2860.     col = x / gdrw->tile_width;
  2861.     row = y / gdrw->tile_height;
  2862.     offx = x % gdrw->tile_width;
  2863.     offy = y % gdrw->tile_height;
  2864.  
  2865.     p_provide_tile(  gdrw, col, row, gdrw->shadow);
  2866.  
  2867.     pixel[1] = 255;  pixel[3] = 255;  /* simulate full visible alpha channel */
  2868.     ptr = gdrw->tile->data + ((( offy * gdrw->tile->ewidth) + offx ) * gdrw->bpp);
  2869.     memcpy(pixel, ptr, gdrw->bpp);
  2870.  
  2871.     /* 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]);
  2872.      */
  2873. }    /* end p_get_pixel */
  2874.  
  2875. void
  2876. p_put_pixel (t_GDRW *gdrw, 
  2877.          gint32  x, 
  2878.          gint32  y, 
  2879.          guchar *pixel)
  2880. {
  2881.     gint   row, col;
  2882.     gint   offx, offy;
  2883.     guchar  *ptr;
  2884.  
  2885.     if (x < gdrw->x1)       return;
  2886.     if (x > gdrw->x2 - 1)   return;
  2887.     if (y < gdrw->y1)       return;
  2888.     if (y > gdrw->y2 - 1)   return;
  2889.  
  2890.     col = x / gdrw->tile_width;
  2891.     row = y / gdrw->tile_height;
  2892.     offx = x % gdrw->tile_width;
  2893.     offy = y % gdrw->tile_height;
  2894.  
  2895.     p_provide_tile( gdrw, col, row, gdrw->shadow );
  2896.  
  2897.     ptr = gdrw->tile->data + ((( offy * gdrw->tile->ewidth ) + offx ) * gdrw->bpp);
  2898.     memcpy(ptr, pixel, gdrw->bpp);
  2899.  
  2900.     gdrw->tile_dirty = TRUE;
  2901.  
  2902.    /* 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]);
  2903.     */
  2904. }    /* end p_put_pixel */
  2905.  
  2906. void
  2907. p_put_mix_pixel (t_GDRW *gdrw, 
  2908.          gint32  x, 
  2909.          gint32  y, 
  2910.          guchar *color, 
  2911.          gint32  nb_curvy, 
  2912.          gint32  nb2_curvy, 
  2913.          gint32  curvy)
  2914. {
  2915.    guchar  l_pixel[4];
  2916.    guchar  l_mixmask;
  2917.    gint    l_idx;
  2918.    gint    l_diff;
  2919.    
  2920.    l_mixmask = 255 - 96;
  2921.    l_diff = abs(nb_curvy - curvy);
  2922.    if(l_diff == 0)
  2923.    {
  2924.      l_mixmask = 255 - 48;
  2925.      l_diff = abs(nb2_curvy - curvy);
  2926.      
  2927.      if(l_diff == 0)
  2928.      {
  2929.        /* last 2 neighbours were not shifted against current pixel, do not mix */     
  2930.        p_put_pixel(gdrw, x, y, color);
  2931.        return;
  2932.      }
  2933.    }
  2934.  
  2935.    /* get left neighbour pixel */ 
  2936.    p_get_pixel(gdrw, x-1, y, &l_pixel[0]);
  2937.  
  2938.    if(l_pixel[gdrw->index_alpha] < 10)
  2939.    {
  2940.      /* neighbour is (nearly or full) transparent, do not mix */     
  2941.      p_put_pixel(gdrw, x, y, color);
  2942.      return;
  2943.    }
  2944.  
  2945.    for(l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
  2946.    {
  2947.       /* mix in left neighbour color */
  2948.       l_pixel[l_idx] = MIX_CHANNEL(color[l_idx], l_pixel[l_idx], l_mixmask);
  2949.    }
  2950.  
  2951.    l_pixel[gdrw->index_alpha] = color[gdrw->index_alpha];
  2952.    p_put_pixel(gdrw, x, y, &l_pixel[0]);
  2953. }
  2954.  
  2955. void
  2956. p_put_mix_pixel_FIX (t_GDRW *gdrw, 
  2957.              gint32  x, 
  2958.              gint32  y, 
  2959.              guchar *color, 
  2960.              gint32  nb_curvy, 
  2961.              gint32  nb2_curvy, 
  2962.              gint32  curvy)
  2963. {
  2964.    guchar  l_pixel[4];
  2965.    guchar  l_mixmask;
  2966.    gint    l_idx;
  2967.    
  2968.    l_mixmask = 256 - 64;
  2969.  
  2970.    /* get left neighbour pixel */ 
  2971.    p_get_pixel(gdrw, x-1, y, &l_pixel[0]);
  2972.  
  2973.    if(l_pixel[gdrw->index_alpha] < 20)
  2974.    {
  2975.      /* neighbour is (nearly or full) transparent, do not mix */     
  2976.      p_put_pixel(gdrw, x, y, color);
  2977.      return;
  2978.    }
  2979.  
  2980.    for(l_idx = 0; l_idx < gdrw->index_alpha ; l_idx++)
  2981.    {
  2982.       /* mix in left neighbour color */
  2983.       l_pixel[l_idx] = MIX_CHANNEL(color[l_idx], l_pixel[l_idx], l_mixmask);
  2984.    }
  2985.  
  2986.    l_pixel[gdrw->index_alpha] = color[gdrw->index_alpha];
  2987.    p_put_pixel(gdrw, x, y, &l_pixel[0]);
  2988. }
  2989.  
  2990. /* ============================================================================
  2991.  * p_clear_drawable
  2992.  * ============================================================================
  2993.  */
  2994.  
  2995. void
  2996. p_clear_drawable (GimpDrawable *drawable)
  2997. {
  2998.    GimpPixelRgn  pixel_rgn;
  2999.    gpointer    pr;
  3000.    gint         l_row;
  3001.    guchar      *l_ptr;
  3002.    
  3003.  
  3004.    gimp_pixel_rgn_init (&pixel_rgn, drawable,
  3005.                  0, 0, drawable->width, drawable->height,
  3006.                  TRUE,  /* dirty */
  3007.                  FALSE  /* shadow */
  3008.                  );
  3009.  
  3010.    /* clear the drawable with 0 Bytes (black full-transparent pixels) */
  3011.    for (pr = gimp_pixel_rgns_register (1, &pixel_rgn);
  3012.     pr != NULL; pr = gimp_pixel_rgns_process (pr))
  3013.    {
  3014.       l_ptr = pixel_rgn.data;
  3015.       for ( l_row = 0; l_row < pixel_rgn.h; l_row++ )
  3016.       {
  3017.     memset(l_ptr, 0, pixel_rgn.w * drawable->bpp);
  3018.     l_ptr += pixel_rgn.rowstride;
  3019.       }
  3020.    }
  3021. }    /* end  p_clear_drawable */
  3022.  
  3023. /* ============================================================================
  3024.  * p_create_pv_image
  3025.  * ============================================================================
  3026.  */
  3027. gint32
  3028. p_create_pv_image (GimpDrawable *src_drawable, 
  3029.            gint32    *layer_id)
  3030. {
  3031.   gint32     l_new_image_id;
  3032.   guint      l_new_width;
  3033.   guint      l_new_height;
  3034.   GimpImageType l_type;
  3035.  
  3036.   gint    l_x, l_y;
  3037.   double  l_scale;
  3038.   guchar  l_pixel[4];
  3039.   GimpDrawable *dst_drawable;
  3040.   t_GDRW  l_src_gdrw;
  3041.   t_GDRW  l_dst_gdrw;
  3042.  
  3043.   l_new_image_id = gimp_image_new(PREVIEW_SIZE_X, PREVIEW_SIZE_Y, 
  3044.                    gimp_image_base_type(gimp_layer_get_image_id(src_drawable->id)));
  3045.   gimp_image_undo_disable (l_new_image_id);
  3046.  
  3047.   l_type = gimp_drawable_type(src_drawable->id);  
  3048.   if(src_drawable->height > src_drawable->width)
  3049.   {
  3050.     l_new_height = PV_IMG_HEIGHT;
  3051.     l_new_width = (src_drawable->width * l_new_height) / src_drawable->height;
  3052.     l_scale = (float)src_drawable->height / PV_IMG_HEIGHT;
  3053.   }
  3054.   else
  3055.   {
  3056.     l_new_width = PV_IMG_WIDTH;
  3057.     l_new_height = (src_drawable->height * l_new_width) / src_drawable->width;
  3058.     l_scale = (float)src_drawable->width / PV_IMG_WIDTH;
  3059.   }
  3060.  
  3061.   *layer_id = gimp_layer_new(l_new_image_id, "preview_original",
  3062.                              l_new_width, l_new_height,
  3063.                              l_type, 
  3064.                              100.0,    /* opacity */
  3065.                              0         /* mode NORMAL */
  3066.                              );
  3067.   if(!gimp_drawable_has_alpha(*layer_id))
  3068.   {
  3069.     /* always add alpha channel */
  3070.     gimp_layer_add_alpha(*layer_id);
  3071.   }
  3072.                                  
  3073.   gimp_image_add_layer(l_new_image_id, *layer_id, 0);
  3074.  
  3075.   dst_drawable = gimp_drawable_get (*layer_id);
  3076.   p_init_gdrw(&l_src_gdrw, src_drawable, FALSE, FALSE);
  3077.   p_init_gdrw(&l_dst_gdrw, dst_drawable,  TRUE,  FALSE);
  3078.  
  3079.   for(l_y = 0; l_y < l_new_height; l_y++)
  3080.   {
  3081.      for(l_x = 0; l_x < l_new_width; l_x++)
  3082.      {
  3083.        p_get_pixel(&l_src_gdrw, l_x * l_scale, l_y * l_scale, &l_pixel[0]);
  3084.        p_put_pixel(&l_dst_gdrw, l_x, l_y, &l_pixel[0]);
  3085.      }
  3086.   }
  3087.   
  3088.   p_end_gdrw(&l_src_gdrw);
  3089.   p_end_gdrw(&l_dst_gdrw);
  3090.  
  3091.   /* gimp_display_new(l_new_image_id); */
  3092.   return (l_new_image_id);
  3093. }
  3094.  
  3095. /* ============================================================================
  3096.  * p_add_layer
  3097.  * ============================================================================
  3098.  */
  3099. GimpDrawable* 
  3100. p_add_layer (gint       width, 
  3101.          gint       height, 
  3102.          GimpDrawable *src_drawable)
  3103. {
  3104.   GimpImageType  l_type;
  3105.   static GimpDrawable  *l_new_drawable;
  3106.   gint32     l_new_layer_id;
  3107.   char      *l_name;
  3108.   char      *l_name2;
  3109.   gdouble    l_opacity;
  3110.   GimpLayerModeEffects l_mode;
  3111.   gint       l_visible;
  3112.   gint32     image_id;
  3113.   gint       stack_position;
  3114.  
  3115.  
  3116.   image_id = gimp_layer_get_image_id(src_drawable->id);
  3117.   stack_position = 0;                                  /* TODO:  should be same as src_layer */
  3118.   
  3119.   /* copy type, name, opacity and mode from src_drawable */ 
  3120.   l_type     = gimp_drawable_type(src_drawable->id);
  3121.   l_visible  = gimp_layer_get_visible(src_drawable->id);
  3122.  
  3123.   if (TRUE != TRUE)
  3124.   {
  3125.     l_name = gimp_layer_get_name(src_drawable->id);
  3126.   }
  3127.   else
  3128.   {
  3129.     l_name2 = gimp_layer_get_name(src_drawable->id);
  3130.     l_name  = g_malloc(strlen(l_name2) + 10);
  3131.     if(l_name == NULL) 
  3132.        return (NULL);
  3133.     sprintf(l_name, "%s_b", l_name2);
  3134.     g_free(l_name2);
  3135.   }
  3136.   l_mode = gimp_layer_get_mode(src_drawable->id);
  3137.   l_opacity = gimp_layer_get_opacity(src_drawable->id);  /* full opacity */
  3138.   
  3139.   l_new_layer_id = gimp_layer_new(image_id, l_name,
  3140.                                   width, height,
  3141.                                   l_type, 
  3142.                                   l_opacity,
  3143.                                   l_mode
  3144.                                   );
  3145.  
  3146.   if(l_name != NULL)         g_free (l_name);
  3147.   if(!gimp_drawable_has_alpha(l_new_layer_id))
  3148.   {
  3149.     /* always add alpha channel */
  3150.     gimp_layer_add_alpha(l_new_layer_id);
  3151.   }
  3152.   
  3153.   l_new_drawable = gimp_drawable_get (l_new_layer_id);
  3154.   if(l_new_drawable == NULL)
  3155.   {
  3156.      fprintf(stderr, "p_ad_layer: cant get new_drawable\n");
  3157.      return (NULL);
  3158.   }
  3159.  
  3160.   /* add the copied layer to the temp. working image */
  3161.   gimp_image_add_layer (image_id, l_new_layer_id, stack_position);
  3162.  
  3163.   /* copy visiblity state */
  3164.   gimp_layer_set_visible(l_new_layer_id, l_visible);
  3165.     
  3166.   return (l_new_drawable);
  3167. }
  3168.  
  3169. /* ============================================================================
  3170.  * p_bender_calculate_iter_curve
  3171.  * ============================================================================
  3172.  */
  3173.  
  3174.  
  3175. void
  3176. p_bender_calculate_iter_curve (BenderDialog *cd, 
  3177.                    gint32        xmax, 
  3178.                    gint32        ymax)
  3179. {
  3180.    int l_x;
  3181.    gint      l_outline;
  3182.    BenderDialog *cd_from;
  3183.    BenderDialog *cd_to;
  3184.  
  3185.    l_outline = cd->outline;
  3186.    
  3187.    if((cd->bval_from == NULL) || (cd->bval_to == NULL) || (cd->bval_curr == NULL))
  3188.    {
  3189.      if(gb_debug)  printf("p_bender_calculate_iter_curve NORMAL1\n");
  3190.      if (cd->curve_type == SMOOTH)
  3191.      {
  3192.        cd->outline = OUTLINE_UPPER;
  3193.        bender_calculate_curve (cd, xmax, ymax, FALSE);
  3194.        cd->outline = OUTLINE_LOWER;
  3195.        bender_calculate_curve (cd, xmax, ymax, FALSE);
  3196.      }
  3197.      else
  3198.      {
  3199.        p_stretch_curves(cd, xmax, ymax);
  3200.      }
  3201.    }
  3202.    else
  3203.    {
  3204.      /* compose curves by iterating between FROM/TO values */
  3205.      if(gb_debug)  printf("p_bender_calculate_iter_curve ITERmode 1\n");
  3206.    
  3207.      /* init FROM curves */
  3208.      cd_from = g_malloc (sizeof (BenderDialog));
  3209.      p_cd_from_bval(cd_from, cd->bval_from);
  3210.      cd_from->curve_ptr[OUTLINE_UPPER] = g_malloc(sizeof(gint32) * (1+xmax));
  3211.      cd_from->curve_ptr[OUTLINE_LOWER] = g_malloc(sizeof(gint32) * (1+xmax));
  3212.      
  3213.      /* init TO curves */
  3214.      cd_to = g_malloc (sizeof (BenderDialog));
  3215.      p_cd_from_bval(cd_to, cd->bval_to);
  3216.      cd_to->curve_ptr[OUTLINE_UPPER] = g_malloc(sizeof(gint32) * (1+xmax));
  3217.      cd_to->curve_ptr[OUTLINE_LOWER] = g_malloc(sizeof(gint32) * (1+xmax));
  3218.  
  3219.      if (cd_from->curve_type == SMOOTH)
  3220.      {
  3221.        /* calculate FROM curves */
  3222.        cd_from->outline = OUTLINE_UPPER;
  3223.        bender_calculate_curve (cd_from, xmax, ymax, FALSE);
  3224.        cd_from->outline = OUTLINE_LOWER;
  3225.        bender_calculate_curve (cd_from, xmax, ymax, FALSE);
  3226.      }
  3227.      else
  3228.      {
  3229.        p_stretch_curves(cd_from, xmax, ymax);
  3230.      }
  3231.  
  3232.      if (cd_to->curve_type == SMOOTH)
  3233.      {
  3234.        /* calculate TO curves */
  3235.        cd_to->outline = OUTLINE_UPPER;
  3236.        bender_calculate_curve (cd_to, xmax, ymax, FALSE);
  3237.        cd_to->outline = OUTLINE_LOWER;
  3238.        bender_calculate_curve (cd_to, xmax, ymax, FALSE);
  3239.      }
  3240.      else
  3241.      {
  3242.        p_stretch_curves(cd_to, xmax, ymax);
  3243.      }
  3244.    
  3245.      
  3246.      /* MIX Y-koords of the curves according to current iteration step */
  3247.      for(l_x = 0; l_x <= xmax; l_x++)
  3248.      {
  3249.         p_delta_gint32(&cd->curve_ptr[OUTLINE_UPPER][l_x],
  3250.                         cd_from->curve_ptr[OUTLINE_UPPER][l_x],
  3251.                         cd_to->curve_ptr[OUTLINE_UPPER][l_x],
  3252.                         cd->bval_curr->total_steps,
  3253.                         cd->bval_curr->current_step);
  3254.                         
  3255.         p_delta_gint32(&cd->curve_ptr[OUTLINE_LOWER][l_x],
  3256.                         cd_from->curve_ptr[OUTLINE_LOWER][l_x],
  3257.                         cd_to->curve_ptr[OUTLINE_LOWER][l_x],
  3258.                         cd->bval_curr->total_steps,
  3259.                         cd->bval_curr->current_step);
  3260.      }
  3261.      
  3262.  
  3263.      g_free(cd_from->curve_ptr[OUTLINE_UPPER]);
  3264.      g_free(cd_from->curve_ptr[OUTLINE_LOWER]);
  3265.      
  3266.      g_free(cd_from);
  3267.      g_free(cd_to);
  3268.      
  3269.    }
  3270.  
  3271.    cd->outline = l_outline;
  3272. }    /* end p_bender_calculate_iter_curve */
  3273.  
  3274. /* ============================================================================
  3275.  * p_vertical_bend
  3276.  * ============================================================================
  3277.  */
  3278.  
  3279. int
  3280. p_vertical_bend (BenderDialog *cd, 
  3281.          t_GDRW       *src_gdrw, 
  3282.          t_GDRW       *dst_gdrw)
  3283. {
  3284.    gint32             l_row, l_col;
  3285.    gint32             l_first_row, l_first_col, l_last_row, l_last_col;
  3286.    gint32             l_x, l_y;
  3287.    gint32             l_x2, l_y2;
  3288.    gint32             l_curvy, l_nb_curvy, l_nb2_curvy;
  3289.    gint32             l_desty, l_othery;
  3290.    gint32             l_miny, l_maxy;
  3291.    gint32             l_sign, l_dy, l_diff;
  3292.    gint32             l_topshift;
  3293.    float l_progress_step;
  3294.    float l_progress_max;
  3295.    float l_progress;
  3296.  
  3297.    t_Last            *last_arr;
  3298.    t_Last            *first_arr;
  3299.    guchar             color[4];
  3300.    guchar             mixcolor[4];
  3301.    guchar             l_alpha_lo;
  3302.    gint               l_alias_dir;
  3303.    guchar             l_mixmask;
  3304.  
  3305.  
  3306.    l_topshift = p_upper_curve_extend(cd, src_gdrw->drawable->width, src_gdrw->drawable->height);
  3307.    l_diff = l_curvy = l_nb_curvy = l_nb2_curvy= l_miny = l_maxy = 0;
  3308.    l_alpha_lo = 20;
  3309.  
  3310.    /* allocate array of last values (one element foreach x koordinate) */
  3311.    last_arr = g_malloc(sizeof(t_Last) * src_gdrw->x2);
  3312.    first_arr = g_malloc(sizeof(t_Last) * src_gdrw->x2);
  3313.  
  3314.    /* ------------------------------------------------
  3315.     * foreach pixel in the SAMPLE_drawable:
  3316.     * ------------------------------------------------
  3317.     * the inner loops (l_x/l_y) are designed to process
  3318.     * all pixels of one tile in the sample drawable, the outer loops (row/col) do step
  3319.     * to the next tiles. (this was done to reduce tile swapping)
  3320.     */
  3321.  
  3322.    l_first_row = src_gdrw->y1 / src_gdrw->tile_height;
  3323.    l_last_row  = (src_gdrw->y2 / src_gdrw->tile_height);
  3324.    l_first_col = src_gdrw->x1 / src_gdrw->tile_width;
  3325.    l_last_col  = (src_gdrw->x2 / src_gdrw->tile_width);
  3326.  
  3327.    /* init progress */
  3328.    l_progress_max = (1 + l_last_row - l_first_row) * (1 + l_last_col - l_first_col);
  3329.    l_progress_step = 1.0 / l_progress_max;
  3330.    l_progress = 0.0;
  3331.    if(cd->show_progress) gimp_progress_init ( _("Curve Bend..."));
  3332.  
  3333.    for(l_row = l_first_row; l_row <= l_last_row; l_row++)
  3334.    {
  3335.      for(l_col = l_first_col; l_col <= l_last_col; l_col++)
  3336.      {
  3337.        if(l_col == l_first_col)    l_x = src_gdrw->x1;
  3338.        else                        l_x = l_col * src_gdrw->tile_width;
  3339.        if(l_col == l_last_col)     l_x2 = src_gdrw->x2;
  3340.        else                        l_x2 = (l_col +1) * src_gdrw->tile_width;
  3341.  
  3342.        if(cd->show_progress) gimp_progress_update (l_progress += l_progress_step);    
  3343.        
  3344.        for( ; l_x < l_x2; l_x++)
  3345.        {
  3346.          if(l_row == l_first_row)    l_y = src_gdrw->y1;
  3347.          else                        l_y = l_row * src_gdrw->tile_height;
  3348.          if(l_row == l_last_row)     l_y2 = src_gdrw->y2;
  3349.          else                        l_y2 = (l_row +1) * src_gdrw->tile_height ;
  3350.  
  3351.          /* printf("X: %4d Y:%4d Y2:%4d\n", (int)l_x, (int)l_y, (int)l_y2); */
  3352.        
  3353.          for( ; l_y < l_y2; l_y++)
  3354.          {
  3355.             /* ---------- copy SRC_PIXEL to curve position ------ */
  3356.             
  3357.         p_get_pixel(src_gdrw, l_x, l_y, &color[0]);            
  3358.  
  3359.             l_curvy = p_curve_get_dy(cd, l_x, 
  3360.                                     (gint32)src_gdrw->drawable->width, 
  3361.                                     (gint32)src_gdrw->drawable->height, (gdouble)l_y);
  3362.             l_desty = l_y + l_topshift + l_curvy;
  3363.             
  3364.             /* ----------- SMOOTING ------------------ */
  3365.             if((cd->smoothing == TRUE) && (l_x > 0))
  3366.             {
  3367.                l_nb_curvy = p_curve_get_dy(cd, l_x -1, 
  3368.                                     (gint32)src_gdrw->drawable->width, 
  3369.                                     (gint32)src_gdrw->drawable->height, (gdouble)l_y);
  3370.                if((l_nb_curvy == l_curvy) && (l_x > 1))
  3371.                {
  3372.                     l_nb2_curvy = p_curve_get_dy(cd, l_x -2, 
  3373.                                     (gint32)src_gdrw->drawable->width, 
  3374.                                     (gint32)src_gdrw->drawable->height, (gdouble)l_y);
  3375.                }
  3376.                else
  3377.                {
  3378.                     l_nb2_curvy = l_nb_curvy;
  3379.                }
  3380.                p_put_mix_pixel(dst_gdrw, l_x, l_desty, &color[0], l_nb_curvy, l_nb2_curvy, l_curvy );
  3381.             }
  3382.             else
  3383.             {
  3384.                p_put_pixel(dst_gdrw, l_x, l_desty, &color[0]);
  3385.             }
  3386.  
  3387.             /* ----------- render ANTIALIAS ------------------ */
  3388.  
  3389.             if(cd->antialias)
  3390.             {
  3391.                l_othery = l_desty;
  3392.                
  3393.                if(l_y == src_gdrw->y1)             /* Upper outline */
  3394.                {
  3395.                   first_arr[l_x].y = l_curvy;
  3396.                   memcpy(&first_arr[l_x].color[0], &color[0], dst_gdrw->drawable->bpp);
  3397.                     
  3398.                   if(l_x > 0)
  3399.                   {
  3400.                     memcpy(&mixcolor[0], &first_arr[l_x-1].color[0], dst_gdrw->drawable->bpp);
  3401.                      
  3402.                     l_diff = abs(first_arr[l_x - 1].y - l_curvy) +1;
  3403.                     l_miny = MIN(first_arr[l_x - 1].y, l_curvy) -1;
  3404.                     l_maxy = MAX(first_arr[l_x - 1].y, l_curvy) +1;
  3405.  
  3406.             l_othery = (src_gdrw->y2 -1) 
  3407.                      + l_topshift 
  3408.                      + p_curve_get_dy(cd, l_x, 
  3409.                                               (gint32)src_gdrw->drawable->width, 
  3410.                                               (gint32)src_gdrw->drawable->height,
  3411.                               (gdouble)(src_gdrw->y2 -1));
  3412.                    }
  3413.                }
  3414.                if(l_y == src_gdrw->y2 -1)      /* Lower outline */
  3415.                {
  3416.                   if(l_x > 0)
  3417.                   {
  3418.                     memcpy(&mixcolor[0], &last_arr[l_x-1].color[0], dst_gdrw->drawable->bpp);
  3419.                      
  3420.                     l_diff = abs(last_arr[l_x - 1].y - l_curvy) +1;
  3421.                     l_maxy = MAX(last_arr[l_x - 1].y, l_curvy) +1;
  3422.                     l_miny = MIN(last_arr[l_x - 1].y, l_curvy) -1;
  3423.                    }
  3424.  
  3425.             l_othery = (src_gdrw->y1) 
  3426.                      + l_topshift 
  3427.                      + p_curve_get_dy(cd, l_x, 
  3428.                                               (gint32)src_gdrw->drawable->width, 
  3429.                                               (gint32)src_gdrw->drawable->height,
  3430.                               (gdouble)(src_gdrw->y1));
  3431.                }
  3432.  
  3433.            if(l_desty < l_othery)        { l_alias_dir =  1; }  /* fade to transp. with descending dy */
  3434.            else if(l_desty > l_othery)   { l_alias_dir = -1; }  /* fade to transp. with ascending dy */
  3435.            else                          { l_alias_dir =  0; }  /* no antialias at curve crossing point(s) */
  3436.            
  3437.            if(l_alias_dir != 0)
  3438.            {
  3439.                l_alpha_lo = 20;
  3440.                    if (gimp_drawable_has_alpha(src_gdrw->drawable->id))
  3441.                    {
  3442.                      l_alpha_lo = MIN(20, mixcolor[src_gdrw->index_alpha]);
  3443.                    }
  3444.                      
  3445.            
  3446.                    for(l_dy = 0; l_dy < l_diff; l_dy++)
  3447.                    {
  3448.                         /* iterate for fading alpha channel */
  3449.                         l_mixmask =  255 * ((gdouble)(l_dy+1) / (gdouble)(l_diff+1));
  3450.                         mixcolor[dst_gdrw->index_alpha] = MIX_CHANNEL(color[dst_gdrw->index_alpha], l_alpha_lo, l_mixmask);
  3451.             if(l_alias_dir > 0)
  3452.             {
  3453.                           p_put_pixel(dst_gdrw, l_x -1, l_y + l_topshift  + l_miny + l_dy, &mixcolor[0]);
  3454.             }
  3455.             else
  3456.             {
  3457.                           p_put_pixel(dst_gdrw, l_x -1, l_y + l_topshift  + (l_maxy - l_dy), &mixcolor[0]);
  3458.             }
  3459.  
  3460.                    }
  3461.            }
  3462.             }
  3463.  
  3464.             /* ------------------ FILL HOLES ------------------ */
  3465.  
  3466.             if(l_y == src_gdrw->y1)
  3467.             {
  3468.                l_diff = 0;
  3469.                l_sign = 1;
  3470.             }
  3471.             else
  3472.             {
  3473.                l_diff = last_arr[l_x].y - l_curvy;
  3474.                if (l_diff < 0)
  3475.                {
  3476.                   l_diff = 0 - l_diff;
  3477.                   l_sign = -1;
  3478.                }
  3479.                else
  3480.                {
  3481.                   l_sign = 1;
  3482.                }
  3483.                
  3484.                memcpy(&mixcolor[0], &color[0], dst_gdrw->drawable->bpp);
  3485.             }
  3486.             
  3487.             for(l_dy = 1; l_dy <= l_diff; l_dy++)
  3488.             {
  3489.                /* y differs more than 1 pixel from last y in the destination
  3490.                 * drawable. So we have to fill the empty space between
  3491.                 * using a mixed color
  3492.                 */
  3493.  
  3494.                if(cd->smoothing == TRUE)
  3495.                {
  3496.                  /* smooting is on, so we are using a mixed color */
  3497.                  l_mixmask =  255 * ((gdouble)(l_dy) / (gdouble)(l_diff+1));
  3498.                  mixcolor[0] =  MIX_CHANNEL(last_arr[l_x].color[0], color[0], l_mixmask);
  3499.                  mixcolor[1] =  MIX_CHANNEL(last_arr[l_x].color[1], color[1], l_mixmask);
  3500.                  mixcolor[2] =  MIX_CHANNEL(last_arr[l_x].color[2], color[2], l_mixmask);
  3501.                  mixcolor[3] =  MIX_CHANNEL(last_arr[l_x].color[3], color[3], l_mixmask);
  3502.                }
  3503.                else
  3504.                {
  3505.                   /* smooting is off, so we are using this color or the last color */
  3506.                   if(l_dy < l_diff / 2)
  3507.                   {
  3508.                     memcpy(&mixcolor[0], &color[0], dst_gdrw->drawable->bpp);
  3509.                   }
  3510.                   else
  3511.                   {
  3512.                     memcpy(&mixcolor[0], &last_arr[l_x].color[0], dst_gdrw->drawable->bpp);
  3513.                   }
  3514.                }
  3515.                
  3516.                if(cd->smoothing == TRUE)
  3517.                {
  3518.                   p_put_mix_pixel(dst_gdrw, l_x, l_desty + (l_dy * l_sign), &mixcolor[0],
  3519.                                   l_nb_curvy, l_nb2_curvy, l_curvy );
  3520.                }
  3521.                else
  3522.                {
  3523.                   p_put_pixel(dst_gdrw, l_x, l_desty + (l_dy * l_sign), &mixcolor[0]);               
  3524.                }
  3525.             }
  3526.             
  3527.             /* store y and color */ 
  3528.             last_arr[l_x].y = l_curvy;
  3529.             memcpy(&last_arr[l_x].color[0], &color[0], dst_gdrw->drawable->bpp);
  3530.             
  3531.  
  3532.          }
  3533.        }
  3534.      }
  3535.    }
  3536.  
  3537.    if (gb_debug) 
  3538.      printf("ROWS: %d - %d  COLS: %d - %d\n", 
  3539.         (int)l_first_row, (int)l_last_row, (int)l_first_col, (int)l_last_col);
  3540.  
  3541.    return 0;
  3542.  
  3543. }
  3544.  
  3545. /* ============================================================================
  3546.  * p_main_bend
  3547.  * ============================================================================
  3548.  */
  3549.  
  3550. gint32
  3551. p_main_bend (BenderDialog *cd, 
  3552.          GimpDrawable    *original_drawable, 
  3553.          gint          work_on_copy)
  3554. {
  3555.    t_GDRW  l_src_gdrw;
  3556.    t_GDRW  l_dst_gdrw;
  3557.    GimpDrawable *dst_drawable;
  3558.    GimpDrawable *src_drawable;
  3559.    gint32    l_dst_height;
  3560.    gint32    l_image_id;
  3561.    gint32    l_tmp_layer_id;
  3562.    gint32    l_interpolation;
  3563.    gint      l_offset_x, l_offset_y;
  3564.    gint      l_center_x, l_center_y;
  3565.    gint32    xmax, ymax;
  3566.   
  3567.    l_interpolation = cd->smoothing;
  3568.    l_image_id = gimp_layer_get_image_id(original_drawable->id);
  3569.    gimp_drawable_offsets(original_drawable->id, &l_offset_x, &l_offset_y);
  3570.  
  3571.    l_center_x = l_offset_x + (gimp_drawable_width  (original_drawable->id) / 2 );
  3572.    l_center_y = l_offset_y + (gimp_drawable_height (original_drawable->id) / 2 );
  3573.    
  3574.    /* always copy original_drawable to a tmp src_layer */  
  3575.    l_tmp_layer_id = gimp_layer_copy(original_drawable->id);
  3576.    /* set layer invisible and dummyname and 
  3577.     * add at top of the image while working
  3578.     * (for the case of undo the gimp must know,
  3579.     *  that the layer was part of the image)
  3580.     */
  3581.    gimp_image_add_layer (l_image_id, l_tmp_layer_id, 0);
  3582.    gimp_layer_set_visible(l_tmp_layer_id, FALSE);
  3583.    gimp_layer_set_name(l_tmp_layer_id, "curve_bend_dummylayer");
  3584.     
  3585.    if(gb_debug) printf("p_main_bend  l_tmp_layer_id %d\n", (int)l_tmp_layer_id);   
  3586.    
  3587.    if(cd->rotation != 0.0)
  3588.    {
  3589.       if(gb_debug) printf("p_main_bend rotate: %f\n", (float)cd->rotation);   
  3590.       p_gimp_rotate(l_image_id, l_tmp_layer_id, l_interpolation, cd->rotation);
  3591.    }
  3592.    src_drawable = gimp_drawable_get (l_tmp_layer_id);
  3593.  
  3594.    xmax = ymax = src_drawable->width -1;
  3595.    cd->curve_ptr[OUTLINE_UPPER] = g_malloc(sizeof(gint32) * (1+xmax));
  3596.    cd->curve_ptr[OUTLINE_LOWER] = g_malloc(sizeof(gint32) * (1+xmax));
  3597.  
  3598.    p_bender_calculate_iter_curve(cd, xmax, ymax);
  3599.    bender_init_min_max(cd, xmax);
  3600.    
  3601.    l_dst_height = src_drawable->height 
  3602.                 + p_upper_curve_extend(cd, src_drawable->width, src_drawable->height)
  3603.                 + p_lower_curve_extend(cd, src_drawable->width, src_drawable->height);
  3604.  
  3605.    if(gb_debug) printf("p_main_bend: l_dst_height:%d\n", (int)l_dst_height);   
  3606.  
  3607.    if(work_on_copy)
  3608.    {
  3609.      dst_drawable = p_add_layer(src_drawable->width, l_dst_height, src_drawable);
  3610.      if(gb_debug) printf("p_main_bend: DONE add layer\n");   
  3611.    }
  3612.    else
  3613.    {
  3614.      /* work on the original */
  3615.      gimp_layer_resize(original_drawable->id, 
  3616.                        src_drawable->width,
  3617.                l_dst_height,
  3618.                l_offset_x, l_offset_y);
  3619.      if(gb_debug) printf("p_main_bend: DONE layer resize\n");   
  3620.      if(!gimp_drawable_has_alpha(original_drawable->id))
  3621.      {
  3622.        /* always add alpha channel */
  3623.        gimp_layer_add_alpha(original_drawable->id);
  3624.      }
  3625.      dst_drawable = gimp_drawable_get (original_drawable->id);
  3626.    }
  3627.    p_clear_drawable(dst_drawable);
  3628.  
  3629.    p_init_gdrw(&l_src_gdrw, src_drawable, FALSE, FALSE);
  3630.    p_init_gdrw(&l_dst_gdrw, dst_drawable,  TRUE,  FALSE);
  3631.  
  3632.    p_vertical_bend(cd, &l_src_gdrw, &l_dst_gdrw);
  3633.  
  3634.    if(gb_debug) printf("p_main_bend: DONE vertical bend\n");   
  3635.  
  3636.    p_end_gdrw(&l_src_gdrw);
  3637.    p_end_gdrw(&l_dst_gdrw);
  3638.  
  3639.    if(cd->rotation != 0.0)
  3640.    {
  3641.       p_gimp_rotate(l_image_id, dst_drawable->id, l_interpolation, (gdouble)(360.0 - cd->rotation));
  3642.       
  3643.       /* TODO: here we should crop dst_drawable to cut off full transparent borderpixels */
  3644.       
  3645.    }
  3646.  
  3647.    /* set offsets of the resulting new layer 
  3648.     *(center == center of original_drawable)
  3649.     */
  3650.    l_offset_x = l_center_x - (gimp_drawable_width  (dst_drawable->id) / 2 );
  3651.    l_offset_y = l_center_y - (gimp_drawable_height  (dst_drawable->id) / 2 );
  3652.    gimp_layer_set_offsets (dst_drawable->id, l_offset_x, l_offset_y);
  3653.  
  3654.    /* delete the temp layer */
  3655.    gimp_image_remove_layer(l_image_id, l_tmp_layer_id);
  3656.  
  3657.    g_free(cd->curve_ptr[OUTLINE_UPPER]);
  3658.    g_free(cd->curve_ptr[OUTLINE_LOWER]);
  3659.  
  3660.    if(gb_debug) printf("p_main_bend: DONE bend main\n");   
  3661.  
  3662.    return dst_drawable->id;
  3663. }    /* end p_main_bend */
  3664.