static gboolean
gimp_brightness_contrast_tool_initialize (GimpTool     *tool,
        GimpDisplay  *display,
        GError      **error)
{
    GimpBrightnessContrastTool *bc_tool  = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
    GimpImage                  *image    = gimp_display_get_image (display);
    GimpDrawable               *drawable = gimp_image_get_active_drawable (image);

    if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
    {
        return FALSE;
    }

    if (gimp_drawable_get_precision (drawable) == GIMP_PRECISION_U8)
    {
        gimp_prop_widget_set_factor (bc_tool->brightness_scale, 127.0, 0);
        gimp_prop_widget_set_factor (bc_tool->contrast_scale,   127.0, 0);
    }
    else
    {
        gimp_prop_widget_set_factor (bc_tool->brightness_scale, 0.5, 3);
        gimp_prop_widget_set_factor (bc_tool->contrast_scale,   0.5, 3);
    }

    return TRUE;
}
static GeglNode *
gimp_brightness_contrast_tool_get_operation (GimpImageMapTool  *im_tool,
                                             GObject          **config)
{
  GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (im_tool);
  GeglNode                   *node;

  node = g_object_new (GEGL_TYPE_NODE,
                       "operation", "gimp:brightness-contrast",
                       NULL);

  bc_tool->config = g_object_new (GIMP_TYPE_BRIGHTNESS_CONTRAST_CONFIG, NULL);

  *config = G_OBJECT (bc_tool->config);

  g_signal_connect_object (bc_tool->config, "notify",
                           G_CALLBACK (brightness_contrast_config_notify),
                           G_OBJECT (bc_tool), 0);

  gegl_node_set (node,
                 "config", bc_tool->config,
                 NULL);

  return node;
}
static void
gimp_brightness_contrast_tool_dialog (GimpImageMapTool *image_map_tool)
{
  GimpBrightnessContrastTool   *bc_tool;
  GimpBrightnessContrastConfig *config;
  GtkWidget                    *main_vbox;
  GtkWidget                    *table;
  GtkWidget                    *button;
  GtkObject                    *data;

  bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (image_map_tool);
  config  = bc_tool->config;

  main_vbox = gimp_image_map_tool_dialog_get_vbox (image_map_tool);

  /*  The table containing sliders  */
  table = gtk_table_new (2, 3, FALSE);
  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
  gtk_widget_show (table);

  /*  Create the brightness scale widget  */
  data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
                               _("_Brightness:"), SLIDER_WIDTH, -1,
                               config->brightness * 127.0,
                               -127.0, 127.0, 1.0, 10.0, 0,
                               TRUE, 0.0, 0.0,
                               NULL, NULL);
  bc_tool->brightness_data = GTK_ADJUSTMENT (data);

  g_signal_connect (data, "value-changed",
                    G_CALLBACK (brightness_contrast_brightness_changed),
                    bc_tool);

  /*  Create the contrast scale widget  */
  data = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
                               _("Con_trast:"), SLIDER_WIDTH, -1,
                               config->contrast * 127.0,
                               -127.0, 127.0, 1.0, 10.0, 0,
                               TRUE, 0.0, 0.0,
                               NULL, NULL);
  bc_tool->contrast_data = GTK_ADJUSTMENT (data);

  g_signal_connect (data, "value-changed",
                    G_CALLBACK (brightness_contrast_contrast_changed),
                    bc_tool);

  button = gimp_stock_button_new (GIMP_STOCK_TOOL_LEVELS,
                                  _("Edit these Settings as Levels"));
  gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
  gtk_widget_show (button);

  g_signal_connect (button, "clicked",
                    G_CALLBACK (brightness_contrast_to_levels_callback),
                    bc_tool);
}
static void
gimp_brightness_contrast_tool_map (GimpImageMapTool *im_tool)
{
  GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (im_tool);

  brightness_contrast_lut_setup (bc_tool->lut,
                                 bc_tool->config->brightness / 2.0,
                                 bc_tool->config->contrast,
                                 gimp_drawable_bytes (im_tool->drawable));
}
static void
gimp_brightness_contrast_tool_finalize (GObject *object)
{
  GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (object);

  if (bc_tool->lut)
    {
      gimp_lut_free (bc_tool->lut);
      bc_tool->lut = NULL;
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GeglNode *
gimp_brightness_contrast_tool_get_operation (GimpImageMapTool  *im_tool,
        GObject          **config,
        gchar            **undo_desc)
{
    GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (im_tool);

    bc_tool->config = g_object_new (GIMP_TYPE_BRIGHTNESS_CONTRAST_CONFIG, NULL);

    *config = G_OBJECT (bc_tool->config);

    return gegl_node_new_child (NULL,
                                "operation", "gimp:brightness-contrast",
                                "config",    bc_tool->config,
                                NULL);
}
static void
gimp_brightness_contrast_tool_motion (GimpTool         *tool,
                                      const GimpCoords *coords,
                                      guint32           time,
                                      GdkModifierType   state,
                                      GimpDisplay      *display)
{
    GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);

    bc_tool->dx =   (coords->x - bc_tool->x);
    bc_tool->dy = - (coords->y - bc_tool->y);

    g_object_set (bc_tool->config,
                  "brightness", CLAMP (bc_tool->dy, -127.0, 127.0) / 127.0,
                  "contrast",   CLAMP (bc_tool->dx, -127.0, 127.0) / 127.0,
                  NULL);
}
static void
gimp_brightness_contrast_tool_button_press (GimpTool            *tool,
        const GimpCoords    *coords,
        guint32              time,
        GdkModifierType      state,
        GimpButtonPressType  press_type,
        GimpDisplay         *display)
{
    GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);

    bc_tool->x  = coords->x - bc_tool->config->contrast   * 127.0;
    bc_tool->y  = coords->y + bc_tool->config->brightness * 127.0;
    bc_tool->dx =   bc_tool->config->contrast   * 127.0;
    bc_tool->dy = - bc_tool->config->brightness * 127.0;

    gimp_tool_control_activate (tool->control);
    tool->display = display;
}
static void
gimp_brightness_contrast_tool_button_release (GimpTool              *tool,
        const GimpCoords      *coords,
        guint32                time,
        GdkModifierType        state,
        GimpButtonReleaseType  release_type,
        GimpDisplay           *display)
{
    GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
    GimpImageMapTool           *im_tool = GIMP_IMAGE_MAP_TOOL (tool);

    gimp_tool_control_halt (tool->control);

    if (bc_tool->dx == 0 && bc_tool->dy == 0)
        return;

    if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
        gimp_config_reset (GIMP_CONFIG (bc_tool->config));

    gimp_image_map_tool_preview (im_tool);
}
static void
gimp_brightness_contrast_tool_dialog (GimpImageMapTool *image_map_tool)
{
    GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (image_map_tool);
    GtkWidget                  *main_vbox;
    GtkWidget                  *scale;
    GtkWidget                  *button;

    main_vbox = gimp_image_map_tool_dialog_get_vbox (image_map_tool);

    /*  Create the brightness scale widget  */
    scale = gimp_prop_spin_scale_new (image_map_tool->config, "brightness",
                                      _("_Brightness"), 1.0 / 127.0, 10.0 / 127.0,
                                      0);
    gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0);
    gtk_widget_show (scale);

    bc_tool->brightness_scale = scale;

    /*  Create the contrast scale widget  */
    scale = gimp_prop_spin_scale_new (image_map_tool->config, "contrast",
                                      _("_Contrast"), 1.0 / 127.0, 10.0 / 127.0,
                                      0);
    gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0);
    gtk_widget_show (scale);

    bc_tool->contrast_scale = scale;

    button = gimp_stock_button_new (GIMP_STOCK_TOOL_LEVELS,
                                    _("Edit these Settings as Levels"));
    gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
    gtk_widget_show (button);

    g_signal_connect (button, "clicked",
                      G_CALLBACK (brightness_contrast_to_levels_callback),
                      image_map_tool);
}
static gboolean
gimp_brightness_contrast_tool_initialize (GimpTool     *tool,
                                          GimpDisplay  *display,
                                          GError      **error)
{
  GimpBrightnessContrastTool *bc_tool  = GIMP_BRIGHTNESS_CONTRAST_TOOL (tool);
  GimpImage                  *image    = gimp_display_get_image (display);
  GimpDrawable               *drawable = gimp_image_get_active_drawable (image);

  if (! drawable)
    return FALSE;

  if (gimp_drawable_is_indexed (drawable))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			   _("Brightness-Contrast does not operate "
			     "on indexed layers."));
      return FALSE;
    }

  gimp_config_reset (GIMP_CONFIG (bc_tool->config));

  return GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error);
}