home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / blend.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  43.8 KB  |  1,639 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22.  
  23. #include <gtk/gtk.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "asupsample.h"
  29. #include "blend.h"
  30. #include "cursorutil.h"
  31. #include "draw_core.h"
  32. #include "drawable.h"
  33. #include "errors.h"
  34. #include "fuzzy_select.h"
  35. #include "gdisplay.h"
  36. #include "gimage_mask.h"
  37. #include "gimpdnd.h"
  38. #include "gimpui.h"
  39. #include "gradient.h"
  40. #include "paint_options.h"
  41. #include "selection.h"
  42. #include "tools.h"
  43. #include "undo.h"
  44.  
  45. #include "tile.h"
  46.  
  47. #include "libgimp/gimpcolorspace.h"
  48. #include "libgimp/gimpmath.h"
  49.  
  50. #include "libgimp/gimpintl.h"
  51.  
  52.  
  53. /*  target size  */
  54. #define  TARGET_HEIGHT    15
  55. #define  TARGET_WIDTH     15
  56.  
  57. #define  STATUSBAR_SIZE  128
  58.  
  59. /*  the blend structures  */
  60.  
  61. typedef gdouble (* RepeatFunc) (gdouble);
  62.  
  63. typedef struct _BlendTool BlendTool;
  64.  
  65. struct _BlendTool
  66. {
  67.   DrawCore *core;        /*  Core select object   */
  68.  
  69.   gint      startx;      /*  starting x coord     */
  70.   gint      starty;      /*  starting y coord     */
  71.  
  72.   gint      endx;        /*  ending x coord       */
  73.   gint      endy;        /*  ending y coord       */
  74.   guint     context_id;  /*  for the statusbar    */
  75. };
  76.  
  77. typedef struct _BlendOptions BlendOptions;
  78.  
  79. struct _BlendOptions
  80. {
  81.   PaintOptions  paint_options;
  82.  
  83.   gdouble       offset;
  84.   gdouble       offset_d;
  85.   GtkObject    *offset_w;
  86.  
  87.   BlendMode     blend_mode;
  88.   BlendMode     blend_mode_d;
  89.   GtkWidget    *blend_mode_w;
  90.  
  91.   GradientType  gradient_type;
  92.   GradientType  gradient_type_d;
  93.   GtkWidget    *gradient_type_w;
  94.  
  95.   RepeatMode    repeat;
  96.   RepeatMode    repeat_d;
  97.   GtkWidget    *repeat_w;
  98.  
  99.   gint          supersample;
  100.   gint          supersample_d;
  101.   GtkWidget    *supersample_w;
  102.  
  103.   gint          max_depth;
  104.   gint          max_depth_d;
  105.   GtkObject    *max_depth_w;
  106.  
  107.   gdouble       threshold;
  108.   gdouble       threshold_d;
  109.   GtkObject    *threshold_w;
  110. };
  111.  
  112. typedef struct
  113. {
  114.   gdouble      offset;
  115.   gdouble      sx, sy;
  116.   BlendMode    blend_mode;
  117.   GradientType gradient_type;
  118.   color_t      fg, bg;
  119.   gdouble      dist;
  120.   gdouble      vec[2];
  121.   RepeatFunc   repeat_func;
  122. } RenderBlendData;
  123.  
  124. typedef struct
  125. {
  126.   PixelRegion *PR;
  127.   guchar      *row_data;
  128.   gint         bytes;
  129.   gint         width;
  130. } PutPixelData;
  131.  
  132.  
  133. /*  the blend tool options  */
  134. static BlendOptions *blend_options = NULL;
  135.  
  136. /*  variables for the shapeburst algs  */
  137. static PixelRegion distR =
  138. {
  139.   NULL,  /* data */
  140.   NULL,  /* tiles */
  141.   0,     /* rowstride */
  142.   0, 0,  /* w, h */
  143.   0, 0,  /* x, y */
  144.   4,     /* bytes */
  145.   0      /* process count */
  146. };
  147.  
  148. /*  dnd stuff  */
  149. static GtkTargetEntry blend_target_table[] =
  150. {
  151.   GIMP_TARGET_GRADIENT,  
  152.   GIMP_TARGET_TOOL
  153. };
  154. static guint blend_n_targets = (sizeof (blend_target_table) /
  155.                 sizeof (blend_target_table[0]));
  156.  
  157. /*  local function prototypes  */
  158.  
  159. static void   gradient_type_callback    (GtkWidget *, gpointer);
  160.  
  161. static void   blend_button_press        (Tool *, GdkEventButton *, gpointer);
  162. static void   blend_button_release      (Tool *, GdkEventButton *, gpointer);
  163. static void   blend_motion              (Tool *, GdkEventMotion *, gpointer);
  164. static void   blend_cursor_update       (Tool *, GdkEventMotion *, gpointer);
  165. static void   blend_control             (Tool *, ToolAction,       gpointer);
  166.  
  167. static void   blend_options_drop_gradient  (GtkWidget *, gradient_t *, gpointer);
  168. static void   blend_options_drop_tool      (GtkWidget *, ToolType,     gpointer);
  169.  
  170. static double gradient_calc_conical_sym_factor           (double dist, double *axis, double offset,
  171.                               double x, double y);
  172. static double gradient_calc_conical_asym_factor          (double dist, double *axis, double offset,
  173.                               double x, double y);
  174. static double gradient_calc_square_factor                (double dist, double offset,
  175.                               double x, double y);
  176. static double gradient_calc_radial_factor                (double dist, double offset,
  177.                               double x, double y);
  178. static double gradient_calc_linear_factor                (double dist, double *vec, double offset,
  179.                               double x, double y);
  180. static double gradient_calc_bilinear_factor              (double dist, double *vec, double offset,
  181.                               double x, double y);
  182. static double gradient_calc_spiral_factor                (double dist, double *axis, double offset,
  183.                               double x, double y, gint cwise);
  184. static double gradient_calc_shapeburst_angular_factor    (double x, double y);
  185. static double gradient_calc_shapeburst_spherical_factor  (double x, double y);
  186. static double gradient_calc_shapeburst_dimpled_factor    (double x, double y);
  187.  
  188. static double gradient_repeat_none                       (double val);
  189. static double gradient_repeat_sawtooth                   (double val);
  190. static double gradient_repeat_triangular                 (double val);
  191.  
  192. static void   gradient_precalc_shapeburst                (GImage *gimage, GimpDrawable *drawable, 
  193.                               PixelRegion *PR, double dist);
  194.  
  195. static void   gradient_render_pixel                      (double x, double y, 
  196.                               color_t *color, void *render_data);
  197. static void   gradient_put_pixel                         (int x, int y, 
  198.                               color_t color, void *put_pixel_data);
  199.  
  200. static void   gradient_fill_region          (GImage *gimage, GimpDrawable *drawable, PixelRegion *PR,
  201.                          int width, int height,
  202.                          BlendMode blend_mode, GradientType gradient_type,
  203.                          double offset, RepeatMode repeat,
  204.                          int supersample, int max_depth, double threshold,
  205.                          double sx, double sy, double ex, double ey,
  206.                          progress_func_t progress_callback,
  207.                          void *progress_data);
  208.  
  209.  
  210. /*  functions  */
  211.  
  212. static void
  213. gradient_type_callback (GtkWidget *widget,
  214.             gpointer   data)
  215. {
  216.   gimp_menu_item_update (widget, data);
  217.  
  218.   gtk_widget_set_sensitive (blend_options->repeat_w, 
  219.                 (blend_options->gradient_type < 6));
  220. }
  221.  
  222. static void
  223. blend_options_reset (void)
  224. {
  225.   BlendOptions *options = blend_options;
  226.  
  227.   paint_options_reset ((PaintOptions *) options);
  228.  
  229.   options->blend_mode    = options->blend_mode_d;
  230.   options->gradient_type = options->gradient_type_d;
  231.   options->repeat        = options->repeat_d;
  232.  
  233.   gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->blend_mode_w),
  234.                    blend_options->blend_mode_d);
  235.   gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w),
  236.                    blend_options->gradient_type_d);
  237.   gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->repeat_w),
  238.                    blend_options->repeat_d);
  239.  
  240.   gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->offset_w),
  241.                 blend_options->offset_d);
  242.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (blend_options->supersample_w),
  243.                 blend_options->supersample_d);
  244.   gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->max_depth_w),
  245.                 blend_options->max_depth_d);
  246.   gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->threshold_w),
  247.                 blend_options->threshold_d);
  248. }
  249.  
  250. static BlendOptions *
  251. blend_options_new (void)
  252. {
  253.   BlendOptions *options;
  254.  
  255.   GtkWidget *vbox;
  256.   GtkWidget *table;
  257.   GtkWidget *scale;
  258.   GtkWidget *frame;
  259.  
  260.   /*  the new blend tool options structure  */
  261.   options = g_new (BlendOptions, 1);
  262.   paint_options_init ((PaintOptions *) options,
  263.               BLEND,
  264.               blend_options_reset);
  265.   options->offset       = options->offset_d          = 0.0;
  266.   options->blend_mode      = options->blend_mode_d    = FG_BG_RGB_MODE;
  267.   options->gradient_type = options->gradient_type_d = LINEAR;
  268.   options->repeat        = options->repeat_d        = REPEAT_NONE;
  269.   options->supersample   = options->supersample_d   = FALSE;
  270.   options->max_depth     = options->max_depth_d     = 3;
  271.   options->threshold     = options->threshold_d     = 0.2;
  272.  
  273.   /*  the main vbox  */
  274.   vbox = ((ToolOptions *) options)->main_vbox;
  275.  
  276.   /*  dnd stuff  */
  277.   gtk_drag_dest_set (vbox,
  278.              GTK_DEST_DEFAULT_HIGHLIGHT |
  279.              GTK_DEST_DEFAULT_MOTION |
  280.              GTK_DEST_DEFAULT_DROP,
  281.              blend_target_table, blend_n_targets,
  282.              GDK_ACTION_COPY); 
  283.   gimp_dnd_gradient_dest_set (vbox, blend_options_drop_gradient, NULL);
  284.   gimp_dnd_tool_dest_set (vbox, blend_options_drop_tool, NULL);
  285.  
  286.   /*  the offset scale  */
  287.   table = gtk_table_new (4, 2, FALSE);
  288.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  289.   gtk_table_set_row_spacings (GTK_TABLE (table), 1);
  290.   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
  291.   gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
  292.  
  293.   options->offset_w =
  294.     gtk_adjustment_new (options->offset_d, 0.0, 100.0, 1.0, 1.0, 0.0);
  295.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->offset_w));
  296.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  297.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  298.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  299.                  _("Offset:"), 1.0, 1.0,
  300.                  scale, 1, FALSE);
  301.   gtk_signal_connect (GTK_OBJECT (options->offset_w), "value_changed",
  302.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  303.               &options->offset);
  304.  
  305.   /*  the blend mode menu  */
  306.   options->blend_mode_w = gimp_option_menu_new2
  307.     (FALSE, gimp_menu_item_update,
  308.      &options->blend_mode, (gpointer) options->blend_mode_d,
  309.  
  310.      _("FG to BG (RGB)"),     (gpointer) FG_BG_RGB_MODE, NULL,
  311.      _("FG to BG (HSV)"),     (gpointer) FG_BG_HSV_MODE, NULL,
  312.      _("FG to Transparent"),  (gpointer) FG_TRANS_MODE, NULL,
  313.      _("Custom Gradient"),    (gpointer) CUSTOM_MODE, NULL,
  314.  
  315.      NULL);
  316.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  317.                  _("Blend:"), 1.0, 0.5,
  318.                  options->blend_mode_w, 1, TRUE);
  319.  
  320.   /*  the gradient type menu  */
  321.   options->gradient_type_w = gimp_option_menu_new2
  322.     (FALSE, gradient_type_callback,
  323.      &options->gradient_type, (gpointer) options->gradient_type_d,
  324.  
  325.      _("Linear"),                 (gpointer) LINEAR, NULL,
  326.      _("Bi-Linear"),              (gpointer) BILINEAR, NULL,
  327.      _("Radial"),                 (gpointer) RADIAL, NULL,
  328.      _("Square"),                 (gpointer) SQUARE, NULL,
  329.      _("Conical (symmetric)"),    (gpointer) CONICAL_SYMMETRIC, NULL,
  330.      _("Conical (asymmetric)"),   (gpointer) CONICAL_ASYMMETRIC, NULL,
  331.      _("Shapeburst (angular)"),   (gpointer) SHAPEBURST_ANGULAR, NULL,
  332.      _("Shapeburst (spherical)"), (gpointer) SHAPEBURST_SPHERICAL, NULL,
  333.      _("Shapeburst (dimpled)"),   (gpointer) SHAPEBURST_DIMPLED, NULL,
  334.      _("Spiral (clockwise)"),     (gpointer) SPIRAL_CLOCKWISE, NULL,
  335.      _("Spiral (anticlockwise)"), (gpointer) SPIRAL_ANTICLOCKWISE, NULL,
  336.  
  337.      NULL);
  338.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  339.                  _("Gradient:"), 1.0, 0.5,
  340.                  options->gradient_type_w, 1, TRUE);
  341.  
  342.   /*  the repeat option  */
  343.   options->repeat_w = gimp_option_menu_new2
  344.     (FALSE, gimp_menu_item_update,
  345.      &options->repeat, (gpointer) options->repeat_d,
  346.  
  347.      _("None"),            (gpointer) REPEAT_NONE, NULL,
  348.      _("Sawtooth Wave"),   (gpointer) REPEAT_SAWTOOTH, NULL,
  349.      _("Triangular Wave"), (gpointer) REPEAT_TRIANGULAR, NULL,
  350.  
  351.      NULL);
  352.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  353.                  _("Repeat:"), 1.0, 0.5,
  354.                  options->repeat_w, 1, TRUE);
  355.  
  356.   /*  show the table  */
  357.   gtk_widget_show (table);
  358.  
  359.   /*  frame for supersampling options  */
  360.   frame = gtk_frame_new (NULL);
  361.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  362.   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
  363.   gtk_widget_show (frame);
  364.  
  365.   /* vbox for the supersampling stuff */
  366.   vbox = gtk_vbox_new (FALSE, 0);
  367.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  368.   gtk_widget_show (vbox);
  369.  
  370.   /*  supersampling toggle  */
  371.   options->supersample_w =
  372.     gtk_check_button_new_with_label (_("Adaptive Supersampling"));
  373.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->supersample_w),
  374.                 options->supersample_d);
  375.   gtk_signal_connect (GTK_OBJECT (options->supersample_w), "toggled",
  376.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  377.               &options->supersample);
  378.   gtk_box_pack_start (GTK_BOX (vbox), options->supersample_w, FALSE, FALSE, 0);
  379.   gtk_widget_show (options->supersample_w);
  380.  
  381.   /*  table for supersampling options  */
  382.   table = gtk_table_new (2, 2, FALSE);
  383.   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  384.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  385.   gtk_table_set_row_spacings (GTK_TABLE (table), 1);
  386.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  387.  
  388.   /*  automatically set the sensitive state of the table  */
  389.   gtk_widget_set_sensitive (table, options->supersample_d);
  390.   gtk_object_set_data (GTK_OBJECT (options->supersample_w), "set_sensitive",
  391.                table);
  392.  
  393.   /*  max depth scale  */
  394.   options->max_depth_w =
  395.     gtk_adjustment_new (options->max_depth_d, 1.0, 10.0, 1.0, 1.0, 1.0);
  396.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->max_depth_w));
  397.   gtk_scale_set_digits (GTK_SCALE (scale), 0);
  398.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  399.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  400.                  _("Max Depth:"), 1.0, 1.0,
  401.                  scale, 1, FALSE);
  402.   gtk_signal_connect (GTK_OBJECT(options->max_depth_w), "value_changed",
  403.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  404.               &options->max_depth);
  405.  
  406.   /*  threshold scale  */
  407.   options->threshold_w =
  408.     gtk_adjustment_new (options->threshold_d, 0.0, 4.0, 0.01, 0.01, 0.0);
  409.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w));
  410.   gtk_scale_set_digits (GTK_SCALE (scale), 2);
  411.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  412.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  413.                  _("Threshold:"), 1.0, 1.0,
  414.                  scale, 1, FALSE);
  415.   gtk_signal_connect (GTK_OBJECT(options->threshold_w), "value_changed",
  416.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  417.               &options->threshold);
  418.  
  419.   /*  show the table  */
  420.   gtk_widget_show (table);
  421.  
  422.   return options;
  423. }
  424.  
  425.  
  426. static void
  427. blend_button_press (Tool           *tool,
  428.             GdkEventButton *bevent,
  429.             gpointer        gdisp_ptr)
  430. {
  431.   GDisplay * gdisp;
  432.   BlendTool * blend_tool;
  433.  
  434.   gdisp = (GDisplay *) gdisp_ptr;
  435.   blend_tool = (BlendTool *) tool->private;
  436.  
  437.   switch (drawable_type (gimage_active_drawable (gdisp->gimage)))
  438.     {
  439.     case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
  440.       g_message (_("Blend: Invalid for indexed images."));
  441.       return;
  442.  
  443.       break;
  444.     default:
  445.       break;
  446.     }
  447.  
  448.   /*  Keep the coordinates of the target  */
  449.   gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
  450.                    &blend_tool->startx, &blend_tool->starty, FALSE, 1);
  451.  
  452.   blend_tool->endx = blend_tool->startx;
  453.   blend_tool->endy = blend_tool->starty;
  454.  
  455.   /*  Make the tool active and set the gdisplay which owns it  */
  456.   gdk_pointer_grab (gdisp->canvas->window, FALSE,
  457.             GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
  458.             NULL, NULL, bevent->time);
  459.  
  460.   tool->gdisp_ptr = gdisp_ptr;
  461.   tool->state = ACTIVE;
  462.  
  463.   /* initialize the statusbar display */
  464.   blend_tool->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "blend");
  465.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id, _("Blend: 0, 0"));
  466.  
  467.   /*  Start drawing the blend tool  */
  468.   draw_core_start (blend_tool->core, gdisp->canvas->window, tool);
  469. }
  470.  
  471. static void
  472. blend_button_release (Tool           *tool,
  473.               GdkEventButton *bevent,
  474.               gpointer        gdisp_ptr)
  475. {
  476.   GDisplay * gdisp;
  477.   GImage * gimage;
  478.   BlendTool * blend_tool;
  479. #ifdef BLEND_UI_CALLS_VIA_PDB
  480.   Argument *return_vals;
  481.   int nreturn_vals;
  482. #else
  483.   gimp_progress *progress;
  484. #endif
  485.  
  486.   gdisp = (GDisplay *) gdisp_ptr;
  487.   gimage = gdisp->gimage;
  488.   blend_tool = (BlendTool *) tool->private;
  489.  
  490.   gdk_pointer_ungrab (bevent->time);
  491.   gdk_flush ();
  492.  
  493.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id);
  494.  
  495.   draw_core_stop (blend_tool->core, tool);
  496.   tool->state = INACTIVE;
  497.  
  498.   /*  if the 3rd button isn't pressed, fill the selected region  */
  499.   if (! (bevent->state & GDK_BUTTON3_MASK) &&
  500.       ((blend_tool->startx != blend_tool->endx) ||
  501.        (blend_tool->starty != blend_tool->endy)))
  502.     {
  503.       /* we can't do callbacks easily with the PDB, so this UI/backend
  504.        * separation (though good) is ignored for the moment */
  505. #ifdef BLEND_UI_CALLS_VIA_PDB
  506.       return_vals = 
  507.     procedural_db_run_proc ("gimp_blend",
  508.                 &nreturn_vals,
  509.                 PDB_DRAWABLE, drawable_ID (gimage_active_drawable (gimage)),
  510.                 PDB_INT32, (gint32) blend_options->blend_mode,
  511.                 PDB_INT32, (gint32) PAINT_OPTIONS_GET_PAINT_MODE (blend_options),
  512.                 PDB_INT32, (gint32) blend_options->gradient_type,
  513.                 PDB_FLOAT, (gdouble) PAINT_OPTIONS_GET_OPACITY (blend_options) * 100,
  514.                 PDB_FLOAT, (gdouble) blend_options->offset,
  515.                 PDB_INT32, (gint32) blend_options->repeat,
  516.                 PDB_INT32, (gint32) blend_options->supersample,
  517.                 PDB_INT32, (gint32) blend_options->max_depth,
  518.                 PDB_FLOAT, (gdouble) blend_options->threshold,
  519.                 PDB_FLOAT, (gdouble) blend_tool->startx,
  520.                 PDB_FLOAT, (gdouble) blend_tool->starty,
  521.                 PDB_FLOAT, (gdouble) blend_tool->endx,
  522.                 PDB_FLOAT, (gdouble) blend_tool->endy,
  523.                 PDB_END);
  524.  
  525.       if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS)
  526.     gdisplays_flush ();
  527.       else
  528.     g_message (_("Blend operation failed."));
  529.  
  530.       procedural_db_destroy_args (return_vals, nreturn_vals);
  531.  
  532. #else /* ! BLEND_UI_CALLS_VIA_PDB */
  533.  
  534.       progress = progress_start (gdisp, _("Blending..."), FALSE, NULL, NULL);
  535.  
  536.       blend (gimage,
  537.          gimage_active_drawable (gimage),
  538.          blend_options->blend_mode,
  539.          gimp_context_get_paint_mode (NULL),
  540.          blend_options->gradient_type,
  541.          gimp_context_get_opacity (NULL) * 100,
  542.          blend_options->offset,
  543.          blend_options->repeat,
  544.          blend_options->supersample,
  545.          blend_options->max_depth,
  546.          blend_options->threshold,
  547.          blend_tool->startx,
  548.          blend_tool->starty,
  549.          blend_tool->endx,
  550.          blend_tool->endy,
  551.          progress ? progress_update_and_flush : (progress_func_t)NULL, 
  552.          progress);
  553.  
  554.       if (progress)
  555.     progress_end (progress);
  556.  
  557.       gdisplays_flush ();
  558. #endif /* ! BLEND_UI_CALLS_VIA_PDB */
  559.     }
  560. }
  561.  
  562. static void
  563. blend_motion (Tool           *tool,
  564.           GdkEventMotion *mevent,
  565.           gpointer        gdisp_ptr)
  566. {
  567.   GDisplay * gdisp;
  568.   BlendTool * blend_tool;
  569.   gchar vector[STATUSBAR_SIZE];
  570.  
  571.   gdisp = (GDisplay *) gdisp_ptr;
  572.   blend_tool = (BlendTool *) tool->private;
  573.  
  574.   /*  undraw the current tool  */
  575.   draw_core_pause (blend_tool->core, tool);
  576.  
  577.   /*  Get the current coordinates  */
  578.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
  579.                    &blend_tool->endx, &blend_tool->endy, FALSE, 1);
  580.  
  581.  
  582.   /* Restrict to multiples of 15 degrees if ctrl is pressed */
  583.   if (mevent->state & GDK_CONTROL_MASK)
  584.     {
  585.       int tangens2[6] = {  34, 106, 196, 334, 618, 1944 };
  586.       int cosinus[7]  = { 256, 247, 222, 181, 128, 66, 0 };
  587.       int dx, dy, i, radius, frac;
  588.  
  589.       dx = blend_tool->endx - blend_tool->startx;
  590.       dy = blend_tool->endy - blend_tool->starty;
  591.  
  592.       if (dy)
  593.     {
  594.       radius = sqrt (SQR (dx) + SQR (dy));
  595.       frac = abs ((dx << 8) / dy);
  596.       for (i = 0; i < 6; i++)
  597.         {
  598.           if (frac < tangens2[i])
  599.         break;  
  600.         }
  601.       dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8);
  602.       dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8);
  603.     }
  604.       blend_tool->endx = blend_tool->startx + dx;
  605.       blend_tool->endy = blend_tool->starty + dy;
  606.     }
  607.  
  608.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id);
  609.   if (gdisp->dot_for_dot)
  610.     {
  611.       g_snprintf (vector, sizeof (vector), gdisp->cursor_format_str,
  612.           _("Blend: "),
  613.           blend_tool->endx - blend_tool->startx,
  614.           ", ",
  615.           blend_tool->endy - blend_tool->starty);
  616.     }
  617.   else /* show real world units */
  618.     {
  619.       gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
  620.  
  621.       g_snprintf (vector, sizeof (vector), gdisp->cursor_format_str,
  622.           _("Blend: "),
  623.           blend_tool->endx - blend_tool->startx * unit_factor /
  624.           gdisp->gimage->xresolution,
  625.           ", ",
  626.           blend_tool->endy - blend_tool->starty * unit_factor /
  627.           gdisp->gimage->yresolution);
  628.     }
  629.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id,
  630.               vector);
  631.  
  632.   /*  redraw the current tool  */
  633.   draw_core_resume (blend_tool->core, tool);
  634. }
  635.  
  636. static void
  637. blend_cursor_update (Tool           *tool,
  638.              GdkEventMotion *mevent,
  639.              gpointer        gdisp_ptr)
  640. {
  641.   GDisplay * gdisp;
  642.  
  643.   gdisp = (GDisplay *) gdisp_ptr;
  644.  
  645.   switch (drawable_type (gimage_active_drawable (gdisp->gimage)))
  646.     {
  647.     case INDEXED_GIMAGE:
  648.     case INDEXEDA_GIMAGE:
  649.       gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
  650.                     BLEND,
  651.                     CURSOR_MODIFIER_NONE,
  652.                     FALSE);
  653.       break;
  654.     default:
  655.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  656.                     BLEND,
  657.                     CURSOR_MODIFIER_NONE,
  658.                     FALSE);
  659.       break;
  660.     }
  661. }
  662.  
  663. static void
  664. blend_draw (Tool *tool)
  665. {
  666.   GDisplay * gdisp;
  667.   BlendTool * blend_tool;
  668.   int tx1, ty1, tx2, ty2;
  669.  
  670.   gdisp = (GDisplay *) tool->gdisp_ptr;
  671.   blend_tool = (BlendTool *) tool->private;
  672.  
  673.   gdisplay_transform_coords (gdisp, blend_tool->startx, blend_tool->starty,
  674.                  &tx1, &ty1, 1);
  675.   gdisplay_transform_coords (gdisp, blend_tool->endx, blend_tool->endy,
  676.                  &tx2, &ty2, 1);
  677.  
  678.   /*  Draw start target  */
  679.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  680.          tx1 - (TARGET_WIDTH >> 1), ty1,
  681.          tx1 + (TARGET_WIDTH >> 1), ty1);
  682.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  683.          tx1, ty1 - (TARGET_HEIGHT >> 1),
  684.          tx1, ty1 + (TARGET_HEIGHT >> 1));
  685.  
  686.   /*  Draw end target  */
  687.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  688.          tx2 - (TARGET_WIDTH >> 1), ty2,
  689.          tx2 + (TARGET_WIDTH >> 1), ty2);
  690.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  691.          tx2, ty2 - (TARGET_HEIGHT >> 1),
  692.          tx2, ty2 + (TARGET_HEIGHT >> 1));
  693.  
  694.   /*  Draw the line between the start and end coords  */
  695.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  696.          tx1, ty1, tx2, ty2);
  697. }
  698.  
  699. static void
  700. blend_control (Tool       *tool,
  701.            ToolAction  action,
  702.            gpointer    gdisp_ptr)
  703. {
  704.   BlendTool * blend_tool;
  705.  
  706.   blend_tool = (BlendTool *) tool->private;
  707.  
  708.   switch (action)
  709.     {
  710.     case PAUSE:
  711.       draw_core_pause (blend_tool->core, tool);
  712.       break;
  713.  
  714.     case RESUME:
  715.       draw_core_resume (blend_tool->core, tool);
  716.       break;
  717.  
  718.     case HALT:
  719.       draw_core_stop (blend_tool->core, tool);
  720.       break;
  721.  
  722.     default:
  723.       break;
  724.     }
  725. }
  726.  
  727.  
  728. static void
  729. blend_options_drop_gradient (GtkWidget  *widget,
  730.                  gradient_t *gradient,
  731.                  gpointer    data)
  732. {
  733.   gimp_context_set_gradient (gimp_context_get_user (), gradient);
  734.   gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->blend_mode_w), 
  735.                    CUSTOM_MODE);
  736.   blend_options->blend_mode = CUSTOM_MODE;
  737. }
  738.  
  739. static void
  740. blend_options_drop_tool (GtkWidget *widget,
  741.              ToolType   tool,
  742.              gpointer   data)
  743. {
  744.   gimp_context_set_tool (gimp_context_get_user (), tool);
  745. }
  746.  
  747.  
  748. /*****/
  749.  
  750. /*  The actual blending procedure  */
  751. void
  752. blend (GImage          *gimage,
  753.        GimpDrawable    *drawable,
  754.        BlendMode        blend_mode,
  755.        int              paint_mode,
  756.        GradientType     gradient_type,
  757.        double           opacity,
  758.        double           offset,
  759.        RepeatMode       repeat,
  760.        int              supersample,
  761.        int              max_depth,
  762.        double           threshold,
  763.        double           startx,
  764.        double           starty,
  765.        double           endx,
  766.        double           endy,
  767.        progress_func_t  progress_callback,
  768.        void            *progress_data)
  769. {
  770.   TileManager *buf_tiles;
  771.   PixelRegion bufPR;
  772.   int has_alpha;
  773.   int has_selection;
  774.   int bytes;
  775.   int x1, y1, x2, y2;
  776.  
  777.   gimp_add_busy_cursors();
  778.  
  779.   has_selection = drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  780.  
  781.   has_alpha = drawable_has_alpha (drawable);
  782.   bytes = drawable_bytes (drawable);
  783.  
  784.   /*  Always create an alpha temp buf (for generality) */
  785.   if (! has_alpha)
  786.     {
  787.       has_alpha = TRUE;
  788.       bytes += 1;
  789.     }
  790.  
  791.   buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
  792.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  793.  
  794.   gradient_fill_region (gimage, drawable,
  795.               &bufPR, (x2 - x1), (y2 - y1),
  796.             blend_mode, gradient_type, offset, repeat,
  797.             supersample, max_depth, threshold,
  798.             (startx - x1), (starty - y1),
  799.             (endx - x1), (endy - y1),
  800.             progress_callback, progress_data);
  801.  
  802.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
  803.   gimage_apply_image (gimage, drawable, &bufPR, TRUE,
  804.               (opacity * 255) / 100, paint_mode, NULL, x1, y1);
  805.  
  806.   /*  update the image  */
  807.   drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
  808.  
  809.   /*  free the temporary buffer  */
  810.   tile_manager_destroy (buf_tiles);
  811.  
  812.   gimp_remove_busy_cursors(NULL);
  813. }
  814.  
  815.  
  816. static double
  817. gradient_calc_conical_sym_factor (double  dist,
  818.                   double *axis,
  819.                   double  offset,
  820.                   double  x,
  821.                   double  y)
  822. {
  823.   double vec[2];
  824.   double r;
  825.   double rat;
  826.  
  827.   if (dist == 0.0)
  828.     rat = 0.0;
  829.   else
  830.     if ((x != 0) || (y != 0))
  831.       {
  832.     /* Calculate offset from the start in pixels */
  833.  
  834.     r = sqrt(x * x + y * y);
  835.  
  836.     vec[0] = x / r;
  837.     vec[1] = y / r;
  838.  
  839.     rat = axis[0] * vec[0] + axis[1] * vec[1]; /* Dot product */
  840.  
  841.     if (rat > 1.0)
  842.       rat = 1.0;
  843.     else if (rat < -1.0)
  844.       rat = -1.0;
  845.  
  846.     /* This cool idea is courtesy Josh MacDonald,
  847.      * Ali Rahimi --- two more XCF losers.  */
  848.  
  849.     rat = acos(rat) / G_PI;
  850.     rat = pow(rat, (offset / 10) + 1);
  851.  
  852.     rat = CLAMP(rat, 0.0, 1.0);
  853.       }
  854.     else
  855.       rat = 0.5;
  856.  
  857.   return rat;
  858. } /* gradient_calc_conical_sym_factor */
  859.  
  860.  
  861. /*****/
  862.  
  863. static double
  864. gradient_calc_conical_asym_factor (double  dist,
  865.                    double *axis,
  866.                    double  offset,
  867.                    double  x,
  868.                    double  y)
  869. {
  870.   double ang0, ang1;
  871.   double ang;
  872.   double rat;
  873.  
  874.   if (dist == 0.0)
  875.     rat = 0.0;
  876.   else
  877.     {
  878.       if ((x != 0) || (y != 0))
  879.     {
  880.       ang0 = atan2(axis[0], axis[1]) + G_PI;
  881.       ang1 = atan2(x, y) + G_PI;
  882.  
  883.       ang = ang1 - ang0;
  884.  
  885.       if (ang < 0.0)
  886.         ang += (2.0 * G_PI);
  887.  
  888.       rat = ang / (2.0 * G_PI);
  889.       rat = pow(rat, (offset / 10) + 1);
  890.  
  891.       rat = CLAMP(rat, 0.0, 1.0);
  892.     }
  893.       else
  894.     rat = 0.5; /* We are on middle point */
  895.     } /* else */
  896.  
  897.   return rat;
  898. } /* gradient_calc_conical_asym_factor */
  899.  
  900.  
  901. /*****/
  902.  
  903. static double
  904. gradient_calc_square_factor (double dist,
  905.                  double offset,
  906.                  double x,
  907.                  double y)
  908. {
  909.   double r;
  910.   double rat;
  911.  
  912.   if (dist == 0.0)
  913.     rat = 0.0;
  914.   else
  915.     {
  916.       /* Calculate offset from start as a value in [0, 1] */
  917.  
  918.       offset = offset / 100.0;
  919.  
  920.       r   = MAX (abs (x), abs (y));
  921.       rat = r / dist;
  922.  
  923.       if (rat < offset)
  924.     rat = 0.0;
  925.       else if (offset == 1)
  926.         rat = (rat>=1) ? 1 : 0;
  927.       else
  928.     rat = (rat - offset) / (1.0 - offset);
  929.     } /* else */
  930.  
  931.   return rat;
  932. } /* gradient_calc_square_factor */
  933.  
  934.  
  935. /*****/
  936.  
  937. static double
  938. gradient_calc_radial_factor (double dist,
  939.                  double offset,
  940.                  double x,
  941.                  double y)
  942. {
  943.   double r;
  944.   double rat;
  945.  
  946.   if (dist == 0.0)
  947.     rat = 0.0;
  948.   else
  949.     {
  950.       /* Calculate radial offset from start as a value in [0, 1] */
  951.  
  952.       offset = offset / 100.0;
  953.  
  954.       r   = sqrt(SQR(x) + SQR(y));
  955.       rat = r / dist;
  956.  
  957.       if (rat < offset)
  958.     rat = 0.0;
  959.       else if (offset == 1)
  960.         rat = (rat>=1) ? 1 : 0;
  961.       else
  962.     rat = (rat - offset) / (1.0 - offset);
  963.     } /* else */
  964.  
  965.   return rat;
  966. } /* gradient_calc_radial_factor */
  967.  
  968.  
  969. /*****/
  970.  
  971. static double
  972. gradient_calc_linear_factor (double  dist,
  973.                  double *vec,
  974.                  double  offset,
  975.                  double  x,
  976.                  double  y)
  977. {
  978.   double r;
  979.   double rat;
  980.  
  981.   if (dist == 0.0)
  982.     rat = 0.0;
  983.   else
  984.     {
  985.       offset = offset / 100.0;
  986.  
  987.       r   = vec[0] * x + vec[1] * y;
  988.       rat = r / dist;
  989.  
  990.       if (rat < offset)
  991.     rat = 0.0;
  992.       else if (offset == 1)
  993.         rat = (rat>=1) ? 1 : 0;
  994.       else
  995.     rat = (rat - offset) / (1.0 - offset);
  996.     } /* else */
  997.  
  998.   return rat;
  999. } /* gradient_calc_linear_factor */
  1000.  
  1001.  
  1002. /*****/
  1003.  
  1004. static double
  1005. gradient_calc_bilinear_factor (double  dist,
  1006.                    double *vec,
  1007.                    double  offset,
  1008.                    double  x,
  1009.                    double  y)
  1010. {
  1011.   double r;
  1012.   double rat;
  1013.  
  1014.   if (dist == 0.0)
  1015.     rat = 0.0;
  1016.   else
  1017.     {
  1018.       /* Calculate linear offset from the start line outward */
  1019.  
  1020.       offset = offset / 100.0;
  1021.  
  1022.       r   = vec[0] * x + vec[1] * y;
  1023.       rat = r / dist;
  1024.  
  1025.       if (fabs(rat) < offset)
  1026.     rat = 0.0;
  1027.       else if (offset == 1)
  1028.         rat = (rat>=1) ? 1 : 0;
  1029.       else
  1030.     rat = (fabs(rat) - offset) / (1.0 - offset);
  1031.     } /* else */
  1032.  
  1033.   return rat;
  1034. } /* gradient_calc_bilinear_factor */
  1035.  
  1036. static double
  1037. gradient_calc_spiral_factor (double  dist,
  1038.                  double *axis,
  1039.                  double  offset,
  1040.                  double  x,
  1041.                  double  y,
  1042.                  gint    cwise)
  1043. {
  1044.   double ang0, ang1;
  1045.   double ang, r;
  1046.   double rat;
  1047.  
  1048.   if (dist == 0.0)
  1049.     rat = 0.0;
  1050.   else
  1051.     {
  1052.       if (x != 0.0 || y != 0.0)
  1053.     {
  1054.       ang0 = atan2 (axis[0], axis[1]) + G_PI;
  1055.       ang1 = atan2 (x, y) + G_PI;
  1056.       if(!cwise)
  1057.         ang = ang0 - ang1;
  1058.       else
  1059.         ang = ang1 - ang0;
  1060.  
  1061.       if (ang < 0.0)
  1062.         ang += (2.0 * G_PI);
  1063.  
  1064.       r = sqrt (x * x + y * y) / dist;
  1065.       rat = ang / (2.0 * G_PI) + r + offset;
  1066.       rat = fmod (rat, 1.0);
  1067.     }
  1068.       else
  1069.     rat = 0.5 ; /* We are on the middle point */
  1070.     }
  1071.  
  1072.   return rat;
  1073. }
  1074.  
  1075. static double
  1076. gradient_calc_shapeburst_angular_factor (double x,
  1077.                      double y)
  1078. {
  1079.   int ix, iy;
  1080.   Tile *tile;
  1081.   float value;
  1082.  
  1083.   ix = (int) CLAMP (x, 0, distR.w);
  1084.   iy = (int) CLAMP (y, 0, distR.h);
  1085.   tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE);
  1086.   value = 1.0 - *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT));
  1087.   tile_release (tile, FALSE);
  1088.  
  1089.   return value;
  1090. }
  1091.  
  1092.  
  1093. static double
  1094. gradient_calc_shapeburst_spherical_factor (double x,
  1095.                        double y)
  1096. {
  1097.   int ix, iy;
  1098.   Tile *tile;
  1099.   float value;
  1100.  
  1101.   ix = (int) CLAMP (x, 0, distR.w);
  1102.   iy = (int) CLAMP (y, 0, distR.h);
  1103.   tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE);
  1104.   value = *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT));
  1105.   value = 1.0 - sin (0.5 * G_PI * value);
  1106.   tile_release (tile, FALSE);
  1107.  
  1108.   return value;
  1109. }
  1110.  
  1111.  
  1112. static double
  1113. gradient_calc_shapeburst_dimpled_factor (double x,
  1114.                      double y)
  1115. {
  1116.   int ix, iy;
  1117.   Tile *tile;
  1118.   float value;
  1119.  
  1120.   ix = (int) CLAMP (x, 0, distR.w);
  1121.   iy = (int) CLAMP (y, 0, distR.h);
  1122.   tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE);
  1123.   value = *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT));
  1124.   value = cos (0.5 * G_PI * value);
  1125.   tile_release (tile, FALSE);
  1126.  
  1127.   return value;
  1128. }
  1129.  
  1130. static double
  1131. gradient_repeat_none (double val)
  1132. {
  1133.   return CLAMP(val, 0.0, 1.0);
  1134. }
  1135.  
  1136. static double
  1137. gradient_repeat_sawtooth (double val)
  1138. {
  1139.   if (val >= 0.0)
  1140.     return fmod(val, 1.0);
  1141.   else
  1142.     return 1.0 - fmod(-val, 1.0);
  1143. }
  1144.  
  1145. static double
  1146. gradient_repeat_triangular (double val)
  1147. {
  1148.   int ival;
  1149.  
  1150.   if (val < 0.0)
  1151.     val = -val;
  1152.  
  1153.   ival = (int) val;
  1154.  
  1155.   if (ival & 1)
  1156.     return 1.0 - fmod(val, 1.0);
  1157.   else
  1158.     return fmod(val, 1.0);
  1159. }
  1160.  
  1161. /*****/
  1162. static void
  1163. gradient_precalc_shapeburst (GImage       *gimage,
  1164.                  GimpDrawable *drawable,
  1165.                  PixelRegion  *PR,
  1166.                  double        dist)
  1167. {
  1168.   Channel *mask;
  1169.   PixelRegion tempR;
  1170.   float max_iteration;
  1171.   float *distp;
  1172.   int size;
  1173.   void * pr;
  1174.   unsigned char white[1] = { OPAQUE_OPACITY };
  1175.  
  1176.   /*  allocate the distance map  */
  1177.   if (distR.tiles)
  1178.     tile_manager_destroy (distR.tiles);
  1179.   distR.tiles = tile_manager_new (PR->w, PR->h, sizeof (float));
  1180.  
  1181.   /*  allocate the selection mask copy  */
  1182.   tempR.tiles = tile_manager_new (PR->w, PR->h, 1);
  1183.   pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1184.  
  1185.   /*  If the gimage mask is not empty, use it as the shape burst source  */
  1186.   if (! gimage_mask_is_empty (gimage))
  1187.     {
  1188.       PixelRegion maskR;
  1189.       int x1, y1, x2, y2;
  1190.       int offx, offy;
  1191.  
  1192.       drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  1193.       drawable_offsets (drawable, &offx, &offy);
  1194.  
  1195.       /*  the selection mask  */
  1196.       mask = gimage_get_mask (gimage);
  1197.       pixel_region_init (&maskR, drawable_data (GIMP_DRAWABLE(mask)), 
  1198.              x1 + offx, y1 + offy, (x2 - x1), (y2 - y1), FALSE);
  1199.  
  1200.       /*  copy the mask to the temp mask  */
  1201.       copy_region (&maskR, &tempR);
  1202.     }
  1203.   /*  otherwise...  */
  1204.   else
  1205.     {
  1206.       /*  If the intended drawable has an alpha channel, use that  */
  1207.       if (drawable_has_alpha (drawable))
  1208.     {
  1209.       PixelRegion drawableR;
  1210.  
  1211.       pixel_region_init (&drawableR, drawable_data (drawable), PR->x, PR->y, PR->w, PR->h, FALSE);
  1212.  
  1213.       extract_alpha_region (&drawableR, NULL, &tempR);
  1214.     }
  1215.       /*  Otherwise, just fill the shapeburst to white  */
  1216.       else
  1217.     color_region (&tempR, white);
  1218.     }
  1219.  
  1220.   pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1221.   pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1222.   max_iteration = shapeburst_region (&tempR, &distR);
  1223.  
  1224.   /*  normalize the shapeburst with the max iteration  */
  1225.   if (max_iteration > 0)
  1226.     {
  1227.       pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1228.  
  1229.       for (pr = pixel_regions_register (1, &distR); pr != NULL; pr = pixel_regions_process (pr))
  1230.     {
  1231.       distp = (float *) distR.data;
  1232.       size = distR.w * distR.h;
  1233.  
  1234.       while (size--)
  1235.         *distp++ /= max_iteration;
  1236.     }
  1237.  
  1238.       pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, FALSE);
  1239.     }
  1240.  
  1241.   tile_manager_destroy (tempR.tiles);
  1242. }
  1243.  
  1244.  
  1245. static void
  1246. gradient_render_pixel (double   x, 
  1247.                double   y, 
  1248.                color_t *color, 
  1249.                void    *render_data)
  1250. {
  1251.   RenderBlendData *rbd;
  1252.   double           factor;
  1253.  
  1254.   rbd = render_data;
  1255.  
  1256.   /* Calculate blending factor */
  1257.  
  1258.   switch (rbd->gradient_type)
  1259.     {
  1260.     case RADIAL:
  1261.       factor = gradient_calc_radial_factor (rbd->dist, rbd->offset,
  1262.                         x - rbd->sx, y - rbd->sy);
  1263.       break;
  1264.  
  1265.     case CONICAL_SYMMETRIC:
  1266.       factor = gradient_calc_conical_sym_factor (rbd->dist, rbd->vec, rbd->offset,
  1267.                          x - rbd->sx, y - rbd->sy);
  1268.       break;
  1269.  
  1270.     case CONICAL_ASYMMETRIC:
  1271.       factor = gradient_calc_conical_asym_factor (rbd->dist, rbd->vec, rbd->offset,
  1272.                           x - rbd->sx, y - rbd->sy);
  1273.       break;
  1274.  
  1275.     case SQUARE:
  1276.       factor = gradient_calc_square_factor (rbd->dist, rbd->offset,
  1277.                         x - rbd->sx, y - rbd->sy);
  1278.       break;
  1279.  
  1280.     case LINEAR:
  1281.       factor = gradient_calc_linear_factor (rbd->dist, rbd->vec, rbd->offset,
  1282.                         x - rbd->sx, y - rbd->sy);
  1283.       break;
  1284.  
  1285.     case BILINEAR:
  1286.       factor = gradient_calc_bilinear_factor (rbd->dist, rbd->vec, rbd->offset,
  1287.                           x - rbd->sx, y - rbd->sy);
  1288.       break;
  1289.  
  1290.     case SHAPEBURST_ANGULAR:
  1291.       factor = gradient_calc_shapeburst_angular_factor (x, y);
  1292.       break;
  1293.  
  1294.     case SHAPEBURST_SPHERICAL:
  1295.       factor = gradient_calc_shapeburst_spherical_factor (x, y);
  1296.       break;
  1297.  
  1298.     case SHAPEBURST_DIMPLED:
  1299.       factor = gradient_calc_shapeburst_dimpled_factor (x, y);
  1300.       break;
  1301.  
  1302.     case SPIRAL_CLOCKWISE:
  1303.       factor = gradient_calc_spiral_factor (rbd->dist, rbd->vec, rbd->offset,
  1304.                         x - rbd->sx, y - rbd->sy,TRUE);
  1305.       break;
  1306.  
  1307.     case SPIRAL_ANTICLOCKWISE:
  1308.       factor = gradient_calc_spiral_factor (rbd->dist, rbd->vec, rbd->offset,
  1309.                         x - rbd->sx, y - rbd->sy,FALSE);
  1310.       break;
  1311.  
  1312.     default:
  1313.       gimp_fatal_error ("gradient_render_pixel(): Unknown gradient type %d",
  1314.             (int) rbd->gradient_type);
  1315.       return;
  1316.     }
  1317.  
  1318.   /* Adjust for repeat */
  1319.  
  1320.   factor = (*rbd->repeat_func)(factor);
  1321.  
  1322.   /* Blend the colors */
  1323.  
  1324.   if (rbd->blend_mode == CUSTOM_MODE)
  1325.     gradient_get_color_at (gimp_context_get_gradient (NULL),
  1326.                factor, &color->r, &color->g, &color->b, &color->a);
  1327.   else
  1328.     {
  1329.       /* Blend values */
  1330.  
  1331.       color->r = rbd->fg.r + (rbd->bg.r - rbd->fg.r) * factor;
  1332.       color->g = rbd->fg.g + (rbd->bg.g - rbd->fg.g) * factor;
  1333.       color->b = rbd->fg.b + (rbd->bg.b - rbd->fg.b) * factor;
  1334.       color->a = rbd->fg.a + (rbd->bg.a - rbd->fg.a) * factor;
  1335.  
  1336.       if (rbd->blend_mode == FG_BG_HSV_MODE)
  1337.     gimp_hsv_to_rgb_double (&color->r, &color->g, &color->b);
  1338.     }
  1339. }
  1340.  
  1341. static void
  1342. gradient_put_pixel (int      x, 
  1343.             int      y, 
  1344.             color_t  color, 
  1345.             void    *put_pixel_data)
  1346. {
  1347.   PutPixelData  *ppd;
  1348.   unsigned char *data;
  1349.  
  1350.   ppd = put_pixel_data;
  1351.  
  1352.   /* Paint */
  1353.  
  1354.   data = ppd->row_data + ppd->bytes * x;
  1355.  
  1356.   if (ppd->bytes >= 3)
  1357.     {
  1358.       *data++ = color.r * 255.0;
  1359.       *data++ = color.g * 255.0;
  1360.       *data++ = color.b * 255.0;
  1361.       *data++ = color.a * 255.0;
  1362.     }
  1363.   else
  1364.     {
  1365.       /* Convert to grayscale */
  1366.  
  1367.       *data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
  1368.       *data++ = color.a * 255.0;
  1369.     }
  1370.  
  1371.   /* Paint whole row if we are on the rightmost pixel */
  1372.  
  1373.   if (x == (ppd->width - 1))
  1374.     pixel_region_set_row(ppd->PR, 0, y, ppd->width, ppd->row_data);
  1375. }
  1376.  
  1377. static void
  1378. gradient_fill_region (GImage          *gimage,
  1379.               GimpDrawable    *drawable,
  1380.               PixelRegion     *PR,
  1381.               int              width,
  1382.               int              height,
  1383.               BlendMode        blend_mode,
  1384.               GradientType     gradient_type,
  1385.               double           offset,
  1386.               RepeatMode       repeat,
  1387.               int              supersample,
  1388.               int              max_depth,
  1389.               double           threshold,
  1390.               double           sx,
  1391.               double           sy,
  1392.               double           ex,
  1393.               double           ey,
  1394.               progress_func_t  progress_callback,
  1395.               void            *progress_data)
  1396. {
  1397.   RenderBlendData  rbd;
  1398.   PutPixelData     ppd;
  1399.   unsigned char    r, g, b;
  1400.   int              x, y;
  1401.   int              endx, endy;
  1402.   void            *pr;
  1403.   unsigned char   *data;
  1404.   color_t          color;
  1405.  
  1406.   /* Get foreground and background colors, normalized */
  1407.  
  1408.   gimp_context_get_foreground (NULL, &r, &g, &b);
  1409.  
  1410.   rbd.fg.r = r / 255.0;
  1411.   rbd.fg.g = g / 255.0;
  1412.   rbd.fg.b = b / 255.0;
  1413.   rbd.fg.a = 1.0;  /* Foreground is always opaque */
  1414.  
  1415.   gimp_context_get_background (NULL, &r, &g, &b);
  1416.  
  1417.   rbd.bg.r = r / 255.0;
  1418.   rbd.bg.g = g / 255.0;
  1419.   rbd.bg.b = b / 255.0;
  1420.   rbd.bg.a = 1.0; /* opaque, for now */
  1421.  
  1422.   switch (blend_mode)
  1423.     {
  1424.     case FG_BG_RGB_MODE:
  1425.       break;
  1426.  
  1427.     case FG_BG_HSV_MODE:
  1428.       /* Convert to HSV */
  1429.  
  1430.       gimp_rgb_to_hsv_double(&rbd.fg.r, &rbd.fg.g, &rbd.fg.b);
  1431.       gimp_rgb_to_hsv_double(&rbd.bg.r, &rbd.bg.g, &rbd.bg.b);
  1432.  
  1433.       break;
  1434.  
  1435.     case FG_TRANS_MODE:
  1436.       /* Color does not change, just the opacity */
  1437.  
  1438.       rbd.bg   = rbd.fg;
  1439.       rbd.bg.a = 0.0; /* transparent */
  1440.  
  1441.       break;
  1442.  
  1443.     case CUSTOM_MODE:
  1444.       break;
  1445.  
  1446.     default:
  1447.       gimp_fatal_error("gradient_fill_region(): Unknown blend mode %d",
  1448.                (int) blend_mode);
  1449.       break;
  1450.     }
  1451.  
  1452.   /* Calculate type-specific parameters */
  1453.  
  1454.   switch (gradient_type)
  1455.     {
  1456.     case RADIAL:
  1457.       rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
  1458.       break;
  1459.  
  1460.     case SQUARE:
  1461.       rbd.dist = MAX (fabs (ex - sx), fabs (ey - sy));
  1462.       break;
  1463.  
  1464.     case CONICAL_SYMMETRIC:
  1465.     case CONICAL_ASYMMETRIC:
  1466.     case SPIRAL_CLOCKWISE:
  1467.     case SPIRAL_ANTICLOCKWISE:
  1468.     case LINEAR:
  1469.     case BILINEAR:
  1470.       rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
  1471.  
  1472.       if (rbd.dist > 0.0)
  1473.     {
  1474.       rbd.vec[0] = (ex - sx) / rbd.dist;
  1475.       rbd.vec[1] = (ey - sy) / rbd.dist;
  1476.     }
  1477.  
  1478.       break;
  1479.  
  1480.     case SHAPEBURST_ANGULAR:
  1481.     case SHAPEBURST_SPHERICAL:
  1482.     case SHAPEBURST_DIMPLED:
  1483.       rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
  1484.       gradient_precalc_shapeburst(gimage, drawable, PR, rbd.dist);
  1485.       break;
  1486.  
  1487.     default:
  1488.       gimp_fatal_error("gradient_fill_region(): Unknown gradient type %d",
  1489.                (int) gradient_type);
  1490.       break;
  1491.     }
  1492.  
  1493.   /* Set repeat function */
  1494.  
  1495.   switch (repeat)
  1496.     {
  1497.     case REPEAT_NONE:
  1498.       rbd.repeat_func = gradient_repeat_none;
  1499.       break;
  1500.  
  1501.     case REPEAT_SAWTOOTH:
  1502.       rbd.repeat_func = gradient_repeat_sawtooth;
  1503.       break;
  1504.  
  1505.     case REPEAT_TRIANGULAR:
  1506.       rbd.repeat_func = gradient_repeat_triangular;
  1507.       break;
  1508.  
  1509.     default:
  1510.       gimp_fatal_error("gradient_fill_region(): Unknown repeat mode %d",
  1511.                (int) repeat);
  1512.       break;
  1513.     }
  1514.  
  1515.   /* Initialize render data */
  1516.  
  1517.   rbd.offset        = offset;
  1518.   rbd.sx            = sx;
  1519.   rbd.sy            = sy;
  1520.   rbd.blend_mode    = blend_mode;
  1521.   rbd.gradient_type = gradient_type;
  1522.  
  1523.   /* Render the gradient! */
  1524.  
  1525.   if (supersample)
  1526.     {
  1527.       /* Initialize put pixel data */
  1528.  
  1529.       ppd.PR       = PR;
  1530.       ppd.row_data = g_malloc(width * PR->bytes);
  1531.       ppd.bytes    = PR->bytes;
  1532.       ppd.width    = width;
  1533.  
  1534.       /* Render! */
  1535.  
  1536.       adaptive_supersample_area(0, 0, (width - 1), (height - 1),
  1537.                 max_depth, threshold,
  1538.                 gradient_render_pixel, &rbd,
  1539.                 gradient_put_pixel, &ppd,
  1540.                 progress_callback, progress_data);
  1541.  
  1542.       /* Clean up */
  1543.  
  1544.       g_free(ppd.row_data);
  1545.     }
  1546.   else
  1547.     {
  1548.       int max_progress = PR->w * PR->h;
  1549.       int progress = 0;
  1550.  
  1551.       for (pr = pixel_regions_register(1, PR); pr != NULL; pr = pixel_regions_process(pr))
  1552.     {
  1553.       data = PR->data;
  1554.       endx = PR->x + PR->w;
  1555.       endy = PR->y + PR->h;
  1556.  
  1557.       for (y = PR->y; y < endy; y++)
  1558.         for (x = PR->x; x < endx; x++)
  1559.           {
  1560.         gradient_render_pixel(x, y, &color, &rbd);
  1561.  
  1562.         if (PR->bytes >= 3)
  1563.           {
  1564.             *data++ = color.r * 255.0;
  1565.             *data++ = color.g * 255.0;
  1566.             *data++ = color.b * 255.0;
  1567.             *data++ = color.a * 255.0;
  1568.           }
  1569.         else
  1570.           {
  1571.             /* Convert to grayscale */
  1572.  
  1573.             *data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
  1574.             *data++ = color.a * 255.0;
  1575.           }
  1576.           }
  1577.  
  1578.       progress += PR->w * PR->h;
  1579.       if (progress_callback)
  1580.         (*progress_callback) (0, max_progress, progress, progress_data);
  1581.     }
  1582.     }
  1583. }
  1584.  
  1585. /****************************/
  1586. /*  Global blend functions  */
  1587. /****************************/
  1588.  
  1589. Tool *
  1590. tools_new_blend ()
  1591. {
  1592.   Tool * tool;
  1593.   BlendTool * private;
  1594.  
  1595.   /*  The tool options  */
  1596.   if (! blend_options)
  1597.     {
  1598.       blend_options = blend_options_new ();
  1599.       tools_register (BLEND, (ToolOptions *) blend_options);
  1600.     }
  1601.  
  1602.   tool = tools_new_tool (BLEND);
  1603.   private = g_new0 (BlendTool, 1);
  1604.  
  1605.   private->core = draw_core_new (blend_draw);
  1606.  
  1607.   tool->scroll_lock = TRUE;  /*  Disallow scrolling  */
  1608.  
  1609.   tool->private = (void *) private;
  1610.  
  1611.   tool->button_press_func   = blend_button_press;
  1612.   tool->button_release_func = blend_button_release;
  1613.   tool->motion_func         = blend_motion;
  1614.   tool->cursor_update_func  = blend_cursor_update;
  1615.   tool->control_func        = blend_control;
  1616.  
  1617.   return tool;
  1618. }
  1619.  
  1620. void
  1621. tools_free_blend (Tool *tool)
  1622. {
  1623.   BlendTool * blend_tool;
  1624.  
  1625.   blend_tool = (BlendTool *) tool->private;
  1626.  
  1627.   if (tool->state == ACTIVE)
  1628.     draw_core_stop (blend_tool->core, tool);
  1629.  
  1630.   draw_core_free (blend_tool->core);
  1631.  
  1632.   /*  free the distance map data if it exists  */
  1633.   if (distR.tiles)
  1634.     tile_manager_destroy (distR.tiles);
  1635.   distR.tiles = NULL;
  1636.  
  1637.   g_free (blend_tool);
  1638. }
  1639.