/* GTK Insensitive tool
 *
 * This is a plug-in for the GIMP 2.0
 *
 * Copyright (C) Jaap Haitsma
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (version 2) as 
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* This plug-in (de)interlaces all layers of a film. 
 */

/*
 * Installation:
 * gimptool --install gtk_insensitive.c
 *
 * Enjoy!
 */


#include <stdio.h>
#include <string.h>
#include <libgimp/gimp.h>


#define PLUG_IN_NAME    "GTK Insensitive"
#define PLUG_IN_VERSION "GTK Insensitive 0.1"
#define PLUG_IN_DATE    "23-10-2004"



/* status of parameter input: if TRUE: use plug-in; if FALSE: cancel */
gint parameter_ok=FALSE;



/********************************************************************/
/* Prototypes                                                       */
/********************************************************************/

/* communication to the GIMP */
static void query(void);

static void run(const gchar      *name,
                 gint              nparams,
                 const GimpParam  *param,
                 gint              *nreturn_vals,
                 GimpParam         **return_vals);

/* modify image to insensitive... */
static void gtk_insensitive (GimpDrawable *drawable);

GimpPlugInInfo PLUG_IN_INFO =
{
  NULL,   /* init_proc  */
  NULL,   /* quit_proc  */
  query,  /* query_proc */
  run     /* run_proc   */
}; 


MAIN()

/* communication to the GIMP */
static void query(void)
{
    static GimpParamDef params[] =
    {
        { GIMP_PDB_INT32,    "run_mode",      "Interactive,non-interactive"},
        { GIMP_PDB_IMAGE,    "image_id",      "Input image" },
        { GIMP_PDB_DRAWABLE, "drawable_id",   "Input drawable" }
    };

    static GimpParamDef *return_vals = NULL;
    static int nparams = sizeof(params)/sizeof(params[0]);
    static int nreturn_vals = 0;
  

    gimp_install_procedure("plug_in_"PLUG_IN_NAME,
                           "makes image insensitive",
                           "This plug-in makes the image (e.g. a button) insensitive/disabled",
                           "Jaap Haitsma",
                           "Jaap Haitsma",
                           PLUG_IN_DATE,
                           "<Image>/Filters/Generic/GTK Insensitive",
                           "RGB*",
                           GIMP_PLUGIN,
                           nparams,
                           nreturn_vals,
                           params,
                           return_vals);
}


static void run(const gchar     *name,
                 gint             nparams,
                 const GimpParam  *param,
                 gint              *nreturn_vals,
                 GimpParam         **return_vals)
{
    static GimpParam values[1];
    GimpDrawable *drawable;
    GimpRunMode run_mode;
    GimpPDBStatusType status = GIMP_PDB_SUCCESS;

    gint32 image_ID;

    run_mode = param[0].data.d_int32;

    /*  Get the specified drawable  */
    drawable = gimp_drawable_get (param[2].data.d_drawable);
    image_ID = param[1].data.d_image;

    /*  Make sure that the drawable is RGB color  */
    if (gimp_drawable_is_rgb (drawable->drawable_id))
    {
        gimp_progress_init ("Making Insensitive...");
        gimp_tile_cache_ntiles(2 * (drawable->width / gimp_tile_width () + 1));
        gtk_insensitive (drawable);

        if (run_mode != GIMP_RUN_NONINTERACTIVE)
	       gimp_displays_flush ();
    }
    else
    {
        status = GIMP_PDB_EXECUTION_ERROR;
    }

    *nreturn_vals = 1;
    *return_vals = values;

    values[0].type = GIMP_PDB_STATUS;
    values[0].data.d_status = status;

    gimp_drawable_detach (drawable);
}

static void
gtk_insensitive (GimpDrawable *drawable)
{
    GimpPixelRgn src_rgn, dest_rgn;
    guchar *src, *s;
    guchar *dest, *d;
    gint    progress, max_progress;
    gint    has_alpha, red, green, blue, alpha;
    gint    x1, y1, x2, y2;
    gint    x, y, cur_x, cur_y;
    gpointer pr;

    /* Get selection area */
    gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
    has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

    red = 0; green = 1; blue = 2;

    alpha = (has_alpha) ? drawable->bpp - 1 : drawable->bpp;

    /* Initialize progress */
    progress = 0;
    max_progress = (x2 - x1) * (y2 - y1);

    /* substitute pixel vales */
    gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
    gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);

#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#define DARK_FACTOR 0.7
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
#define CLAMP_UCHAR(v) (t = (v), CLAMP (t, 0, 255))
#define SATURATE(v) ((1.0 - saturation) * intensity + saturation * (v))

    for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
         pr != NULL;
         pr = gimp_pixel_rgns_process (pr))
    {
        src = src_rgn.data;
        dest = dest_rgn.data;
        
        for (y = 0; y < src_rgn.h; y++)
        {
	        s = src;
	        d = dest;
            cur_y = src_rgn.y + y;
	        for (x = 0; x < src_rgn.w; x++)
	        {
                cur_x = src_rgn.x + x;
                guchar intensity = INTENSITY (s[red], s[green], s[blue]);
                if ((cur_x+cur_y) % 2 == 0) 
                {
                    d[red] = intensity / 2 + 127;
                    d[green] = d[red];
                    d[blue] = d[red];
                } 
                else
                {
                    gfloat saturation = 0.8;
                    gint t;
                    d[red] = CLAMP_UCHAR ((SATURATE (s[red])) * DARK_FACTOR);
					d[green] = CLAMP_UCHAR ((SATURATE (s[green])) * DARK_FACTOR);
                    d[blue] = CLAMP_UCHAR ((SATURATE (s[blue])) * DARK_FACTOR);
                }

	            if (has_alpha)
                {
                    d[alpha] = s[alpha];
                }
                s += src_rgn.bpp;
                d += dest_rgn.bpp;
            }
            src += src_rgn.rowstride;
	        dest += dest_rgn.rowstride;
        }

        progress += src_rgn.w * src_rgn.h;

        gimp_progress_update ((double) progress / (double) max_progress);
    }

    /*  update the region  */
    gimp_drawable_flush (drawable);
    gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
    gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
}
