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