home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 February / CMCD0205.ISO / Linux / gimp-2.2.0.tar.gz / gimp-2.2.0.tar / gimp-2.2.0 / libgimpwidgets / gimpcolorselect.c < prev    next >
C/C++ Source or Header  |  2004-09-19  |  38KB  |  1,487 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * gimpcolorselect.c
  5.  * Copyright (C) 2002 Michael Natterer <mitch@gimp.org>
  6.  *
  7.  * based on color_notebook module
  8.  * Copyright (C) 1998 Austin Donnelly <austin@greenend.org.uk>
  9.  *
  10.  * This library is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU Lesser General Public
  12.  * License as published by the Free Software Foundation; either
  13.  * version 2 of the License, or (at your option) any later version.
  14.  *
  15.  * This library is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.  * Library General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU Lesser General Public
  21.  * License along with this library; if not, write to the
  22.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  23.  * Boston, MA 02111-1307, USA.
  24.  */
  25.  
  26. #include "config.h"
  27.  
  28. #include <gtk/gtk.h>
  29.  
  30. #include "libgimpcolor/gimpcolor.h"
  31. #include "libgimpmath/gimpmath.h"
  32.  
  33. #include "gimpwidgetstypes.h"
  34.  
  35. #include "gimpcolorselector.h"
  36. #include "gimpcolorselect.h"
  37. #include "gimphelpui.h"
  38. #include "gimppreviewarea.h"
  39. #include "gimpstock.h"
  40.  
  41. #include "libgimp/libgimp-intl.h"
  42.  
  43.  
  44. #define COLOR_AREA_EVENT_MASK (GDK_EXPOSURE_MASK       | \
  45.                                GDK_BUTTON_PRESS_MASK   | \
  46.                                GDK_BUTTON_RELEASE_MASK | \
  47.                                GDK_BUTTON_MOTION_MASK  | \
  48.                                GDK_ENTER_NOTIFY_MASK)
  49.  
  50.  
  51. typedef enum
  52. {
  53.   COLOR_SELECT_HUE = 0,
  54.   COLOR_SELECT_SATURATION,
  55.   COLOR_SELECT_VALUE,
  56.   COLOR_SELECT_RED,
  57.   COLOR_SELECT_GREEN,
  58.   COLOR_SELECT_BLUE,
  59.   COLOR_SELECT_ALPHA,
  60.   COLOR_SELECT_HUE_SATURATION,
  61.   COLOR_SELECT_HUE_VALUE,
  62.   COLOR_SELECT_SATURATION_VALUE,
  63.   COLOR_SELECT_RED_GREEN,
  64.   COLOR_SELECT_RED_BLUE,
  65.   COLOR_SELECT_GREEN_BLUE
  66. } ColorSelectFillType;
  67.  
  68. typedef enum
  69. {
  70.   UPDATE_VALUES     = 1 << 0,
  71.   UPDATE_POS        = 1 << 1,
  72.   UPDATE_XY_COLOR   = 1 << 2,
  73.   UPDATE_Z_COLOR    = 1 << 3,
  74.   UPDATE_CALLER     = 1 << 6
  75. } ColorSelectUpdateType;
  76.  
  77.  
  78. #define GIMP_COLOR_SELECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_COLOR_SELECT, GimpColorSelectClass))
  79. #define GIMP_IS_COLOR_SELECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_COLOR_SELECT))
  80. #define GIMP_COLOR_SELECT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_COLOR_SELECT, GimpColorSelectClass))
  81.  
  82.  
  83. typedef struct _GimpColorSelectClass GimpColorSelectClass;
  84.  
  85. struct _GimpColorSelect
  86. {
  87.   GimpColorSelector    parent_instance;
  88.  
  89.   GtkWidget           *toggle_box;
  90.  
  91.   GtkWidget           *xy_color;
  92.   GtkWidget           *z_color;
  93.  
  94.   gint                 pos[3];
  95.  
  96.   ColorSelectFillType  z_color_fill;
  97.   ColorSelectFillType  xy_color_fill;
  98.   GdkGC               *gc;
  99. };
  100.  
  101. struct _GimpColorSelectClass
  102. {
  103.   GimpColorSelectorClass  parent_class;
  104. };
  105.  
  106.  
  107. typedef struct _ColorSelectFill ColorSelectFill;
  108.  
  109. typedef void (* ColorSelectFillUpdateProc) (ColorSelectFill *color_select_fill);
  110.  
  111. struct _ColorSelectFill
  112. {
  113.   guchar  *buffer;
  114.   gint     y;
  115.   gint     width;
  116.   gint     height;
  117.   GimpRGB  rgb;
  118.   GimpHSV  hsv;
  119.  
  120.   ColorSelectFillUpdateProc update;
  121. };
  122.  
  123.  
  124. static void   gimp_color_select_class_init    (GimpColorSelectClass *klass);
  125. static void   gimp_color_select_init          (GimpColorSelect      *select);
  126.  
  127. static void   gimp_color_select_unrealize       (GtkWidget          *widget);
  128.  
  129. static void   gimp_color_select_togg_visible    (GimpColorSelector  *selector,
  130.                                                  gboolean            visible);
  131. static void   gimp_color_select_togg_sensitive  (GimpColorSelector  *selector,
  132.                                                  gboolean            sensitive);
  133. static void   gimp_color_select_set_color       (GimpColorSelector  *selector,
  134.                                                  const GimpRGB      *rgb,
  135.                                                  const GimpHSV      *hsv);
  136. static void   gimp_color_select_set_channel     (GimpColorSelector  *selector,
  137.                                                  GimpColorSelectorChannel  channel);
  138.  
  139. static void   gimp_color_select_channel_toggled (GtkWidget          *widget,
  140.                                                  GimpColorSelect    *select);
  141.  
  142. static void   gimp_color_select_update          (GimpColorSelect    *select,
  143.                                                  ColorSelectUpdateType  type);
  144. static void   gimp_color_select_update_values   (GimpColorSelect    *select);
  145. static void   gimp_color_select_update_pos      (GimpColorSelect    *select);
  146.  
  147. #if 0
  148. static void   gimp_color_select_drop_color      (GtkWidget          *widget,
  149.                                                  const GimpRGB      *color,
  150.                                                  gpointer            data);
  151. #endif
  152.  
  153. static void  gimp_color_select_xy_size_allocate (GtkWidget          *widget,
  154.                                                  GtkAllocation      *allocation,
  155.                                                  GimpColorSelect    *select);
  156. static gboolean   gimp_color_select_xy_expose   (GtkWidget          *widget,
  157.                                                  GdkEventExpose     *eevent,
  158.                                                  GimpColorSelect    *select);
  159. static gboolean   gimp_color_select_xy_events   (GtkWidget          *widget,
  160.                                                  GdkEvent           *event,
  161.                                                  GimpColorSelect    *select);
  162. static void   gimp_color_select_z_size_allocate (GtkWidget          *widget,
  163.                                                  GtkAllocation      *allocation,
  164.                                                  GimpColorSelect    *select);
  165. static gboolean   gimp_color_select_z_expose    (GtkWidget          *widget,
  166.                                                  GdkEventExpose     *eevent,
  167.                                                  GimpColorSelect    *select);
  168. static gboolean   gimp_color_select_z_events    (GtkWidget          *widet,
  169.                                                  GdkEvent           *event,
  170.                                                  GimpColorSelect    *select);
  171.  
  172. static void   gimp_color_select_image_fill      (GtkWidget          *widget,
  173.                                                  ColorSelectFillType fill_type,
  174.                                                  const GimpHSV      *hsv,
  175.                                                  const GimpRGB      *rgb);
  176.  
  177. static void   gimp_color_select_draw_z_marker   (GimpColorSelect    *select,
  178.                                                  GdkRectangle       *clip);
  179. static void   gimp_color_select_draw_xy_marker  (GimpColorSelect    *select,
  180.                                                  GdkRectangle       *clip);
  181.  
  182. static void   color_select_update_red              (ColorSelectFill *csf);
  183. static void   color_select_update_green            (ColorSelectFill *csf);
  184. static void   color_select_update_blue             (ColorSelectFill *csf);
  185. static void   color_select_update_hue              (ColorSelectFill *csf);
  186. static void   color_select_update_saturation       (ColorSelectFill *csf);
  187. static void   color_select_update_value            (ColorSelectFill *csf);
  188. static void   color_select_update_red_green        (ColorSelectFill *csf);
  189. static void   color_select_update_red_blue         (ColorSelectFill *csf);
  190. static void   color_select_update_green_blue       (ColorSelectFill *csf);
  191. static void   color_select_update_hue_saturation   (ColorSelectFill *csf);
  192. static void   color_select_update_hue_value        (ColorSelectFill *csf);
  193. static void   color_select_update_saturation_value (ColorSelectFill *csf);
  194.  
  195.  
  196. /*  static variables  */
  197.  
  198. static GimpColorSelectorClass *parent_class = NULL;
  199.  
  200. static ColorSelectFillUpdateProc update_procs[] =
  201. {
  202.   color_select_update_hue,
  203.   color_select_update_saturation,
  204.   color_select_update_value,
  205.   color_select_update_red,
  206.   color_select_update_green,
  207.   color_select_update_blue,
  208.   NULL, /* alpha */
  209.   color_select_update_hue_saturation,
  210.   color_select_update_hue_value,
  211.   color_select_update_saturation_value,
  212.   color_select_update_red_green,
  213.   color_select_update_red_blue,
  214.   color_select_update_green_blue,
  215. };
  216.  
  217.  
  218. GType
  219. gimp_color_select_get_type (void)
  220. {
  221.   static GType select_type = 0;
  222.  
  223.   if (! select_type)
  224.     {
  225.       static const GTypeInfo select_info =
  226.       {
  227.         sizeof (GimpColorSelectClass),
  228.         (GBaseInitFunc) NULL,
  229.         (GBaseFinalizeFunc) NULL,
  230.         (GClassInitFunc) gimp_color_select_class_init,
  231.         NULL,           /* class_finalize */
  232.         NULL,           /* class_data     */
  233.         sizeof (GimpColorSelect),
  234.         0,              /* n_preallocs    */
  235.         (GInstanceInitFunc) gimp_color_select_init,
  236.       };
  237.  
  238.       select_type = g_type_register_static (GIMP_TYPE_COLOR_SELECTOR,
  239.                                             "GimpColorSelect",
  240.                                             &select_info, 0);
  241.     }
  242.  
  243.   return select_type;
  244. }
  245.  
  246. static void
  247. gimp_color_select_class_init (GimpColorSelectClass *klass)
  248. {
  249.   GtkWidgetClass         *widget_class   = GTK_WIDGET_CLASS (klass);
  250.   GimpColorSelectorClass *selector_class = GIMP_COLOR_SELECTOR_CLASS (klass);
  251.  
  252.   parent_class = g_type_class_peek_parent (klass);
  253.  
  254.   widget_class->unrealize               = gimp_color_select_unrealize;
  255.  
  256.   selector_class->name                  = "GIMP";
  257.   selector_class->help_id               = "gimp-colorselector-gimp";
  258.   selector_class->stock_id              = GIMP_STOCK_WILBER;
  259.   selector_class->set_toggles_visible   = gimp_color_select_togg_visible;
  260.   selector_class->set_toggles_sensitive = gimp_color_select_togg_sensitive;
  261.   selector_class->set_color             = gimp_color_select_set_color;
  262.   selector_class->set_channel           = gimp_color_select_set_channel;
  263. }
  264.  
  265. static void
  266. gimp_color_select_init (GimpColorSelect *select)
  267. {
  268.   GtkWidget *hbox;
  269.   GtkWidget *frame;
  270.  
  271.   select->z_color_fill  = COLOR_SELECT_HUE;
  272.   select->xy_color_fill = COLOR_SELECT_SATURATION_VALUE;
  273.   select->gc            = NULL;
  274.  
  275.   hbox = gtk_hbox_new (FALSE, 4);
  276.   gtk_box_pack_start (GTK_BOX (select), hbox, TRUE, TRUE, 0);
  277.   gtk_widget_show (hbox);
  278.  
  279.   /*  The x/y component preview  */
  280.   frame = gtk_frame_new (NULL);
  281.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  282.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  283.   gtk_widget_show (frame);
  284.  
  285.   select->xy_color = gimp_preview_area_new ();
  286.   gtk_widget_set_size_request (select->xy_color,
  287.                                GIMP_COLOR_SELECTOR_SIZE,
  288.                                GIMP_COLOR_SELECTOR_SIZE);
  289.   gtk_widget_set_events (select->xy_color, COLOR_AREA_EVENT_MASK);
  290.   gtk_container_add (GTK_CONTAINER (frame), select->xy_color);
  291.   gtk_widget_show (select->xy_color);
  292.  
  293.   g_signal_connect (select->xy_color, "size_allocate",
  294.                     G_CALLBACK (gimp_color_select_xy_size_allocate),
  295.                     select);
  296.   g_signal_connect_after (select->xy_color, "expose_event",
  297.                           G_CALLBACK (gimp_color_select_xy_expose),
  298.                           select);
  299.   g_signal_connect (select->xy_color, "event",
  300.                     G_CALLBACK (gimp_color_select_xy_events),
  301.                     select);
  302.  
  303. #if 0
  304.   gimp_dnd_color_dest_add (select->xy_color, gimp_color_select_drop_color,
  305.                            select);
  306. #endif
  307.  
  308.   /*  The z component preview  */
  309.   frame = gtk_frame_new (NULL);
  310.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  311.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  312.   gtk_widget_show (frame);
  313.  
  314.   select->z_color = gimp_preview_area_new ();
  315.   gtk_widget_set_size_request (select->z_color,
  316.                                GIMP_COLOR_SELECTOR_BAR_SIZE,
  317.                                GIMP_COLOR_SELECTOR_SIZE);
  318.   gtk_widget_set_events (select->z_color, COLOR_AREA_EVENT_MASK);
  319.   gtk_container_add (GTK_CONTAINER (frame), select->z_color);
  320.   gtk_widget_show (select->z_color);
  321.  
  322.   g_signal_connect (select->z_color, "size_allocate",
  323.                     G_CALLBACK (gimp_color_select_z_size_allocate),
  324.                     select);
  325.   g_signal_connect_after (select->z_color, "expose_event",
  326.                           G_CALLBACK (gimp_color_select_z_expose),
  327.                           select);
  328.   g_signal_connect (select->z_color, "event",
  329.                     G_CALLBACK (gimp_color_select_z_events),
  330.                     select);
  331.  
  332.   select->toggle_box = gtk_vbox_new (FALSE, 2);
  333.   gtk_box_pack_start (GTK_BOX (hbox), select->toggle_box, FALSE, FALSE, 0);
  334.   gtk_widget_show (select->toggle_box);
  335.  
  336.   /*  channel toggles  */
  337.   {
  338.     GimpColorSelectorChannel  channel;
  339.     GSList                   *group = NULL;
  340.  
  341.     static const gchar *labels[] =
  342.     {
  343.       N_("_H"), N_("_S"), N_("_V"), N_("_R"), N_("_G"), N_("_B")
  344.     };
  345.     static const gchar *tips[7] =
  346.     {
  347.       N_("Hue"),
  348.       N_("Saturation"),
  349.       N_("Value"),
  350.       N_("Red"),
  351.       N_("Green"),
  352.       N_("Blue"),
  353.       N_("Alpha")
  354.     };
  355.  
  356.     for (channel = GIMP_COLOR_SELECTOR_HUE;
  357.          channel < GIMP_COLOR_SELECTOR_ALPHA;
  358.          channel++)
  359.       {
  360.         GtkWidget *button;
  361.  
  362.         button = gtk_radio_button_new_with_mnemonic (group,
  363.                                                      gettext (labels[channel]));
  364.         group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
  365.         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
  366.         gtk_box_pack_start (GTK_BOX (select->toggle_box), button,
  367.                             TRUE, TRUE, 0);
  368.         gtk_widget_show (button);
  369.  
  370.         g_object_set_data (G_OBJECT (button), "channel",
  371.                            GINT_TO_POINTER (channel));
  372.  
  373.         if (channel == GIMP_COLOR_SELECTOR_HUE)
  374.           gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
  375.  
  376.         gimp_help_set_help_data (button, gettext (tips[channel]), NULL);
  377.  
  378.         g_signal_connect (button, "toggled",
  379.                           G_CALLBACK (gimp_color_select_channel_toggled),
  380.                           select);
  381.       }
  382.   }
  383. }
  384.  
  385. static void
  386. gimp_color_select_unrealize (GtkWidget *widget)
  387. {
  388.   GimpColorSelect *select = GIMP_COLOR_SELECT (widget);
  389.  
  390.   if (select->gc)
  391.     {
  392.       g_object_unref (select->gc);
  393.       select->gc = NULL;
  394.     }
  395.  
  396.   GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
  397. }
  398.  
  399. static void
  400. gimp_color_select_togg_visible (GimpColorSelector *selector,
  401.                                 gboolean           visible)
  402. {
  403.   GimpColorSelect *select = GIMP_COLOR_SELECT (selector);
  404.  
  405.   if (visible)
  406.     gtk_widget_show (select->toggle_box);
  407.   else
  408.     gtk_widget_hide (select->toggle_box);
  409. }
  410.  
  411. static void
  412. gimp_color_select_togg_sensitive (GimpColorSelector *selector,
  413.                                   gboolean           sensitive)
  414. {
  415.   GimpColorSelect *select = GIMP_COLOR_SELECT (selector);
  416.  
  417.   gtk_widget_set_sensitive (select->toggle_box, sensitive);
  418. }
  419.  
  420. static void
  421. gimp_color_select_set_color (GimpColorSelector *selector,
  422.                              const GimpRGB     *rgb,
  423.                              const GimpHSV     *hsv)
  424. {
  425.   GimpColorSelect *select = GIMP_COLOR_SELECT (selector);
  426.  
  427.   gimp_color_select_update (select,
  428.                             UPDATE_POS | UPDATE_XY_COLOR | UPDATE_Z_COLOR);
  429. }
  430.  
  431. static void
  432. gimp_color_select_set_channel (GimpColorSelector        *selector,
  433.                                GimpColorSelectorChannel  channel)
  434. {
  435.   GimpColorSelect *select = GIMP_COLOR_SELECT (selector);
  436.  
  437.   switch ((ColorSelectFillType) channel)
  438.     {
  439.     case COLOR_SELECT_HUE:
  440.       select->z_color_fill  = COLOR_SELECT_HUE;
  441.       select->xy_color_fill = COLOR_SELECT_SATURATION_VALUE;
  442.       break;
  443.  
  444.     case COLOR_SELECT_SATURATION:
  445.       select->z_color_fill  = COLOR_SELECT_SATURATION;
  446.       select->xy_color_fill = COLOR_SELECT_HUE_VALUE;
  447.       break;
  448.  
  449.     case COLOR_SELECT_VALUE:
  450.       select->z_color_fill  = COLOR_SELECT_VALUE;
  451.       select->xy_color_fill = COLOR_SELECT_HUE_SATURATION;
  452.       break;
  453.  
  454.     case COLOR_SELECT_RED:
  455.       select->z_color_fill  = COLOR_SELECT_RED;
  456.       select->xy_color_fill = COLOR_SELECT_GREEN_BLUE;
  457.       break;
  458.  
  459.     case COLOR_SELECT_GREEN:
  460.       select->z_color_fill  = COLOR_SELECT_GREEN;
  461.       select->xy_color_fill = COLOR_SELECT_RED_BLUE;
  462.       break;
  463.  
  464.     case COLOR_SELECT_BLUE:
  465.       select->z_color_fill  = COLOR_SELECT_BLUE;
  466.       select->xy_color_fill = COLOR_SELECT_RED_GREEN;
  467.       break;
  468.  
  469.     default:
  470.       break;
  471.     }
  472.  
  473.   gimp_color_select_update (select,
  474.                             UPDATE_POS | UPDATE_Z_COLOR | UPDATE_XY_COLOR);
  475. }
  476.  
  477. static void
  478. gimp_color_select_channel_toggled (GtkWidget       *widget,
  479.                                    GimpColorSelect *select)
  480. {
  481.   if (GTK_TOGGLE_BUTTON (widget)->active)
  482.     {
  483.       GimpColorSelector        *selector = GIMP_COLOR_SELECTOR (select);
  484.       GimpColorSelectorChannel  channel;
  485.  
  486.       channel = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
  487.                                                     "channel"));
  488.  
  489.       selector->channel = channel;
  490.       gimp_color_select_set_channel (selector, channel);
  491.  
  492.       gimp_color_selector_channel_changed (selector);
  493.     }
  494. }
  495.  
  496. static void
  497. gimp_color_select_update (GimpColorSelect       *select,
  498.                           ColorSelectUpdateType  update)
  499. {
  500.   GimpColorSelector *selector = GIMP_COLOR_SELECTOR (select);
  501.  
  502.   if (update & UPDATE_POS)
  503.     gimp_color_select_update_pos (select);
  504.  
  505.   if (update & UPDATE_VALUES)
  506.     gimp_color_select_update_values (select);
  507.  
  508.   if (update & UPDATE_XY_COLOR)
  509.     {
  510.       gimp_color_select_image_fill (select->xy_color, select->xy_color_fill,
  511.                                     &selector->hsv, &selector->rgb);
  512.       gtk_widget_queue_draw (select->xy_color);
  513.     }
  514.  
  515.   if (update & UPDATE_Z_COLOR)
  516.     {
  517.       gimp_color_select_image_fill (select->z_color, select->z_color_fill,
  518.                                     &selector->hsv, &selector->rgb);
  519.       gtk_widget_queue_draw (select->z_color);
  520.     }
  521.  
  522.   if (update & UPDATE_CALLER)
  523.     gimp_color_selector_color_changed (GIMP_COLOR_SELECTOR (select));
  524. }
  525.  
  526. static void
  527. gimp_color_select_update_values (GimpColorSelect *select)
  528. {
  529.   GimpColorSelector *selector = GIMP_COLOR_SELECTOR (select);
  530.  
  531.   switch (select->z_color_fill)
  532.     {
  533.     case COLOR_SELECT_RED:
  534.       selector->rgb.b = select->pos[0] / 255.0;
  535.       selector->rgb.g = select->pos[1] / 255.0;
  536.       selector->rgb.r = select->pos[2] / 255.0;
  537.       break;
  538.     case COLOR_SELECT_GREEN:
  539.       selector->rgb.b = select->pos[0] / 255.0;
  540.       selector->rgb.r = select->pos[1] / 255.0;
  541.       selector->rgb.g = select->pos[2] / 255.0;
  542.       break;
  543.     case COLOR_SELECT_BLUE:
  544.       selector->rgb.g = select->pos[0] / 255.0;
  545.       selector->rgb.r = select->pos[1] / 255.0;
  546.       selector->rgb.b = select->pos[2] / 255.0;
  547.       break;
  548.  
  549.     case COLOR_SELECT_HUE:
  550.       selector->hsv.v = select->pos[0] / 255.0;
  551.       selector->hsv.s = select->pos[1] / 255.0;
  552.       selector->hsv.h = select->pos[2] / 255.0;
  553.       break;
  554.     case COLOR_SELECT_SATURATION:
  555.       selector->hsv.v = select->pos[0] / 255.0;
  556.       selector->hsv.h = select->pos[1] / 255.0;
  557.       selector->hsv.s = select->pos[2] / 255.0;
  558.       break;
  559.     case COLOR_SELECT_VALUE:
  560.       selector->hsv.s = select->pos[0] / 255.0;
  561.       selector->hsv.h = select->pos[1] / 255.0;
  562.       selector->hsv.v = select->pos[2] / 255.0;
  563.       break;
  564.  
  565.     default:
  566.       break;
  567.     }
  568.  
  569.   switch (select->z_color_fill)
  570.     {
  571.     case COLOR_SELECT_RED:
  572.     case COLOR_SELECT_GREEN:
  573.     case COLOR_SELECT_BLUE:
  574.       gimp_rgb_to_hsv (&selector->rgb, &selector->hsv);
  575.       break;
  576.  
  577.     case COLOR_SELECT_HUE:
  578.     case COLOR_SELECT_SATURATION:
  579.     case COLOR_SELECT_VALUE:
  580.       gimp_hsv_to_rgb (&selector->hsv, &selector->rgb);
  581.       break;
  582.  
  583.     default:
  584.       break;
  585.     }
  586. }
  587.  
  588. static void
  589. gimp_color_select_update_pos (GimpColorSelect *select)
  590. {
  591.   GimpColorSelector *selector = GIMP_COLOR_SELECTOR (select);
  592.  
  593.   switch (select->z_color_fill)
  594.     {
  595.     case COLOR_SELECT_RED:
  596.       select->pos[0] = ROUND (selector->rgb.b * 255.0);
  597.       select->pos[1] = ROUND (selector->rgb.g * 255.0);
  598.       select->pos[2] = ROUND (selector->rgb.r * 255.0);
  599.       break;
  600.     case COLOR_SELECT_GREEN:
  601.       select->pos[0] = ROUND (selector->rgb.b * 255.0);
  602.       select->pos[1] = ROUND (selector->rgb.r * 255.0);
  603.       select->pos[2] = ROUND (selector->rgb.g * 255.0);
  604.       break;
  605.     case COLOR_SELECT_BLUE:
  606.       select->pos[0] = ROUND (selector->rgb.g * 255.0);
  607.       select->pos[1] = ROUND (selector->rgb.r * 255.0);
  608.       select->pos[2] = ROUND (selector->rgb.b * 255.0);
  609.       break;
  610.  
  611.     case COLOR_SELECT_HUE:
  612.       select->pos[0] = ROUND (selector->hsv.v * 255.0);
  613.       select->pos[1] = ROUND (selector->hsv.s * 255.0);
  614.       select->pos[2] = ROUND (selector->hsv.h * 255.0);
  615.       break;
  616.     case COLOR_SELECT_SATURATION:
  617.       select->pos[0] = ROUND (selector->hsv.v * 255.0);
  618.       select->pos[1] = ROUND (selector->hsv.h * 255.0);
  619.       select->pos[2] = ROUND (selector->hsv.s * 255.0);
  620.       break;
  621.     case COLOR_SELECT_VALUE:
  622.       select->pos[0] = ROUND (selector->hsv.s * 255.0);
  623.       select->pos[1] = ROUND (selector->hsv.h * 255.0);
  624.       select->pos[2] = ROUND (selector->hsv.v * 255.0);
  625.       break;
  626.  
  627.     default:
  628.       break;
  629.     }
  630. }
  631.  
  632. #if 0
  633. static void
  634. gimp_color_select_drop_color (GtkWidget     *widget,
  635.                               const GimpRGB *color,
  636.                               gpointer       data)
  637. {
  638.   GimpColorSelect *select = GIMP_COLOR_SELECT (data);
  639.  
  640.   select->rgb = *color;
  641.  
  642.   gimp_color_select_update_hsv_values (select);
  643.  
  644.   gimp_color_select_update (select,
  645.                             UPDATE_POS | UPDATE_XY_COLOR | UPDATE_Z_COLOR |
  646.                             UPDATE_CALLER);
  647. }
  648. #endif
  649.  
  650. static void
  651. gimp_color_select_xy_size_allocate (GtkWidget       *widget,
  652.                                     GtkAllocation   *allocation,
  653.                                     GimpColorSelect *select)
  654. {
  655.   gimp_color_select_update (select, UPDATE_XY_COLOR);
  656. }
  657.  
  658. static gboolean
  659. gimp_color_select_xy_expose (GtkWidget       *widget,
  660.                              GdkEventExpose  *event,
  661.                              GimpColorSelect *select)
  662. {
  663.   if (! select->gc)
  664.     select->gc = gdk_gc_new (widget->window);
  665.  
  666.   gimp_color_select_draw_xy_marker (select, &event->area);
  667.  
  668.   return TRUE;
  669. }
  670.  
  671. static gboolean
  672. gimp_color_select_xy_events (GtkWidget       *widget,
  673.                              GdkEvent        *event,
  674.                              GimpColorSelect *select)
  675. {
  676.   GdkEventButton *bevent;
  677.   GdkEventMotion *mevent;
  678.   gint            width, height;
  679.   gint            x, y;
  680.  
  681.   switch (event->type)
  682.     {
  683.     case GDK_BUTTON_PRESS:
  684.       bevent = (GdkEventButton *) event;
  685.       x = bevent->x;
  686.       y = bevent->y;
  687.  
  688.       gdk_pointer_grab (select->xy_color->window, FALSE,
  689.                         GDK_POINTER_MOTION_HINT_MASK |
  690.                         GDK_BUTTON_MOTION_MASK       |
  691.                         GDK_BUTTON_RELEASE_MASK,
  692.                         NULL, NULL, bevent->time);
  693.       break;
  694.  
  695.     case GDK_BUTTON_RELEASE:
  696.       bevent = (GdkEventButton *) event;
  697.       x = bevent->x;
  698.       y = bevent->y;
  699.  
  700.       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
  701.                                   bevent->time);
  702.       break;
  703.  
  704.     case GDK_MOTION_NOTIFY:
  705.       mevent = (GdkEventMotion *) event;
  706.       if (mevent->is_hint)
  707.         {
  708.           gdk_window_get_pointer (widget->window, &x, &y, NULL);
  709.         }
  710.       else
  711.         {
  712.           x = mevent->x;
  713.           y = mevent->y;
  714.         }
  715.       break;
  716.  
  717.     default:
  718.       return FALSE;
  719.     }
  720.  
  721.   gimp_color_select_draw_xy_marker (select, NULL);
  722.  
  723.   width  = select->xy_color->allocation.width;
  724.   height = select->xy_color->allocation.height;
  725.  
  726.   if (width > 1 && height > 1)
  727.     {
  728.       select->pos[0] = (x * 255) / (width - 1);
  729.       select->pos[1] = 255 - (y * 255) / (height - 1);
  730.     }
  731.  
  732.   select->pos[0] = CLAMP (select->pos[0], 0, 255);
  733.   select->pos[1] = CLAMP (select->pos[1], 0, 255);
  734.  
  735.   gimp_color_select_draw_xy_marker (select, NULL);
  736.  
  737.   gimp_color_select_update (select, UPDATE_VALUES | UPDATE_CALLER);
  738.  
  739.   return TRUE;
  740. }
  741.  
  742. static void
  743. gimp_color_select_z_size_allocate (GtkWidget       *widget,
  744.                                    GtkAllocation   *allocation,
  745.                                    GimpColorSelect *select)
  746. {
  747.   gimp_color_select_update (select, UPDATE_Z_COLOR);
  748. }
  749.  
  750. static gboolean
  751. gimp_color_select_z_expose (GtkWidget       *widget,
  752.                             GdkEventExpose  *event,
  753.                             GimpColorSelect *select)
  754. {
  755.   if (! select->gc)
  756.     select->gc = gdk_gc_new (widget->window);
  757.  
  758.   gimp_color_select_draw_z_marker (select, &event->area);
  759.  
  760.   return TRUE;
  761. }
  762.  
  763. static gboolean
  764. gimp_color_select_z_events (GtkWidget       *widget,
  765.                             GdkEvent        *event,
  766.                             GimpColorSelect *select)
  767. {
  768.   GdkEventButton *bevent;
  769.   GdkEventMotion *mevent;
  770.   gint            height;
  771.   gint            z;
  772.  
  773.   switch (event->type)
  774.     {
  775.     case GDK_BUTTON_PRESS:
  776.       bevent = (GdkEventButton *) event;
  777.       z = bevent->y;
  778.  
  779.       gdk_pointer_grab (select->z_color->window, FALSE,
  780.                         GDK_POINTER_MOTION_HINT_MASK |
  781.                         GDK_BUTTON_MOTION_MASK       |
  782.                         GDK_BUTTON_RELEASE_MASK,
  783.                         NULL, NULL, bevent->time);
  784.       break;
  785.  
  786.     case GDK_BUTTON_RELEASE:
  787.       bevent = (GdkEventButton *) event;
  788.       z = bevent->y;
  789.  
  790.       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
  791.                                   bevent->time);
  792.       break;
  793.  
  794.     case GDK_MOTION_NOTIFY:
  795.       mevent = (GdkEventMotion *) event;
  796.       if (mevent->is_hint)
  797.         {
  798.           gdk_window_get_pointer (widget->window, NULL, &z, NULL);
  799.         }
  800.       else
  801.         {
  802.           z = mevent->y;
  803.         }
  804.       break;
  805.  
  806.     default:
  807.       return FALSE;
  808.     }
  809.  
  810.   gimp_color_select_draw_z_marker (select, NULL);
  811.  
  812.   height = select->z_color->allocation.height;
  813.  
  814.   if (height > 1)
  815.     select->pos[2] = 255 - (z * 255) / (height - 1);
  816.  
  817.   select->pos[2] = CLAMP (select->pos[2], 0, 255);
  818.  
  819.   gimp_color_select_draw_z_marker (select, NULL);
  820.   gimp_color_select_update (select,
  821.                             UPDATE_VALUES | UPDATE_XY_COLOR | UPDATE_CALLER);
  822.  
  823.   return TRUE;
  824. }
  825.  
  826. static void
  827. gimp_color_select_image_fill (GtkWidget           *preview,
  828.                               ColorSelectFillType  fill_type,
  829.                               const GimpHSV       *hsv,
  830.                               const GimpRGB       *rgb)
  831. {
  832.   ColorSelectFill csf;
  833.  
  834.   csf.update = update_procs[fill_type];
  835.  
  836.   csf.width  = preview->allocation.width;
  837.   csf.height = preview->allocation.height;
  838.   csf.hsv    = *hsv;
  839.   csf.rgb    = *rgb;
  840.  
  841.   csf.buffer = g_alloca (csf.width * 3);
  842.  
  843.   for (csf.y = 0; csf.y < csf.height; csf.y++)
  844.     {
  845.       {
  846.         if (csf.update)
  847.           (* csf.update) (&csf);
  848.  
  849.         gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
  850.                                 0, csf.y, csf.width, 1,
  851.                                 GIMP_RGB_IMAGE,
  852.                                 csf.buffer, csf.width * 3);
  853.       }
  854.     }
  855. }
  856.  
  857. static void
  858. gimp_color_select_draw_z_marker (GimpColorSelect *select,
  859.                                  GdkRectangle    *clip)
  860. {
  861.   gint width;
  862.   gint height;
  863.   gint y;
  864.   gint minx;
  865.   gint miny;
  866.  
  867.   if (! select->gc)
  868.     return;
  869.  
  870.   width  = select->z_color->allocation.width;
  871.   height = select->z_color->allocation.height;
  872.  
  873.   if (width < 1 || height < 1)
  874.     return;
  875.  
  876.   y = (height - 1) - ((height - 1) * select->pos[2]) / 255;
  877.  
  878.   minx = 0;
  879.   miny = 0;
  880.  
  881.   if (clip)
  882.     {
  883.       width  = MIN (width,  clip->x + clip->width);
  884.       height = MIN (height, clip->y + clip->height);
  885.       minx   = MAX (0, clip->x);
  886.       miny   = MAX (0, clip->y);
  887.     }
  888.  
  889.   if (y >= miny && y < height)
  890.     {
  891.       gdk_gc_set_function (select->gc, GDK_INVERT);
  892.       gdk_draw_line (select->z_color->window,
  893.                      select->gc, minx, y, width - 1, y);
  894.       gdk_gc_set_function (select->gc, GDK_COPY);
  895.     }
  896. }
  897.  
  898. static void
  899. gimp_color_select_draw_xy_marker (GimpColorSelect *select,
  900.                                   GdkRectangle    *clip)
  901. {
  902.   gint width;
  903.   gint height;
  904.   gint x, y;
  905.   gint minx, miny;
  906.  
  907.   if (! select->gc)
  908.     return;
  909.  
  910.   width  = select->xy_color->allocation.width;
  911.   height = select->xy_color->allocation.height;
  912.  
  913.   if (width < 1 || height < 1)
  914.     return;
  915.  
  916.   x = ((width - 1) * select->pos[0]) / 255;
  917.   y = (height - 1) - ((height - 1) * select->pos[1]) / 255;
  918.  
  919.   minx = 0;
  920.   miny = 0;
  921.  
  922.   gdk_gc_set_function (select->gc, GDK_INVERT);
  923.  
  924.   if (clip)
  925.     {
  926.       width  = MIN (width,  clip->x + clip->width);
  927.       height = MIN (height, clip->y + clip->height);
  928.       minx   = MAX (0, clip->x);
  929.       miny   = MAX (0, clip->y);
  930.     }
  931.  
  932.   if (y >= miny && y < height)
  933.     gdk_draw_line (select->xy_color->window,
  934.                    select->gc, minx, y, width - 1, y);
  935.  
  936.   if (x >= minx && x < width)
  937.     gdk_draw_line (select->xy_color->window,
  938.                    select->gc, x, miny, x, height - 1);
  939.  
  940.   gdk_gc_set_function (select->gc, GDK_COPY);
  941. }
  942.  
  943. static void
  944. color_select_update_red (ColorSelectFill *csf)
  945. {
  946.   guchar *p;
  947.   gint    i, r;
  948.  
  949.   p = csf->buffer;
  950.  
  951.   r = (csf->height - csf->y + 1) * 255 / csf->height;
  952.  
  953.   if (r < 0)
  954.     r = 0;
  955.   if (r > 255)
  956.     r = 255;
  957.  
  958.   for (i = 0; i < csf->width; i++)
  959.     {
  960.       *p++ = r;
  961.       *p++ = 0;
  962.       *p++ = 0;
  963.     }
  964. }
  965.  
  966. static void
  967. color_select_update_green (ColorSelectFill *csf)
  968. {
  969.   guchar *p;
  970.   gint    i, g;
  971.  
  972.   p = csf->buffer;
  973.  
  974.   g = (csf->height - csf->y + 1) * 255 / csf->height;
  975.  
  976.   if (g < 0)
  977.     g = 0;
  978.   if (g > 255)
  979.     g = 255;
  980.  
  981.   for (i = 0; i < csf->width; i++)
  982.     {
  983.       *p++ = 0;
  984.       *p++ = g;
  985.       *p++ = 0;
  986.     }
  987. }
  988.  
  989. static void
  990. color_select_update_blue (ColorSelectFill *csf)
  991. {
  992.   guchar *p;
  993.   gint    i, b;
  994.  
  995.   p = csf->buffer;
  996.  
  997.   b = (csf->height - csf->y + 1) * 255 / csf->height;
  998.  
  999.   if (b < 0)
  1000.     b = 0;
  1001.   if (b > 255)
  1002.     b = 255;
  1003.  
  1004.   for (i = 0; i < csf->width; i++)
  1005.     {
  1006.       *p++ = 0;
  1007.       *p++ = 0;
  1008.       *p++ = b;
  1009.     }
  1010. }
  1011.  
  1012. static void
  1013. color_select_update_hue (ColorSelectFill *csf)
  1014. {
  1015.   guchar *p;
  1016.   gfloat  h, f;
  1017.   gint    r, g, b;
  1018.   gint    i;
  1019.  
  1020.   p = csf->buffer;
  1021.  
  1022.   h = csf->y * 360.0 / csf->height;
  1023.  
  1024.   h = CLAMP (360 - h, 0, 360);
  1025.  
  1026.   h /= 60;
  1027.   f = (h - (int) h) * 255;
  1028.  
  1029.   r = g = b = 0;
  1030.  
  1031.   switch ((int) h)
  1032.     {
  1033.     case 0:
  1034.       r = 255;
  1035.       g = f;
  1036.       b = 0;
  1037.       break;
  1038.     case 1:
  1039.       r = 255 - f;
  1040.       g = 255;
  1041.       b = 0;
  1042.       break;
  1043.     case 2:
  1044.       r = 0;
  1045.       g = 255;
  1046.       b = f;
  1047.       break;
  1048.     case 3:
  1049.       r = 0;
  1050.       g = 255 - f;
  1051.       b = 255;
  1052.       break;
  1053.     case 4:
  1054.       r = f;
  1055.       g = 0;
  1056.       b = 255;
  1057.       break;
  1058.     case 5:
  1059.       r = 255;
  1060.       g = 0;
  1061.       b = 255 - f;
  1062.       break;
  1063.     }
  1064.  
  1065.   for (i = 0; i < csf->width; i++)
  1066.     {
  1067.       *p++ = r;
  1068.       *p++ = g;
  1069.       *p++ = b;
  1070.     }
  1071. }
  1072.  
  1073. static void
  1074. color_select_update_saturation (ColorSelectFill *csf)
  1075. {
  1076.   guchar *p;
  1077.   gint    s;
  1078.   gint    i;
  1079.  
  1080.   p = csf->buffer;
  1081.  
  1082.   s = csf->y * 255 / csf->height;
  1083.  
  1084.   if (s < 0)
  1085.     s = 0;
  1086.   if (s > 255)
  1087.     s = 255;
  1088.  
  1089.   s = 255 - s;
  1090.  
  1091.   for (i = 0; i < csf->width; i++)
  1092.     {
  1093.       *p++ = s;
  1094.       *p++ = s;
  1095.       *p++ = s;
  1096.     }
  1097. }
  1098.  
  1099. static void
  1100. color_select_update_value (ColorSelectFill *csf)
  1101. {
  1102.   guchar *p;
  1103.   gint    v;
  1104.   gint    i;
  1105.  
  1106.   p = csf->buffer;
  1107.  
  1108.   v = csf->y * 255 / csf->height;
  1109.  
  1110.   if (v < 0)
  1111.     v = 0;
  1112.   if (v > 255)
  1113.     v = 255;
  1114.  
  1115.   v = 255 - v;
  1116.  
  1117.   for (i = 0; i < csf->width; i++)
  1118.     {
  1119.       *p++ = v;
  1120.       *p++ = v;
  1121.       *p++ = v;
  1122.     }
  1123. }
  1124.  
  1125. static void
  1126. color_select_update_red_green (ColorSelectFill *csf)
  1127. {
  1128.   guchar *p;
  1129.   gint    i, r, b;
  1130.   gfloat  g, dg;
  1131.  
  1132.   p = csf->buffer;
  1133.  
  1134.   b = ROUND (csf->rgb.b * 255.0);
  1135.   r = (csf->height - csf->y + 1) * 255 / csf->height;
  1136.  
  1137.   if (r < 0)
  1138.     r = 0;
  1139.   if (r > 255)
  1140.     r = 255;
  1141.  
  1142.   g = 0;
  1143.   dg = 255.0 / csf->width;
  1144.  
  1145.   for (i = 0; i < csf->width; i++)
  1146.     {
  1147.       *p++ = r;
  1148.       *p++ = g;
  1149.       *p++ = b;
  1150.  
  1151.       g += dg;
  1152.     }
  1153. }
  1154.  
  1155. static void
  1156. color_select_update_red_blue (ColorSelectFill *csf)
  1157. {
  1158.   guchar *p;
  1159.   gint    i, r, g;
  1160.   gfloat  b, db;
  1161.  
  1162.   p = csf->buffer;
  1163.  
  1164.   g = ROUND (csf->rgb.g * 255.0);
  1165.   r = (csf->height - csf->y + 1) * 255 / csf->height;
  1166.  
  1167.   if (r < 0)
  1168.     r = 0;
  1169.   if (r > 255)
  1170.     r = 255;
  1171.  
  1172.   b = 0;
  1173.   db = 255.0 / csf->width;
  1174.  
  1175.   for (i = 0; i < csf->width; i++)
  1176.     {
  1177.       *p++ = r;
  1178.       *p++ = g;
  1179.       *p++ = b;
  1180.  
  1181.       b += db;
  1182.     }
  1183. }
  1184.  
  1185. static void
  1186. color_select_update_green_blue (ColorSelectFill *csf)
  1187. {
  1188.   guchar *p;
  1189.   gint    i, g, r;
  1190.   gfloat  b, db;
  1191.  
  1192.   p = csf->buffer;
  1193.  
  1194.   r = ROUND (csf->rgb.r * 255.0);
  1195.   g = (csf->height - csf->y + 1) * 255 / csf->height;
  1196.  
  1197.   if (g < 0)
  1198.     g = 0;
  1199.   if (g > 255)
  1200.     g = 255;
  1201.  
  1202.   b = 0;
  1203.   db = 255.0 / csf->width;
  1204.  
  1205.   for (i = 0; i < csf->width; i++)
  1206.     {
  1207.       *p++ = r;
  1208.       *p++ = g;
  1209.       *p++ = b;
  1210.  
  1211.       b += db;
  1212.     }
  1213. }
  1214.  
  1215. static void
  1216. color_select_update_hue_saturation (ColorSelectFill *csf)
  1217. {
  1218.   guchar *p;
  1219.   gfloat  h, v, s, ds;
  1220.   gint    f;
  1221.   gint    i;
  1222.  
  1223.   p = csf->buffer;
  1224.  
  1225.   h = 360 - (csf->y * 360 / csf->height);
  1226.  
  1227.   if (h < 0)
  1228.     h = 0;
  1229.   if (h > 359)
  1230.     h = 359;
  1231.  
  1232.   h /= 60;
  1233.   f = (h - (int) h) * 255;
  1234.  
  1235.   s = 0;
  1236.   ds = 1.0 / csf->width;
  1237.  
  1238.   v = csf->hsv.v;
  1239.  
  1240.   switch ((int) h)
  1241.     {
  1242.     case 0:
  1243.       for (i = 0; i < csf->width; i++)
  1244.         {
  1245.           *p++ = v * 255;
  1246.           *p++ = v * (255 - (s * (255 - f)));
  1247.           *p++ = v * 255 * (1 - s);
  1248.  
  1249.           s += ds;
  1250.         }
  1251.       break;
  1252.     case 1:
  1253.       for (i = 0; i < csf->width; i++)
  1254.         {
  1255.           *p++ = v * (255 - s * f);
  1256.           *p++ = v * 255;
  1257.           *p++ = v * 255 * (1 - s);
  1258.  
  1259.           s += ds;
  1260.         }
  1261.       break;
  1262.     case 2:
  1263.       for (i = 0; i < csf->width; i++)
  1264.         {
  1265.           *p++ = v * 255 * (1 - s);
  1266.           *p++ = v *255;
  1267.           *p++ = v * (255 - (s * (255 - f)));
  1268.  
  1269.           s += ds;
  1270.         }
  1271.       break;
  1272.     case 3:
  1273.       for (i = 0; i < csf->width; i++)
  1274.         {
  1275.           *p++ = v * 255 * (1 - s);
  1276.           *p++ = v * (255 - s * f);
  1277.           *p++ = v * 255;
  1278.  
  1279.           s += ds;
  1280.         }
  1281.       break;
  1282.     case 4:
  1283.       for (i = 0; i < csf->width; i++)
  1284.         {
  1285.           *p++ = v * (255 - (s * (255 - f)));
  1286.           *p++ = v * (255 * (1 - s));
  1287.           *p++ = v * 255;
  1288.  
  1289.           s += ds;
  1290.         }
  1291.       break;
  1292.     case 5:
  1293.       for (i = 0; i < csf->width; i++)
  1294.         {
  1295.           *p++ = v * 255;
  1296.           *p++ = v * 255 * (1 - s);
  1297.           *p++ = v * (255 - s * f);
  1298.  
  1299.           s += ds;
  1300.         }
  1301.       break;
  1302.     }
  1303. }
  1304.  
  1305. static void
  1306. color_select_update_hue_value (ColorSelectFill *csf)
  1307. {
  1308.   guchar *p;
  1309.   gfloat  h, v, dv, s;
  1310.   gint    f;
  1311.   gint    i;
  1312.  
  1313.   p = csf->buffer;
  1314.  
  1315.   h = 360 - (csf->y * 360 / csf->height);
  1316.  
  1317.   if (h < 0)
  1318.     h = 0;
  1319.   if (h > 359)
  1320.     h = 359;
  1321.  
  1322.   h /= 60;
  1323.   f = (h - (int) h) * 255;
  1324.  
  1325.   v = 0;
  1326.   dv = 1.0 / csf->width;
  1327.  
  1328.   s = csf->hsv.s;
  1329.  
  1330.   switch ((int) h)
  1331.     {
  1332.     case 0:
  1333.       for (i = 0; i < csf->width; i++)
  1334.         {
  1335.           *p++ = v * 255;
  1336.           *p++ = v * (255 - (s * (255 - f)));
  1337.           *p++ = v * 255 * (1 - s);
  1338.  
  1339.           v += dv;
  1340.         }
  1341.       break;
  1342.     case 1:
  1343.       for (i = 0; i < csf->width; i++)
  1344.         {
  1345.           *p++ = v * (255 - s * f);
  1346.           *p++ = v * 255;
  1347.           *p++ = v * 255 * (1 - s);
  1348.  
  1349.           v += dv;
  1350.         }
  1351.       break;
  1352.     case 2:
  1353.       for (i = 0; i < csf->width; i++)
  1354.         {
  1355.           *p++ = v * 255 * (1 - s);
  1356.           *p++ = v *255;
  1357.           *p++ = v * (255 - (s * (255 - f)));
  1358.  
  1359.           v += dv;
  1360.         }
  1361.       break;
  1362.     case 3:
  1363.       for (i = 0; i < csf->width; i++)
  1364.         {
  1365.           *p++ = v * 255 * (1 - s);
  1366.           *p++ = v * (255 - s * f);
  1367.           *p++ = v * 255;
  1368.  
  1369.           v += dv;
  1370.         }
  1371.       break;
  1372.     case 4:
  1373.       for (i = 0; i < csf->width; i++)
  1374.         {
  1375.           *p++ = v * (255 - (s * (255 - f)));
  1376.           *p++ = v * (255 * (1 - s));
  1377.           *p++ = v * 255;
  1378.  
  1379.           v += dv;
  1380.         }
  1381.       break;
  1382.     case 5:
  1383.       for (i = 0; i < csf->width; i++)
  1384.         {
  1385.           *p++ = v * 255;
  1386.           *p++ = v * 255 * (1 - s);
  1387.           *p++ = v * (255 - s * f);
  1388.  
  1389.           v += dv;
  1390.         }
  1391.       break;
  1392.     }
  1393. }
  1394.  
  1395. static void
  1396. color_select_update_saturation_value (ColorSelectFill *csf)
  1397. {
  1398.   guchar *p;
  1399.   gfloat  h, v, dv, s;
  1400.   gint    f;
  1401.   gint    i;
  1402.  
  1403.   p = csf->buffer;
  1404.  
  1405.   s = (gfloat) csf->y / csf->height;
  1406.  
  1407.   if (s < 0)
  1408.     s = 0;
  1409.   if (s > 1)
  1410.     s = 1;
  1411.  
  1412.   s = 1 - s;
  1413.  
  1414.   h = (gfloat) csf->hsv.h * 360.0;
  1415.   if (h >= 360)
  1416.     h -= 360;
  1417.   h /= 60;
  1418.   f = (h - (gint) h) * 255;
  1419.  
  1420.   v = 0;
  1421.   dv = 1.0 / csf->width;
  1422.  
  1423.   switch ((gint) h)
  1424.     {
  1425.     case 0:
  1426.       for (i = 0; i < csf->width; i++)
  1427.         {
  1428.           *p++ = v * 255;
  1429.           *p++ = v * (255 - (s * (255 - f)));
  1430.           *p++ = v * 255 * (1 - s);
  1431.  
  1432.           v += dv;
  1433.         }
  1434.       break;
  1435.     case 1:
  1436.       for (i = 0; i < csf->width; i++)
  1437.         {
  1438.           *p++ = v * (255 - s * f);
  1439.           *p++ = v * 255;
  1440.           *p++ = v * 255 * (1 - s);
  1441.  
  1442.           v += dv;
  1443.         }
  1444.       break;
  1445.     case 2:
  1446.       for (i = 0; i < csf->width; i++)
  1447.         {
  1448.           *p++ = v * 255 * (1 - s);
  1449.           *p++ = v *255;
  1450.           *p++ = v * (255 - (s * (255 - f)));
  1451.  
  1452.           v += dv;
  1453.         }
  1454.       break;
  1455.     case 3:
  1456.       for (i = 0; i < csf->width; i++)
  1457.         {
  1458.           *p++ = v * 255 * (1 - s);
  1459.           *p++ = v * (255 - s * f);
  1460.           *p++ = v * 255;
  1461.  
  1462.           v += dv;
  1463.         }
  1464.       break;
  1465.     case 4:
  1466.       for (i = 0; i < csf->width; i++)
  1467.         {
  1468.           *p++ = v * (255 - (s * (255 - f)));
  1469.           *p++ = v * (255 * (1 - s));
  1470.           *p++ = v * 255;
  1471.  
  1472.           v += dv;
  1473.         }
  1474.       break;
  1475.     case 5:
  1476.       for (i = 0; i < csf->width; i++)
  1477.         {
  1478.           *p++ = v * 255;
  1479.           *p++ = v * 255 * (1 - s);
  1480.           *p++ = v * (255 - s * f);
  1481.  
  1482.           v += dv;
  1483.         }
  1484.       break;
  1485.     }
  1486. }
  1487.