CmapAlloc.c revision 53bb355a
1/* 2 3Copyright 1989, 1994, 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 <X11/Xlib.h> 35#include <X11/Xatom.h> 36#include <X11/Xutil.h> 37#include <X11/Xmu/StdCmap.h> 38#include <stdio.h> 39 40#define lowbit(x) ((x) & (~(x) + 1)) 41 42/* 43 * Prototypes 44 */ 45static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*, 46 unsigned long*); 47static int default_allocation(XVisualInfo*, unsigned long*, 48 unsigned long*, unsigned long*); 49static void gray_allocation(int, unsigned long*, unsigned long*, 50 unsigned long*); 51static int icbrt(int); 52static int icbrt_with_bits(int, int); 53static int icbrt_with_guess(int, int); 54 55/* To determine the best allocation of reds, greens, and blues in a 56 * standard colormap, use XmuGetColormapAllocation. 57 * vinfo specifies visual information for a chosen visual 58 * property specifies one of the standard colormap property names 59 * red_max returns maximum red value 60 * green_max returns maximum green value 61 * blue_max returns maximum blue value 62 * 63 * XmuGetColormapAllocation returns 0 on failure, non-zero on success. 64 * It is assumed that the visual is appropriate for the colormap property. 65 */ 66 67Status 68XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property, 69 unsigned long *red_max, 70 unsigned long *green_max, 71 unsigned long *blue_max) 72{ 73 Status status = 1; 74 75 if (vinfo->colormap_size <= 2) 76 return 0; 77 78 switch (property) 79 { 80 case XA_RGB_DEFAULT_MAP: 81 status = default_allocation(vinfo, red_max, green_max, blue_max); 82 break; 83 case XA_RGB_BEST_MAP: 84 best_allocation(vinfo, red_max, green_max, blue_max); 85 break; 86 case XA_RGB_GRAY_MAP: 87 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max); 88 break; 89 case XA_RGB_RED_MAP: 90 *red_max = vinfo->colormap_size - 1; 91 *green_max = *blue_max = 0; 92 break; 93 case XA_RGB_GREEN_MAP: 94 *green_max = vinfo->colormap_size - 1; 95 *red_max = *blue_max = 0; 96 break; 97 case XA_RGB_BLUE_MAP: 98 *blue_max = vinfo->colormap_size - 1; 99 *red_max = *green_max = 0; 100 break; 101 default: 102 status = 0; 103 } 104 return status; 105} 106 107/****************************************************************************/ 108/* Determine the appropriate color allocations of a gray scale. 109 * 110 * Keith Packard, MIT X Consortium 111 */ 112 113static void 114gray_allocation(int n, unsigned long *red_max, unsigned long *green_max, 115 unsigned long *blue_max) 116{ 117 *red_max = (n * 30) / 100; 118 *green_max = (n * 59) / 100; 119 *blue_max = (n * 11) / 100; 120 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max)); 121} 122 123/****************************************************************************/ 124/* Determine an appropriate color allocation for the RGB_DEFAULT_MAP. 125 * If a map has less than a minimum number of definable entries, we do not 126 * produce an allocation for an RGB_DEFAULT_MAP. 127 * 128 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes, 129 * 12 each. For 8 planes, let n = the number of colormap entries, which may 130 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1. 131 * Maximum green and maximum blue values are identical to maximum red. 132 * This leaves at least 125 cells which clients can allocate. 133 * 134 * Return 0 if an allocation has been determined, non-zero otherwise. 135 */ 136 137static int 138default_allocation(XVisualInfo *vinfo, unsigned long *red, 139 unsigned long *green, unsigned long *blue) 140{ 141 int ngrays; /* number of gray cells */ 142 143 switch (vinfo->class) { 144 case PseudoColor: 145 146 if (vinfo->colormap_size > 65000) 147 /* intended for displays with 16 planes */ 148 *red = *green = *blue = (unsigned long) 27; 149 else if (vinfo->colormap_size > 4000) 150 /* intended for displays with 12 planes */ 151 *red = *green = *blue = (unsigned long) 12; 152 else if (vinfo->colormap_size < 250) 153 return 0; 154 else 155 /* intended for displays with 8 planes */ 156 *red = *green = *blue = (unsigned long) 157 (icbrt(vinfo->colormap_size - 125) - 1); 158 break; 159 160 case DirectColor: 161 162 if (vinfo->colormap_size < 10) 163 return 0; 164 *red = *green = *blue = vinfo->colormap_size / 2 - 1; 165 break; 166 167 case TrueColor: 168 169 *red = vinfo->red_mask / lowbit(vinfo->red_mask); 170 *green = vinfo->green_mask / lowbit(vinfo->green_mask); 171 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask); 172 break; 173 174 case GrayScale: 175 176 if (vinfo->colormap_size > 65000) 177 ngrays = 4096; 178 else if (vinfo->colormap_size > 4000) 179 ngrays = 512; 180 else if (vinfo->colormap_size < 250) 181 return 0; 182 else 183 ngrays = 12; 184 gray_allocation(ngrays, red, green, blue); 185 break; 186 187 default: 188 return 0; 189 } 190 return 1; 191} 192 193/****************************************************************************/ 194/* Determine an appropriate color allocation for the RGB_BEST_MAP. 195 * 196 * For a DirectColor or TrueColor visual, the allocation is determined 197 * by the red_mask, green_mask, and blue_mask members of the visual info. 198 * 199 * Otherwise, if the colormap size is an integral power of 2, determine 200 * the allocation according to the number of bits given to each color, 201 * with green getting more than red, and red more than blue, if there 202 * are to be inequities in the distribution. If the colormap size is 203 * not an integral power of 2, let n = the number of colormap entries. 204 * Then maximum red value = floor(cube_root(n)) - 1; 205 * maximum blue value = floor(cube_root(n)) - 1; 206 * maximum green value = n / ((# red values) * (# blue values)) - 1; 207 * Which, on a GPX, allows for 252 entries in the best map, out of 254 208 * definable colormap entries. 209 */ 210 211static void 212best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green, 213 unsigned long *blue) 214{ 215 216 if (vinfo->class == DirectColor || vinfo->class == TrueColor) 217 { 218 *red = vinfo->red_mask; 219 while ((*red & 01) == 0) 220 *red >>= 1; 221 *green = vinfo->green_mask; 222 while ((*green & 01) == 0) 223 *green >>=1; 224 *blue = vinfo->blue_mask; 225 while ((*blue & 01) == 0) 226 *blue >>= 1; 227 } 228 else 229 { 230 register int bits, n; 231 232 /* Determine n such that n is the least integral power of 2 which is 233 * greater than or equal to the number of entries in the colormap. 234 */ 235 n = 1; 236 bits = 0; 237 while (vinfo->colormap_size > n) 238 { 239 n = n << 1; 240 bits++; 241 } 242 243 /* If the number of entries in the colormap is a power of 2, determine 244 * the allocation by "dealing" the bits, first to green, then red, then 245 * blue. If not, find the maximum integral red, green, and blue values 246 * which, when multiplied together, do not exceed the number of 247 248 * colormap entries. 249 */ 250 if (n == vinfo->colormap_size) 251 { 252 register int r, g, b; 253 b = bits / 3; 254 g = b + ((bits % 3) ? 1 : 0); 255 r = b + (((bits % 3) == 2) ? 1 : 0); 256 *red = 1 << r; 257 *green = 1 << g; 258 *blue = 1 << b; 259 } 260 else 261 { 262 *red = icbrt_with_bits(vinfo->colormap_size, bits); 263 *blue = *red; 264 *green = (vinfo->colormap_size / ((*red) * (*blue))); 265 } 266 (*red)--; 267 (*green)--; 268 (*blue)--; 269 } 270 return; 271} 272 273/* 274 * integer cube roots by Newton's method 275 * 276 * Stephen Gildea, MIT X Consortium, July 1991 277 */ 278 279static int 280icbrt(int a) 281{ 282 register int bits = 0; 283 register unsigned n = a; 284 285 while (n) 286 { 287 bits++; 288 n >>= 1; 289 } 290 return icbrt_with_bits(a, bits); 291} 292 293 294static int 295icbrt_with_bits(int a, int bits) 296 /* bits - log 2 of a */ 297{ 298 return icbrt_with_guess(a, a>>2*bits/3); 299} 300 301#ifdef _X_ROOT_STATS 302int icbrt_loopcount; 303#endif 304 305/* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */ 306 307/* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */ 308 309/* 310 * Quick and dirty cube roots. Nothing fancy here, just Newton's method. 311 * Only works for positive integers (since that's all we need). 312 * We actually return floor(cbrt(a)) because that's what we need here, too. 313 */ 314 315static int 316icbrt_with_guess(int a, int guess) 317{ 318 register int delta; 319 320#ifdef _X_ROOT_STATS 321 icbrt_loopcount = 0; 322#endif 323 if (a <= 0) 324 return 0; 325 if (guess < 1) 326 guess = 1; 327 328 do { 329#ifdef _X_ROOT_STATS 330 icbrt_loopcount++; 331#endif 332 delta = (guess - a/(guess*guess))/3; 333#if defined(DEBUG) && defined(_X_ROOT_STATS) 334 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta); 335#endif 336 guess -= delta; 337 } while (delta != 0); 338 339 if (guess*guess*guess > a) 340 guess--; 341 342 return guess; 343} 344