# include # include #include #include #include #include "defs.h" #include "xws_defs.h" #include "xws_color.h" /* Color function pointers, to be used by the various X driver routines. * These are set to appropriate functions by xws_setup_color(), depending * on the visual type of the display. xws_ctab, xws_cmapin, xws_cmapout, * and xws_bp_color may be NULL, denoting that no function needs to be * called for these tasks. The others are guaranteed to be initialized * after xws_setup_color(). */ int (*xws_ctab)(); /* general color table routine */ void (*xws_cmapin)(), /* swap in device color map if necessary */ (*xws_cmapout)(), /* swap out device color map if necessary */ (*xws_bp_color)(); /* color actions at begin page time */ Pixeltype (*xws_get_pixel)(); /* returns a pixel value from color data */ Pixeltype *(*xws_get_row)(); /* returns a row of pixel values from clrs */ /* Color global variables, private to this file. * ============================================= * * RGB_Cmap, if defined, is always the X Colormap ID for the RGB map * used for direct color metafiles. Cmap is the current colormap in * use on the device's screen. * * For indexed color only, the array DevColor provides a mapping * between gplot's idea of a color index and the corresponding device * color index. The array DevColor is initialized by * *(xws_pcolor_init)(), defined by (*xws_ctab)(), and reset by * (*xws_bp_color)(). DevColor[0] is background. DevColor[1] is * foreground. * * DevMaxIndex is the maximum legal index into DevColor[]. * * The array "Defined" is just an array of boolean flags to keep track of * whether a gplot index is defined or undefined. All color indexes * become undefined at the beginning of each frame in the metafile, by * setting all elements of this array to FALSE, according to CGM standard. * This could be made into a bit vector if you want to conserve memory. * * Gdct is Gplot Default Color Table. Set by Metafile Default Replacement * elements via calls to (*xws_ctab)() before the first call to * xws_bpage(), and set by (*xws_bp_color()) during the first call to * xws_bpage(), the Gdct stores default color table definitions. It is * referenced only on demand, by (*xws_get_pixel)(). * * dev_depth is the number of device planes. */ static Colormap RGB_Cmap; /* direct */ static Colormap Cmap; /* direct */ static XStandardColormap map_info; /* direct */ static Pixeltype DevColor[DEVICE_COLOR_TABLE_SIZE]; /* indexed */ static int DevMaxIndex; /* indexed */ static char Defined[DEVICE_COLOR_TABLE_SIZE]; /* indexed */ static float Gdct[GDCT_SIZE]; /* indexed */ static int dev_depth; /* indexed */ /* Some macros useful in color conversion */ /* The following implements the standard NTSC encoding conversion from an RGB value to an intensity. */ #define rgb_to_intensity(r,g,b) ( 0.30*(r) + 0.59*(g) + 0.11*(b) ) /* rgb_to_pixel translates an r, g, b triple (in floats) into a pixel value. It returns a Pixeltype value. The other three macros (r_actual, etc.) return the actual r, g, or b value that the pixel supplied by rgb_to_pixel implies. They each take a float as input and return a float. Note that these routines only work if Cmap==RGB_Cmap (i.e. if a standard colormap is in effect). */ #define bnd(x) ((x<0.0) ? 0.0 : ((x>1.0) ? 1.0 : x)) #define rgb_to_pixel(r,g,b) \ (Pixeltype) ( map_info.base_pixel + \ ((unsigned long)(0.5 + (bnd(r)*map_info.red_max))*map_info.red_mult) + \ ((unsigned long)(0.5 + (bnd(g)*map_info.green_max))*map_info.green_mult)+\ ((unsigned long)(0.5 + (bnd(b)*map_info.blue_max)) * map_info.blue_mult) ) #define r_actual( r ) \ floor( bnd(r)*map_info.red_max + 0.5 )/map_info.red_max #define g_actual( g ) \ floor( bnd(g)*map_info.green_max + 0.5 )/map_info.green_max #define b_actual( b ) \ floor( bnd(b)*map_info.blue_max + 0.5 )/map_info.blue_max /* The following implements a simple monochrome dithering algorithm. The first definitions set up the dither matrices. The macro is used as follows: 'intensity' is a float between 0.0 and 1.0 . i and j are integers which are used to select a particular location in the appropriate dither matrix. */ static char dither_matrix[10][3][3]= { { {0,0,0}, {0,0,0}, {0,0,0} }, { {0,0,0}, {0,1,0}, {0,0,0} }, { {0,0,0}, {1,1,0}, {0,0,0} }, { {0,0,0}, {1,1,0}, {0,1,0} }, { {0,0,0}, {1,1,1}, {0,1,0} }, { {0,0,1}, {1,1,1}, {0,1,0} }, { {0,0,1}, {1,1,1}, {1,1,0} }, { {1,0,1}, {1,1,1}, {1,1,0} }, { {1,0,1}, {1,1,1}, {1,1,1} }, { {1,1,1}, {1,1,1}, {1,1,1} }}; #define mono_dither(intensity,i,j) \ (dither_matrix[ (int)rint( 9*(intensity) ) ][ (j) % 3 ][ (i) % 3 ]) static Colormap currentcolormap() /* This function returns the current window color map */ { XWindowAttributes attrib; if ( XGetWindowAttributes(Dpy,Win,&attrib) ) return( attrib.colormap ); else return( (Colormap)None ); } void xws_scolor_init() /* called once by xws_color_init for initialization of StaticGray visuals */ { DevMaxIndex= (1 << dev_depth) - 1; /* calc max index from no. of planes */ } Pixeltype xws_sget_pixel(r, g, b, index) /* supply a pixel value */ float r, g, b; /* requested r,g,b values for direct color */ int index; /* requested color index for indexed color */ /* This routine returns a pixel value for StaticGray visuals */ { return( (Pixeltype)(DevMaxIndex*rgb_to_intensity(r,g,b)) ); } Pixeltype * xws_sget_row(rarray,garray,barray,iarray,ndim,row) float *rarray, *garray, *barray; /* the color arrays */ int *iarray; /* array of indices */ int ndim, /* dimension of input arrays */ row; /* current row number */ /* This routine returns a row of pixels for StaticGray visuals. */ { static Pixeltype *results= NULL; register Pixeltype *pix; Pixeltype *endpix; register int index; register float *cptr; register float r, g, b; if (row==0) /* This is the first call- allocate memory */ { if (results) free(results); /* called before- free old mem */ if ( (results = (Pixeltype *)calloc( ndim,sizeof(Pixeltype) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_dget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } } /* Calculate pixel values for the whole row */ endpix= results + ndim; for (pix= results; pixc_s_mode == i_c_mode ) { index= ( (*iarray < 0) || (*iarray > CGMClass1->max_c_index) ) ? 0 : *iarray; cptr= CGMClass5->ctab + 3*index; r= *cptr++; g= *cptr++; b= *cptr; } else { r= *rarray; g= *garray; b= *barray; }; /* Translate r, g, b into a pixel value */ *pix= (Pixeltype)(DevMaxIndex*rgb_to_intensity( r, g, b )); /* Move on to next pixel */ rarray++; garray++; barray++; iarray++; } return( results ); } void xws_pcolor_init() /* called once by xws_color_init() for initialization of PseudoColor visuals */ { register int i; Cmap = DefaultColormap(Dpy, Scr); DevMaxIndex = DEVICE_COLOR_TABLE_SIZE - 1; /* The following is necessary in case a previous image with a * different color map has already been drawn, as can happen * when the driver is controlled by a user interface. */ if ( currentcolormap() != Cmap ) { XSetWindowColormap(Dpy, Win, Cmap); XSetWindowColormap(Dpy, Topwin, Cmap); } /* Mark all cells in the device colormap as being unallocated */ for (i=0; i < DEVICE_COLOR_TABLE_SIZE; i++) DevColor[i] = UNALLOCATED; /* Mark all of the default color table as being undefined */ for (i=0; i < GDCT_SIZE; i += 3) Gdct[i] = UNDEFINED_GDCT_COLOR; } void xws_dcolor_init() /* called once by xws_color_init() for initialization of DirectColor visuals */ { /* We assume this is a 24 bit system with 8 bits per color */ map_info.base_pixel= 0; map_info.red_max= 255; map_info.red_mult= 256*256; map_info.green_max= 255; map_info.green_mult= 256; map_info.blue_max= 255; map_info.blue_mult= 1; map_info.colormap= DefaultColormap(Dpy,Scr); RGB_Cmap= map_info.colormap; Cmap= RGB_Cmap; } static void xws_rgbmap(thismap_info) XStandardColormap *thismap_info; /* we use this routine to create a 3,3,2 RGB Best Map colormap */ { Visual *visual; Colormap colormap; visual = DefaultVisual(Dpy, Scr); if (visual->class == PseudoColor) { register int i, n, j, k; int ncolors; XColor color[256]; unsigned short xred[RED_MAX+1], xgreen[GREEN_MAX+1], xblue[BLUE_MAX+1]; /* Fill in color table info struct data */ thismap_info->base_pixel= 0; thismap_info->red_max= RED_MAX; thismap_info->green_max= GREEN_MAX; thismap_info->blue_max= BLUE_MAX; thismap_info->red_mult= (GREEN_MAX+1) * (BLUE_MAX+1); thismap_info->green_mult= BLUE_MAX + 1; thismap_info->blue_mult= 1; colormap = XCreateColormap(Dpy, Win, visual, AllocAll); ncolors = ( RED_MAX + 1 )*( GREEN_MAX+1 )*( BLUE_MAX + 1 ); if ( ncolors > visual->map_entries ) ncolors= visual->map_entries; for (i=0; i <= RED_MAX; i++) xred[i] = (unsigned short) ((i * 65535) / RED_MAX); for (i=0; i <= GREEN_MAX; i++) xgreen[i] = (unsigned short) ((i * 65535) / GREEN_MAX); for (i=0; i <= BLUE_MAX; i++) xblue[i] = (unsigned short) ((i * 65535) / BLUE_MAX); n = thismap_info->base_pixel; for (i=0; i <= RED_MAX; i++) for (j=0; j <= GREEN_MAX; j++) for (k=0; k <= BLUE_MAX; k++) { color[n].pixel = (unsigned long) n; color[n].flags = DoRed | DoGreen | DoBlue; color[n].red = xred[i]; color[n].green = xgreen[j]; color[n++].blue = xblue[k]; } XStoreColors(Dpy, colormap, color, ncolors > visual->map_entries ? visual->map_entries : ncolors ); /* On a GPX, the last two colors are reserved for the cursor. * They cannot be changed by the XStoreColors() call. These * calls to XRecolorCursor() will define indices 254 and 255. */ if ((visual->map_entries == 254) && (ncolors == 256)) { XColor fore, back; /* cursor colors */ back.flags = fore.flags = DoRed | DoGreen | DoBlue; back.red = color[254].red; back.green = color[254].green; back.blue = color[254].blue; fore.red = color[255].red; fore.green = color[255].green; fore.blue = color[255].blue; XRecolorCursor(Dpy, WaitCursor, &fore, &back); XRecolorCursor(Dpy, ReadyCursor, &fore, &back); } } else { /* No color definitions are made for direct color metacode on non - * PseudoColor visual class devices. This is an incomplete * implementation! */ (void)fprintf(stderr, "%s: xws_rgbmap: no color definitions \n", ProgramName ); (void)fprintf(stderr, "for your device visual type.\n" ); /* colormap = NULL; */ } thismap_info->colormap= colormap; } static int server_is_sun_or_hp() /* This routine returns true if the display is a Sun X11/News or HP server */ { char *vendor= XServerVendor(Dpy); return( !strncmp(vendor, "X11/NeWS", 8) || !strncmp(vendor, "Hewlett-Packard Company",23) ); } static int pxl_compare( p1, p2 ) long *p1, *p2; /* This routine is used by qsort to sort a list of pixel values. */ { if (*p1 > *p2) return(-1); if (*p1 == *p2) return(0); return(1); } static void generate_sun_rgbmap(map_info) XStandardColormap *map_info; /* This routine generates an rgb map that won't frighten X11/News */ { int noSet, noGrabbed= 0, noAlloced= 0; XColor *myColors= (XColor *)0; unsigned long pixels[512]; int contig_pixels, start_pixel; int l, m, i, j, k; int found_map_space; /* The actual color map will be the display's default map */ map_info->colormap= currentcolormap(); /* grab as many colours as possible */ /* assume < 512 colours needed */ for (l=256; l>0; l/=2) { if (XAllocColorCells(Dpy, map_info->colormap, False, 0, 0, pixels + noAlloced, l)) { noAlloced += l; } } /* Sort the available pixels */ (void)qsort(pixels, noAlloced, sizeof(long), pxl_compare); /* Find a contiguous stretch to make into a map (top preferred) */ m= 0; found_map_space= 0; while (!found_map_space && m=64) { /* Found a place to put the map */ if (contig_pixels>=125) { /* 5x5x5 case */ map_info->red_max= 4; map_info->green_max= 4; map_info->blue_max= 4; } else if (contig_pixels>=100) { /* 5x5x4 case */ map_info->red_max= 4; map_info->green_max= 4; map_info->blue_max= 3; } else if (contig_pixels>=80) { /* 5x4x4 case */ map_info->red_max= 4; map_info->green_max= 3; map_info->blue_max= 3; } else { /* 4x4x4 case */ map_info->red_max= 3; map_info->green_max= 3; map_info->blue_max= 3; } map_info->blue_mult= 1; map_info->green_mult= map_info->blue_max+1; map_info->red_mult= map_info->green_mult * (map_info->green_max + 1); map_info->base_pixel= start_pixel; noSet = (int) ((map_info->red_max + 1) * (map_info->green_max + 1) * (map_info->blue_max + 1)); found_map_space= 1; } } if (!found_map_space) { fprintf(stderr, "generate_sun_rgbmap: couldn't find color table space!\n"); exit(-1); } map_info->base_pixel= pixels[0] - noSet + 1; /* Free up unneeded color cells */ if (start_pixel != 0) XFreeColors(Dpy, map_info->colormap, pixels, start_pixel, 0); if (start_pixel+noSet < noAlloced) XFreeColors(Dpy, map_info->colormap, pixels+start_pixel+noSet, noAlloced-(start_pixel+noSet), 0); /* make up our default colour table */ if ( !(myColors= (XColor *)malloc(noSet*sizeof(XColor))) ) { fprintf(stderr,"generate_sun_rgbmap: can't allocate %d XColors!\n", noSet); exit(-1); } /* Create the map */ noGrabbed= 0; for (i=0; i<=map_info->red_max; ++i) for (j=0;j<=map_info->green_max; ++j) for (k=0; k<=map_info->blue_max;++k) { myColors[noGrabbed].flags = DoRed | DoGreen | DoBlue; myColors[noGrabbed].pixel = map_info->base_pixel + i * map_info->red_mult + j * map_info->green_mult + k * map_info->blue_mult; /* now fill out the values */ myColors[noGrabbed].red = (unsigned short) ((i * 65535)/ map_info->red_max); myColors[noGrabbed].green = (unsigned short) ((j * 65535) / map_info->green_max); myColors[noGrabbed].blue = (unsigned short) ((k * 65535)/ map_info->blue_max); noGrabbed++; } /* now store the colours, should be OK */ XStoreColors(Dpy, map_info->colormap, myColors, noGrabbed); /* Clean up */ if (myColors) free( (char *)myColors ); } void xws_pbp_color() /* called by xws_bpage() for initialization for each frame */ { register int i; static int last_frame_d_c= 0; if (Metafile_Defaults) { /* First time through, load indexed color default definitions * for indices [0..63]. If the Metafile Defaults Replacement * element has specified definitions for any of these indices, * those definitions will be in place in gplot's "ctab" data. * Otherwise, gplot supplies it's own default color values. * There are always 64 tuples supplied by gplot. */ for (i=0; i < (64 * 3); i++) Gdct[i] = CGMClass5->ctab[i]; Metafile_Defaults = FALSE; } switch ((int) CGMClass2->c_s_mode) { case (i_c_mode): /* Don't retain any color index definitions from the previous * frame. */ for (i=0; i < DEVICE_COLOR_TABLE_SIZE; i++) Defined[i] = (char) FALSE; /* Always begin indexed color with the default colormap. * If the last frame used direct color, always retrieve * the default color map. */ if (last_frame_d_c || (Cmap != DefaultColormap(Dpy, Scr))) { if (xws_cmapout) (*xws_cmapout)(); Cmap = DefaultColormap(Dpy, Scr); if ( currentcolormap() != Cmap ) { XSetWindowColormap(Dpy, Win, Cmap); XSetWindowColormap(Dpy, Topwin, Cmap); } /* Newly installed implies all cells are unallocated */ for (i=0; i < DEVICE_COLOR_TABLE_SIZE; i++) DevColor[i] = UNALLOCATED; } /* Force definition of foreground, index 1, because * (*xws_get_pixel)() relies on its definition for a default. */ if (xws_ctab) (*xws_ctab)(1, 1, Gdct); /* Make a note that this is an indexed color frame */ last_frame_d_c= 0; break; case ((int) d_c_mode): /* Get RGB_DEFAULT_MAP, or RGB_BEST_MAP, or if they are * unavailable, generate one. */ if ( !RGB_Cmap ) /* Have to handle Sun X11/News and HP separately */ if (server_is_sun_or_hp()) { fprintf(stderr,"Sun or HP server; generating RGB map\n"); generate_sun_rgbmap(&map_info); RGB_Cmap= map_info.colormap; } else { XStandardColormap *mymaps; int count; if (XGetRGBColormaps(Dpy, RootWindow(Dpy,Scr), &mymaps, &count, XA_RGB_DEFAULT_MAP)) { map_info= *mymaps; /* bitwise copy will work */ } else { if (XmuLookupStandardColormap(Dpy, Scr, XVisualIDFromVisual( DefaultVisual(Dpy, Scr)), dev_depth, XA_RGB_DEFAULT_MAP, False, True)) { if (XGetRGBColormaps(Dpy, RootWindow(Dpy,Scr), &mymaps, &count, XA_RGB_DEFAULT_MAP)) { map_info= *mymaps; /* bitwise copy will work */ } else { fprintf(stderr, "Couldn't get RGB_DEFAULT_MAP; calling xws_rgbmap\n"); xws_rgbmap(&map_info); } } else { fprintf(stderr, "Couldn't get RGB_DEFAULT_MAP; calling xws_rgbmap\n"); xws_rgbmap(&map_info); } } RGB_Cmap = map_info.colormap; } if ( !RGB_Cmap ) break; /* Install the RGB Colormap Map if it is not already installed. */ if (Cmap != RGB_Cmap) { Cmap = RGB_Cmap; if (xws_cmapin) (*xws_cmapin)(); if ( currentcolormap() != Cmap ) { XSetWindowColormap(Dpy, Win, Cmap); XSetWindowColormap(Dpy, Topwin, Cmap); } } /* Make a note that this is a direct color frame */ last_frame_d_c= 1; break; default: (void) fprintf(stderr, "%s: xws_pbp_color: bad color mode.\n", ProgramName); } } static void xws_cursor_color(color) /* color the cursor to define the last two indices */ XColor color; { static XColor fore, back; static short fdef=FALSE, bdef=FALSE; if (color.pixel == 254) /* cursor background */ { back.pixel = color.pixel; back.red = color.red; back.green = color.green; back.blue = color.blue; back.flags = DoRed | DoGreen | DoBlue; bdef = TRUE; } else if (color.pixel == 255) /* cursor foreground */ { fore.pixel = color.pixel; fore.red = color.red; fore.green = color.green; fore.blue = color.blue; fore.flags = DoRed | DoGreen | DoBlue; fdef = TRUE; } if (fdef && bdef) { XRecolorCursor(Dpy, WaitCursor, &fore, &back); XRecolorCursor(Dpy, ReadyCursor, &fore, &back); } else if (fdef && !bdef) { XRecolorCursor(Dpy, WaitCursor, &fore, &fore); XRecolorCursor(Dpy, ReadyCursor, &fore, &fore); } else if (!fdef && bdef) { XRecolorCursor(Dpy, WaitCursor, &back, &back); XRecolorCursor(Dpy, ReadyCursor, &back, &back); } return; } xws_pctab(gplot_index, count, table) int gplot_index, count; float table[]; /* allocate & define color cells for pseudocolor device */ { register int i, j; XColor color; /* for specifying color value */ unsigned long plane_masks[1]; /* not used */ unsigned long pixels_return[1]; /* the device index */ int status = GPLOT_SUCCESS; /* This routine called only for indexed color metafiles. * All color specifications are assumed to be legal values. * * The optional CGM element Metafile Defaults Replacement may contain * definitions of default indexed colors. These default colors * apply to any frame which does not supply its own color table, and * therefore these default colors are stored for the duration of the * metafile translation in the gplot default color table, Gdct. * The Metafile Defaults Replacement element, if it contains indexed * color definitions, will result in a call to (*xws_ctab)() which will * occur prior to the first call to xws_bpage(). The global flag * variable "Metafile_Defaults" controls recognition of this condition. */ if (Metafile_Defaults) { int limit; if ((limit = gplot_index + count) > (GDCT_MAX_INDEX + 1)) { (void) fprintf(stderr, "%s: xws_ctab: GDCT_MAX_INDEX \ may be too small; requesting %d.\n", ProgramName, --limit); limit = GDCT_MAX_INDEX + 1; status = GPLOT_DRIVER_ERROR; } limit *= 3; /* limit = 1 + index of last color to be defined */ for (i = gplot_index * 3; i < limit; i++) Gdct[i] = table[i]; return(status); } /* Do not allow definition of out of bounds indices. */ if (gplot_index + count > DEVICE_COLOR_TABLE_SIZE) { status = GPLOT_DRIVER_ERROR; count = DEVICE_COLOR_TABLE_SIZE - gplot_index; } color.flags = DoRed | DoGreen | DoBlue; j = 3 * gplot_index; /* j is the index into the color table */ for (i=0; i < count; i++, gplot_index++) { if (DevColor[gplot_index] == UNALLOCATED) { if (XAllocColorCells(Dpy, Cmap, CONTIGUOUS, plane_masks, 0, pixels_return, 1)) DevColor[gplot_index] = pixels_return[0]; else if (Cmap == DefaultColormap(Dpy, Scr)) { Cmap = XCopyColormapAndFree(Dpy, Cmap); if (xws_cmapin) (*xws_cmapin)(); if ( currentcolormap() != Cmap ) { XSetWindowColormap(Dpy, Win, Cmap); XSetWindowColormap(Dpy, Topwin, Cmap); } if (XAllocColorCells(Dpy, Cmap, CONTIGUOUS, plane_masks, 0, pixels_return, 1)) DevColor[gplot_index]= pixels_return[0]; else { /* No more room in the color table */ status = GPLOT_DRIVER_ERROR; /* Advance the color table index */ j += 3; /* Continue, because it is theoretically * possible to get a request to redefine * an already allocated cell, or to be * able to allocate more if another * client releases allocated color cells. */ continue; } } } /* At this point, a cell has been allocated; now define it. */ color.red = (unsigned short) (table[j++] * X_RGB_SCALE); color.green=(unsigned short) (table[j++] * X_RGB_SCALE); color.blue= (unsigned short) (table[j++] * X_RGB_SCALE); Defined[gplot_index] = (char) TRUE; if ((color.pixel = DevColor[gplot_index]) < 254) XStoreColor(Dpy, Cmap, &color); else xws_cursor_color(color); } return(status); } void xws_pcmapin() /* This routine swaps a device color map in for Pseudocolor visuals */ { #ifdef installcmaps if (Cmap != DefaultColormap(Dpy, Scr)) XInstallColormap(Dpy, Cmap); #endif } void xws_pcmapout() /* This routine swaps a device color map out for Pseudocolor visuals */ { /* If you are running XV11R2 on a GPX, you must have fix #16 * for XUninstallColormap() to work properly. */ #ifdef installcmaps if (Cmap != DefaultColormap(Dpy, Scr)) XUninstallColormap(Dpy, Cmap); #endif } /* This routine supplies a pixel value for PseudoColor visuals */ Pixeltype xws_pget_pixel(r, g, b, index) /* supply a pixel value */ float r, g, b; /* requested r,g,b values for direct color */ int index; /* requested color index for indexed color */ { switch ((int) CGMClass2->c_s_mode) { case ((int) i_c_mode): /* indexed */ /* The foreground index 1 is guaranteed to be defined by * (*xws_bp_color)(), at the beginning of each frame. The actual * color of the foreground pixel is taken from the metafile's color * table index 1, if it has been defined by a direct call to * (*xws_ctab)() after the current call to xws_bpage(). Otherwise * it is taken from gplot default color table index 1, which is * defined from the metafile default colors, at the first call to * (*xws_bp_color)(). */ if (0 <= index && index <= DevMaxIndex) { if (Defined[index]) return(DevColor[index]); /* Try the default color table */ if (index <= GDCT_MAX_INDEX && Gdct[index*3] != UNDEFINED_GDCT_COLOR && xws_ctab) if ((*xws_ctab)(index, 1, Gdct)==GPLOT_SUCCESS) return(DevColor[index]); } return(DevColor[1]); /* must be defined */ case ((int) d_c_mode): /* direct */ /* This routine is called for all direct color references, except * those made during cell array translation. For cell array * translation, this code is duplicated in the cell array routine. */ /* Convert gplot r,g,b specification into an X RGB Best Map index.*/ return( rgb_to_pixel(r,g,b) ); default: (void) fprintf(stderr, "%s: xws_pget_pixel: bad color mode.\n", ProgramName); return(BlackPixel(Dpy, Scr)); } /*NOTREACHED*/ } Pixeltype * xws_pget_row(rarray,garray,barray,iarray,ndim,row) float *rarray, *garray, *barray; /* the color arrays */ int *iarray; /* array of indices */ int ndim, /* dimension of input arrays */ row; /* current row number */ { static Pixeltype *results= NULL; static float *r_dither, *g_dither, *b_dither; register Pixeltype *pix; register float *r_error, *g_error, *b_error, r, g, b, r_forward, g_forward, b_forward, r_diag, g_diag, b_diag; Pixeltype *endpix; if (row==0) /* This is the first call- allocate memory */ { if (results) free(results); /* called before- free old mem */ if ( (results = (Pixeltype *)calloc( ndim,sizeof(Pixeltype) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_pget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } } /* First call for direct color, so allocate and zero dither buffers */ if ( row==0 && CGMClass2->c_s_mode == d_c_mode ) { if (r_dither) free(r_dither); /* called before- free old mem */ if ( (r_dither = (float *)calloc( ndim,sizeof(float) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_pget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } if (g_dither) free(g_dither); /* called before- free old mem */ if ( (g_dither = (float *)calloc( ndim,sizeof(float) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_pget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } if (b_dither) free(b_dither); /* called before- free old mem */ if ( (b_dither = (float *)calloc( ndim,sizeof(float) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_pget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } } /* Get pixel value, distinguishing indexed and direct color modes. For each case we do an entire row of pixels. */ endpix= results + ndim; /* loop end; might as well precalculate */ switch ((int) CGMClass2->c_s_mode) { case ((int) i_c_mode): /* indexed */ for (pix= results; pixc_s_mode == i_c_mode ) { if ( (index < 0) || (index > CGMClass1->max_c_index) ) index= 1; cptr= CGMClass5->ctab + 3*index; r= *cptr++; g= *cptr++; b= *cptr; } /* Translate r, g, b into a pixel value and return */ return( rgb_to_pixel( r, g, b ) ); } /* This routine supplies a pixel value for monochrome visuals */ Pixeltype xws_mget_pixel(r,g,b,index) float r, g, b; /* requested r,g,b values for direct color */ int index; /* requested color index for indexed color */ { float intensity; /* In the indexed color environment, this routine returns the background pixel value for index 0, and the foreground pixel value for all other indices. In the direct color case, it returns the value closest to the intensity of the requested color. */ if ( CGMClass2->c_s_mode == i_c_mode ) { if (index == 0) return( WhitePixel( Dpy, Scr ) ); else return( BlackPixel( Dpy, Scr ) ); } else return( rgb_to_intensity(r,g,b) >= 0.5 ? WhitePixel( Dpy, Scr ) : BlackPixel( Dpy, Scr ) ); } /* This routine supplies a row of pixel values for DirectColor visuals */ Pixeltype * xws_dget_row(rarray,garray,barray,iarray,ndim,row) float *rarray, *garray, *barray; /* the color arrays */ int *iarray; /* array of indices */ int ndim, /* dimension of input arrays */ row; /* current row number */ { static Pixeltype *results= NULL; register Pixeltype *pix; Pixeltype *endpix; register int index; register float *cptr; register float r, g, b; if (row==0) /* This is the first call- allocate memory */ { if (results) free(results); /* called before- free old mem */ if ( (results = (Pixeltype *)calloc( ndim,sizeof(Pixeltype) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_dget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } } /* Calculate pixel values for the whole row */ endpix= results + ndim; for (pix= results; pixc_s_mode == i_c_mode ) { index= ( (*iarray < 0) || (*iarray > CGMClass1->max_c_index) ) ? 0 : *iarray; cptr= CGMClass5->ctab + 3*index; r= *cptr++; g= *cptr++; b= *cptr; } else { r= *rarray; g= *garray; b= *barray; }; /* Translate r, g, b into a pixel value */ *pix= rgb_to_pixel( r, g, b ); /* Move on to next pixel */ rarray++; garray++; barray++; iarray++; } return( results ); } /* This routine supplies a row of pixel values for monochrome visuals */ Pixeltype * xws_mget_row(rarray,garray,barray,iarray,ndim,row) float *rarray, *garray, *barray; /* the color arrays */ int *iarray; /* array of indices */ int ndim, /* dimension of input arrays */ row; /* current row number */ { static Pixeltype *results= NULL; register Pixeltype *pix; Pixeltype *endpix; register int index; register float intensity; if (row==0) /* This is the first call- allocate memory */ { if (results) free(results); /* called before- free old mem */ if ( (results = (Pixeltype *)calloc( ndim,sizeof(Pixeltype) ) ) == NULL ) { (void) fprintf(stderr, "%s: xws_mget_row: No memory for cell array row\n", ProgramName); return( (Pixeltype *)NULL ); } } /* Calculate pixel values for the whole row */ endpix= results + ndim; if ( CGMClass2->c_s_mode == i_c_mode ) /* indexed color case */ /* If indexed color mode, get foreground or background pixel depending on index */ for (pix= results; pix CGMClass1->max_c_index) ) ? 0 : *iarray; *pix= index == 0 ? WhitePixel( Dpy, Scr ) : BlackPixel( Dpy, Scr ); iarray++; } else /* direct color case */ /* return the results of dithering for the intensity equivalent to the given red, green, and blue. */ for (pix= results; pixclass) { case (int)TrueColor: case (int)DirectColor: xws_bp_color= NULL; xws_ctab= NULL; xws_cmapin= NULL; xws_cmapout= NULL; xws_get_pixel= xws_dget_pixel; xws_get_row= xws_dget_row; xws_dcolor_init(); break; case (int)PseudoColor: xws_bp_color= xws_pbp_color; xws_ctab= xws_pctab; xws_cmapin= xws_pcmapin; xws_cmapout= xws_pcmapout; xws_get_pixel= xws_pget_pixel; xws_get_row= xws_pget_row; xws_pcolor_init(); break; case (int)StaticColor: fprintf(stderr, "%s: Sorry, no color support for StaticColor visual type\n", ProgramName); exit(-1); break; case (int)GrayScale: fprintf(stderr, "%s: Sorry, no color support for GrayScale visual type\n", ProgramName); exit(-1); break; case (int)StaticGray: xws_bp_color= NULL; xws_ctab= NULL; xws_cmapin= NULL; xws_cmapout= NULL; xws_get_pixel= xws_sget_pixel; xws_get_row= xws_sget_row; xws_scolor_init(); break; }; }