StdCmap.c revision e120bd27
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