 /*
  * Khoros: $Id: color.c,v 1.1 1991/05/10 15:56:56 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: color.c,v 1.1 1991/05/10 15:56:56 khoros Exp $";
#endif

 /*
  * $Log: color.c,v $
 * Revision 1.1  1991/05/10  15:56:56  khoros
 * Initial revision
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 *
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "X3D.h"	
#include "colorspace.h"	


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name: color.c 				      <<<<
   >>>>                                                       <<<<
   >>>>   description: Color Allocation routines	      <<<<
   >>>>                                                       <<<<
   >>>>      routines:					      <<<<
   >>>>			X3D_allocate_named_color()	      <<<<
   >>>>			X3D_allocate_named_colors()	      <<<<
   >>>>			X3D_allocate_predefined_colors()      <<<<
   >>>>                                                       <<<<
   >>>> modifications:					      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

/************************************************************
*
*  MODULE NAME:  X3D_allocate_named_color
*
*      PURPOSE:  Allocates an XColor structure based on the color
*		 name passed in.  If the color cannot be
*		 allocated, the XColor structure passed back will be Mono.
*		 Error statements only printed out when in verbose mode.
*
*        INPUT: display    - pointer to Display structure
*		colorname  - string specifying desired color
*		Color	   - pointer to the XColor struct to be filled in
*		verbose    - pass TRUE for error messages, FALSE for no error
*			     messages.
*
*       OUTPUT: returns the XColor structure allocated in Color.
*		returns TRUE on success, False on failure
*
*    CALLED BY: application program
*
*   WRITTEN BY: Danielle Argiro
*
*************************************************************/

int X3D_allocate_named_color(display, colorname, Color, verbose, monochrome)
Display *display;
char   *colorname;
XColor *Color;
int    verbose;
int    monochrome;
{
	int      screen;
        XColor   exact_color_def, screen_color_def, Mono;
	Colormap colormap;

	screen = XDefaultScreen(display);
	colormap  = XDefaultColormap(display, screen);

	if (XDisplayPlanes(display, screen) < 4)
	{
	    if (monochrome == X3D_WHITE)
	    	Mono.pixel = WhitePixel(display, screen);
	    else
	    	Mono.pixel = BlackPixel(display, screen);
	    Mono.flags = DoRed | DoBlue | DoGreen;

	    if (XQueryColor(display, colormap, &Mono))
	    {
	        if (verbose)
	        {
	       	    fprintf(stderr, "X3D_allocate_named_color:\n");
		    fprintf(stderr, "Couldn't look up white XColor struct\n");
	        }
	    }
	    *Color = Mono;
            return(1);
	}

        if (XAllocNamedColor(display, colormap,
			     colorname, &screen_color_def, 
			     &exact_color_def))
	{
	     *Color = screen_color_def;
	     return(true);
	}
	else return(false);

}



/************************************************************
*
*  MODULE NAME:  X3D_allocate_named_colors
*
*      PURPOSE:  Allocates an XColor array based on the color
*		 names passed in.  If a certain color cannot be
*		 allocated, the Color[] element corresponding to
*		 that colornames[] string will be assigned to 
*		 the XColor indicated by 'monochrome'.
*		 Error statements only printed out when in verbose mode.
*		 When on a monochrome (1 plane or 2 plane) display,
*		 all Colors[] are allocated the XColor
*		 indicated by 'monochrome'.
*
*        INPUT: display    - pointer to Display structure
*		colornames - array of strings specifying desired colors
*		Colors     - array of XColors to be filled in
*		size       - size of the colornames & Colors arrays
*		verbose    - pass TRUE for error messages, FALSE for no error
*			     messages.
*		monochrome - in the event that the application is run
*			     on a monochrome screen, should we assign
*			     Black or White to all colors?
*
*       OUTPUT: returns the number of colors that were actually allocated
*
*    CALLED BY: application program
*
*   WRITTEN BY: Danielle Argiro
*
*************************************************************/

int X3D_allocate_named_colors(display, colornames, Colors, size, 
			      verbose, monochrome)
Display *display;
char  *colornames[];
XColor Colors[];
int    size;
int    verbose;
int    monochrome;
{
	int      count, i, screen;
	Colormap colormap;
	XColor Mono;

	count = 0;
	screen = XDefaultScreen(display);
	colormap  = XDefaultColormap(display, screen);

	if (monochrome == X3D_WHITE)
	    Mono.pixel = WhitePixel(display, screen);
	else
	    Mono.pixel = BlackPixel(display, screen);

	Mono.flags = DoRed | DoBlue | DoGreen;
	if (!(XQueryColor(display, colormap, &Mono)))
	{
	    if (verbose)
	    {
	        fprintf(stderr, "X3D_allocate_named_colors:\n");
	        fprintf(stderr, "Couldn't look up white XColor struct\n");
	    }
	}	

	if (XDisplayPlanes(display, screen) < 4)
	{
	    for (i=0; i < size; i++)
	        Colors[i] = Mono;
	    return(1);
	}

	/*
	 *  now, allocate as many colors as we can.  fill in those that
	 *  can't be allocated as Mono.  print error messages 
	 *  only when in verbose mode.
	 */
	i = 0;
	while (i < size)
	{
		if (X3D_allocate_named_color(display, colornames[i], 
					     &Colors[i], verbose, monochrome))
		    count++;
		else 
		{
		     if (verbose)
		     {
		     	fprintf(stderr, "X3D_allocate_named_colors:\n");
		     	fprintf(stderr, "Couldn't allocate %s\n", 
				colornames[i]);
		     }
		     Colors[i] = Mono;
		}
		i++;
	}

	return(count);

}



/************************************************************
*
*  MODULE NAME:  X3D_allocate_predefined_colors
*
*      PURPOSE:  Allocates an XColor array based on a pre-defined
*		 color scheme.  If a certain color cannot be
*		 allocated, the Color[] element corresponding to
*		 that colornames[] string will be assigned 
*		 according to the value given to 'monochrome'.
*		 Error statements only printed out when in verbose mode.
*		 When on a monochrome (1 plane or 2 plane) display,
*		 all Colors[] are allocated the XColor indicated by 'monochrome'.
*		 When on a 4 plane display, only the first 16 colors
*		 will be allocated;  any remaining XColors in the array
*		 will be allocated the XColor indicated by 'monochrome'.
*
*        INPUT: display    - pointer to the Display structure
*		Colors     - array of XColors to be filled in
*		size       - size of the Colors array
*		verbose    - pass TRUE for error messages, FALSE for no error
*			     messages.
*		monochrome - in the event that the application is run
*			     on a monochrome screen, should we assign
*			     Black or White to all colors?
*
*       OUTPUT: returns the number of colors that were actually allocated
*
*    CALLED BY: application program
*
*   WRITTEN BY: Danielle Argiro
*
*************************************************************/

int X3D_allocate_predefined_colors(display, Colors, size, verbose, monochrome)
Display *display;
XColor Colors[];
int    size;
int    verbose;
int    monochrome;
{
	int      count, i, screen;
        XColor   Mono, xcolor;
	Colormap colormap;
	float  hue, saturation, value;

	count = 0;
	screen = XDefaultScreen(display);
	colormap  = XDefaultColormap(display, screen);

	if (monochrome == X3D_WHITE)
	    Mono.pixel = WhitePixel(display, screen);
	else
	    Mono.pixel = BlackPixel(display, screen);
	Mono.flags = DoRed | DoBlue | DoGreen;

	if (!(XQueryColor(display, colormap, &Mono)))
	{
	    if (verbose)
	    {
	   	fprintf(stderr, "X3D_allocate_predefined_colors:\n");
		fprintf(stderr, "Couldn't look up white XColor struct\n");
	    }
	}

	if (XDisplayPlanes(display, screen) < 4)
	{
	    for (i=0; i < size; i++)
	        Colors[i] = Mono;
	    return(1);
	}
	/*
	 *  now, allocate as many colors as we can.  fill in those that
	 *  can't be allocated as 'Mono' (black or white).  
	 *  print error messages only when in verbose mode.
	 */
	i = 0;
	xcolor.flags = DoRed | DoGreen | DoBlue;
        saturation = value = 1.0;
	while (i < size)
	{
		hue = ((float) i)/size;
                HSV_to_RGB(hue, saturation, value, xcolor);

		if (XAllocColor(display, colormap, &xcolor))
		{
		    Colors[i] = xcolor;
		    count++;
		}
		else 
		{
		     if (verbose)
		     {
		     	fprintf(stderr, "X3D_allocate_predefined_colors:\n");
		     	fprintf(stderr, "Couldn't allocate predefined color %d\n",
				i+1);
		     }
		     Colors[i] = Mono;
		}
		i++;
	}

	return(count);

}


