StdCmap.c revision 0cc2eac3
1/* 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27/* 28 * Author: Donna Converse, MIT X Consortium 29 */ 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34#include <stdio.h> 35#include <X11/Xlib.h> 36#include <X11/Xatom.h> 37#include <X11/Xutil.h> 38#include <X11/Xmu/StdCmap.h> 39 40#define lowbit(x) ((x) & (~(x) + 1)) 41 42/* 43 * Prototypes 44 */ 45/* argument restrictions */ 46static Status valid_args(XVisualInfo*, unsigned long, unsigned long, 47 unsigned long, Atom); 48 49/* 50 * To create any one standard colormap, use XmuStandardColormap(). 51 * 52 * Create a standard colormap for the given screen, visualid, and visual 53 * depth, with the given red, green, and blue maximum values, with the 54 * given standard property name. Return a pointer to an XStandardColormap 55 * structure which describes the newly created colormap, upon success. 56 * Upon failure, return NULL. 57 * 58 * XmuStandardColormap() calls XmuCreateColormap() to create the map. 59 * 60 * Resources created by this function are not made permanent; that is the 61 * caller's responsibility. 62 */ 63 64XStandardColormap * 65XmuStandardColormap(Display *dpy, int screen, VisualID visualid, 66 unsigned int depth, Atom property, Colormap cmap, 67 unsigned long red_max, unsigned long green_max, 68 unsigned long blue_max) 69 /* 70 * dpy - specifies X server connection 71 * screen - specifies display screen 72 * visualid - identifies the visual type 73 * depth - identifies the visual type 74 * property - a standard colormap property 75 * cmap - specifies colormap ID or None 76 * red_max, green_max, blue_max - allocations 77 */ 78{ 79 XStandardColormap *stdcmap; 80 Status status; 81 XVisualInfo vinfo_template, *vinfo; 82 long vinfo_mask; 83 int n; 84 85 /* Match the required visual information to an actual visual */ 86 vinfo_template.visualid = visualid; 87 vinfo_template.screen = screen; 88 vinfo_template.depth = depth; 89 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask; 90 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL) 91 return NULL; 92 93 /* Check the validity of the combination of visual characteristics, 94 * allocation, and colormap property. Create an XStandardColormap 95 * structure. 96 */ 97 98 if (! valid_args(vinfo, red_max, green_max, blue_max, property) 99 || ((stdcmap = XAllocStandardColormap()) == NULL)) { 100 XFree((char *) vinfo); 101 return NULL; 102 } 103 104 /* Fill in the XStandardColormap structure */ 105 106 if (cmap == DefaultColormap(dpy, screen)) { 107 /* Allocating out of the default map, cannot use XFreeColormap() */ 108 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1, 109 0, 0, InputOnly, vinfo->visual, 110 (unsigned long) 0, 111 (XSetWindowAttributes *)NULL); 112 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth); 113 XDestroyWindow(dpy, win); 114 stdcmap->colormap = cmap; 115 } else { 116 stdcmap->killid = ReleaseByFreeingColormap; 117 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen), 118 vinfo->visual, AllocNone); 119 } 120 stdcmap->red_max = red_max; 121 stdcmap->green_max = green_max; 122 stdcmap->blue_max = blue_max; 123 if (property == XA_RGB_GRAY_MAP) 124 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1; 125 else if (vinfo->class == TrueColor || vinfo->class == DirectColor) { 126 stdcmap->red_mult = lowbit(vinfo->red_mask); 127 stdcmap->green_mult = lowbit(vinfo->green_mask); 128 stdcmap->blue_mult = lowbit(vinfo->blue_mask); 129 } else { 130 stdcmap->red_mult = (red_max > 0) 131 ? (green_max + 1) * (blue_max + 1) : 0; 132 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0; 133 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0; 134 } 135 stdcmap->base_pixel = 0; /* base pixel may change */ 136 stdcmap->visualid = vinfo->visualid; 137 138 /* Make the colormap */ 139 140 status = XmuCreateColormap(dpy, stdcmap); 141 142 /* Clean up */ 143 144 XFree((char *) vinfo); 145 if (!status) { 146 147 /* Free the colormap or the pixmap, if we created one */ 148 if (stdcmap->killid == ReleaseByFreeingColormap) 149 XFreeColormap(dpy, stdcmap->colormap); 150 else if (stdcmap->killid != None) 151 XFreePixmap(dpy, stdcmap->killid); 152 153 XFree((char *) stdcmap); 154 return (XStandardColormap *) NULL; 155 } 156 return stdcmap; 157} 158 159/****************************************************************************/ 160static Status 161valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max, 162 unsigned long blue_max, Atom property) 163 /* 164 * vinfo - specifies visual 165 * red_max, green_max, blue_max - specifies alloc 166 * property - specifies property name 167 */ 168{ 169 unsigned long ncolors; /* number of colors requested */ 170 171 /* Determine that the number of colors requested is <= map size */ 172 173 if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) { 174 unsigned long mask; 175 176 mask = vinfo->red_mask; 177 while (!(mask & 1)) 178 mask >>= 1; 179 if (red_max > mask) 180 return 0; 181 mask = vinfo->green_mask; 182 while (!(mask & 1)) 183 mask >>= 1; 184 if (green_max > mask) 185 return 0; 186 mask = vinfo->blue_mask; 187 while (!(mask & 1)) 188 mask >>= 1; 189 if (blue_max > mask) 190 return 0; 191 } else if (property == XA_RGB_GRAY_MAP) { 192 ncolors = red_max + green_max + blue_max + 1; 193 if (ncolors > vinfo->colormap_size) 194 return 0; 195 } else { 196 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1); 197 if (ncolors > vinfo->colormap_size) 198 return 0; 199 } 200 201 /* Determine that the allocation and visual make sense for the property */ 202 203 switch (property) 204 { 205 case XA_RGB_DEFAULT_MAP: 206 if (red_max == 0 || green_max == 0 || blue_max == 0) 207 return 0; 208 break; 209 case XA_RGB_RED_MAP: 210 if (red_max == 0) 211 return 0; 212 break; 213 case XA_RGB_GREEN_MAP: 214 if (green_max == 0) 215 return 0; 216 break; 217 case XA_RGB_BLUE_MAP: 218 if (blue_max == 0) 219 return 0; 220 break; 221 case XA_RGB_BEST_MAP: 222 if (red_max == 0 || green_max == 0 || blue_max == 0) 223 return 0; 224 break; 225 case XA_RGB_GRAY_MAP: 226 if (red_max == 0 || blue_max == 0 || green_max == 0) 227 return 0; 228 break; 229 default: 230 return 0; 231 } 232 return 1; 233} 234