/*
 * libcolorblind - Pixel Filter for colorblind accessibility
 *
 * This is in Public Domain
 *
 * This library provides an unified way to recalculate colors
 * in order to present alternative views on images for colorblind
 * people.
 *
 */

#ifndef COLORBLIND_MAIN
#define COLORBLIND_MAIN

/*
 * This is the list of filter types
 */
enum COLORBLIND_FILTER_TYPE {
        colorblind_filter_t_no_filter,
        colorblind_filter_t_selective_saturate_red,
        colorblind_filter_t_selective_saturate_green,
        colorblind_filter_t_selective_saturate_blue,
        colorblind_filter_t_selective_dessaturate_red,
        colorblind_filter_t_selective_dessaturate_green,
        colorblind_filter_t_selective_dessaturate_blue,
        colorblind_filter_t_hue_shift_positive,
        colorblind_filter_t_hue_shift_negative,
        colorblind_filter_t_selective_saturate,
        colorblind_filter_t_selective_dessaturate,
        colorblind_filter_t_monochrome_others};

/*
 * This is how we deal with the pixels.
 * It's supposed to be binary-compatible with
 * XColor definition from Xlib.
 * This struct is always used as a pointer so
 * libcolorblind doesn't care about it's real
 * size.
 */
typedef struct COLORBLIND_XCOLOR {
        /*
         * The pixel value is not used here.
         * It's here just to be binary compatible
         * with XColor
         */
        unsigned long pixel;
        /*
         * These are the color values
         */
	unsigned short red, green, blue;
} COLORBLIND_XCOLOR;

/*
 * The COLORBLIND_RUNTIME typedef is the runtime object used when
 * applying filters. You can have several instances of it and thus
 * use diferent filters in different images at the same time.
 */
typedef struct COLORBLIND_RUNTIME {
        /*
         * Type of filter to apply
         */
        enum COLORBLIND_FILTER_TYPE filter_type;
        /*
         * Base color for the filter
         * probably choosed interactively by the user.
         */
        COLORBLIND_XCOLOR* base_color;
        /*
         * Used for filters that accepts more than one
         * base color. In this case base_color will be
         * an array
         */
        int base_color_count;
} COLORBLIND_RUNTIME;

/*
 * Now the methods
 */

/*
 * The method colorblind_create, for now, just allocs the COLORBLIND_RUNTIME
 * and returns it to you. But please keep calling it as this method may be
 * used in future versions for something more usefull.
 */
extern COLORBLIND_RUNTIME* colorblind_create();

/*
 * The method colorblind_destroy, for now, just frees the COLORBLIND_RUNTIME.
 * But please keep calling it as this method may be
 * used in future versions for something more usefull.
 */
extern int colorblind_destroy(COLORBLIND_RUNTIME* cbr);

/*
 * This method receives a COLORBLIND_XCOLOR*, filters it and saves the
 * new value in it.  Note that if you're passing the XColor struct,
 * this function will not allocate a new color nor query the colormap
 * to get the pixel value for the new color, and also it won't touch
 * in the pixel value.
 *
 * But this method will return 0 if the color hasn't changed so
 * you can avoid querying the colormap unless it's really needed.
 *
 * This mehod will return a positive integer if the color has been
 * touched (you probably want to set pixel to NULL and allocate the
 * new color before using).
 *
 * If any error occour a negative integer will be returned.
 */
extern int colorblind_filter(COLORBLIND_RUNTIME* cbr, COLORBLIND_XCOLOR* color);

/*
 * This method sets the filter type.
 * Returns 0 if you already have the necessary data needed by this filter.
 */
extern int colorblind_set_filter_type(COLORBLIND_RUNTIME* cbr, enum COLORBLIND_FILTER_TYPE);

/*
 * This method sets the base_color.
 */
extern int colorblind_set_base_color(COLORBLIND_RUNTIME* cbr, COLORBLIND_XCOLOR* color);

/*
 * This method sets the base color, but using several colors.
 */
extern int colorblind_set_base_colors(COLORBLIND_RUNTIME* cbr, COLORBLIND_XCOLOR* colors, int count);

/*
 * Removes the base_color. You probably want to do that before freeing the color you were using.
 */
extern int colorblind_remove_base_color(COLORBLIND_RUNTIME* cbr);

#endif
