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