1c3c75042Smrg/* 26c321187Smrg 36c321187SmrgCopyright 1989, 1994, 1998 The Open Group 46c321187Smrg 56c321187SmrgPermission to use, copy, modify, distribute, and sell this software and its 66c321187Smrgdocumentation for any purpose is hereby granted without fee, provided that 76c321187Smrgthe above copyright notice appear in all copies and that both that 86c321187Smrgcopyright notice and this permission notice appear in supporting 96c321187Smrgdocumentation. 106c321187Smrg 116c321187SmrgThe above copyright notice and this permission notice shall be included in 126c321187Smrgall copies or substantial portions of the Software. 136c321187Smrg 146c321187SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 156c321187SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 166c321187SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 176c321187SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 186c321187SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 196c321187SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 206c321187Smrg 216c321187SmrgExcept as contained in this notice, the name of The Open Group shall not be 226c321187Smrgused in advertising or otherwise to promote the sale, use or other dealings 236c321187Smrgin this Software without prior written authorization from The Open Group. 246c321187Smrg 256c321187Smrg*/ 266c321187Smrg 276c321187Smrg/* 286c321187Smrg * Author: Donna Converse, MIT X Consortium 296c321187Smrg */ 306c321187Smrg 316c321187Smrg#ifdef HAVE_CONFIG_H 326c321187Smrg#include <config.h> 336c321187Smrg#endif 346c321187Smrg#include <X11/Xlib.h> 356c321187Smrg#include <X11/Xatom.h> 366c321187Smrg#include <X11/Xutil.h> 376c321187Smrg#include <X11/Xmu/StdCmap.h> 386c321187Smrg#include <stdio.h> 396c321187Smrg 406c321187Smrg#define lowbit(x) ((x) & (~(x) + 1)) 416c321187Smrg 426c321187Smrg/* 436c321187Smrg * Prototypes 446c321187Smrg */ 456c321187Smrgstatic void best_allocation(XVisualInfo*, unsigned long*, unsigned long*, 466c321187Smrg unsigned long*); 476c321187Smrgstatic int default_allocation(XVisualInfo*, unsigned long*, 486c321187Smrg unsigned long*, unsigned long*); 496c321187Smrgstatic void gray_allocation(int, unsigned long*, unsigned long*, 506c321187Smrg unsigned long*); 516c321187Smrgstatic int icbrt(int); 526c321187Smrgstatic int icbrt_with_bits(int, int); 536c321187Smrgstatic int icbrt_with_guess(int, int); 546c321187Smrg 55c3c75042Smrg/* To determine the best allocation of reds, greens, and blues in a 566c321187Smrg * standard colormap, use XmuGetColormapAllocation. 576c321187Smrg * vinfo specifies visual information for a chosen visual 586c321187Smrg * property specifies one of the standard colormap property names 59c3c75042Smrg * red_max returns maximum red value 606c321187Smrg * green_max returns maximum green value 616c321187Smrg * blue_max returns maximum blue value 626c321187Smrg * 636c321187Smrg * XmuGetColormapAllocation returns 0 on failure, non-zero on success. 646c321187Smrg * It is assumed that the visual is appropriate for the colormap property. 656c321187Smrg */ 666c321187Smrg 676c321187SmrgStatus 686c321187SmrgXmuGetColormapAllocation(XVisualInfo *vinfo, Atom property, 696c321187Smrg unsigned long *red_max, 706c321187Smrg unsigned long *green_max, 716c321187Smrg unsigned long *blue_max) 726c321187Smrg{ 736c321187Smrg Status status = 1; 746c321187Smrg 756c321187Smrg if (vinfo->colormap_size <= 2) 766c321187Smrg return 0; 776c321187Smrg 786c321187Smrg switch (property) 796c321187Smrg { 806c321187Smrg case XA_RGB_DEFAULT_MAP: 816c321187Smrg status = default_allocation(vinfo, red_max, green_max, blue_max); 826c321187Smrg break; 836c321187Smrg case XA_RGB_BEST_MAP: 846c321187Smrg best_allocation(vinfo, red_max, green_max, blue_max); 856c321187Smrg break; 866c321187Smrg case XA_RGB_GRAY_MAP: 876c321187Smrg gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max); 886c321187Smrg break; 896c321187Smrg case XA_RGB_RED_MAP: 906c321187Smrg *red_max = vinfo->colormap_size - 1; 916c321187Smrg *green_max = *blue_max = 0; 926c321187Smrg break; 936c321187Smrg case XA_RGB_GREEN_MAP: 946c321187Smrg *green_max = vinfo->colormap_size - 1; 956c321187Smrg *red_max = *blue_max = 0; 966c321187Smrg break; 976c321187Smrg case XA_RGB_BLUE_MAP: 986c321187Smrg *blue_max = vinfo->colormap_size - 1; 996c321187Smrg *red_max = *green_max = 0; 1006c321187Smrg break; 1016c321187Smrg default: 1026c321187Smrg status = 0; 1036c321187Smrg } 1046c321187Smrg return status; 1056c321187Smrg} 1066c321187Smrg 1076c321187Smrg/****************************************************************************/ 1086c321187Smrg/* Determine the appropriate color allocations of a gray scale. 1096c321187Smrg * 1106c321187Smrg * Keith Packard, MIT X Consortium 1116c321187Smrg */ 1126c321187Smrg 1136c321187Smrgstatic void 1146c321187Smrggray_allocation(int n, unsigned long *red_max, unsigned long *green_max, 1156c321187Smrg unsigned long *blue_max) 1166c321187Smrg{ 1176c321187Smrg *red_max = (n * 30) / 100; 118c3c75042Smrg *green_max = (n * 59) / 100; 119c3c75042Smrg *blue_max = (n * 11) / 100; 1206c321187Smrg *green_max += ((n - 1) - (*red_max + *green_max + *blue_max)); 1216c321187Smrg} 1226c321187Smrg 1236c321187Smrg/****************************************************************************/ 1246c321187Smrg/* Determine an appropriate color allocation for the RGB_DEFAULT_MAP. 1256c321187Smrg * If a map has less than a minimum number of definable entries, we do not 126c3c75042Smrg * produce an allocation for an RGB_DEFAULT_MAP. 1276c321187Smrg * 1286c321187Smrg * For 16 planes, the default colormap will have 27 each RGB; for 12 planes, 1296c321187Smrg * 12 each. For 8 planes, let n = the number of colormap entries, which may 1306c321187Smrg * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1. 1316c321187Smrg * Maximum green and maximum blue values are identical to maximum red. 1326c321187Smrg * This leaves at least 125 cells which clients can allocate. 1336c321187Smrg * 1346c321187Smrg * Return 0 if an allocation has been determined, non-zero otherwise. 1356c321187Smrg */ 1366c321187Smrg 1376c321187Smrgstatic int 1386c321187Smrgdefault_allocation(XVisualInfo *vinfo, unsigned long *red, 1396c321187Smrg unsigned long *green, unsigned long *blue) 1406c321187Smrg{ 1416c321187Smrg int ngrays; /* number of gray cells */ 1426c321187Smrg 1436c321187Smrg switch (vinfo->class) { 1446c321187Smrg case PseudoColor: 1456c321187Smrg 1466c321187Smrg if (vinfo->colormap_size > 65000) 1476c321187Smrg /* intended for displays with 16 planes */ 1486c321187Smrg *red = *green = *blue = (unsigned long) 27; 1496c321187Smrg else if (vinfo->colormap_size > 4000) 1506c321187Smrg /* intended for displays with 12 planes */ 1516c321187Smrg *red = *green = *blue = (unsigned long) 12; 1526c321187Smrg else if (vinfo->colormap_size < 250) 1536c321187Smrg return 0; 1546c321187Smrg else 1556c321187Smrg /* intended for displays with 8 planes */ 1566c321187Smrg *red = *green = *blue = (unsigned long) 1576c321187Smrg (icbrt(vinfo->colormap_size - 125) - 1); 1586c321187Smrg break; 1596c321187Smrg 1606c321187Smrg case DirectColor: 1616c321187Smrg 1626c321187Smrg if (vinfo->colormap_size < 10) 1636c321187Smrg return 0; 1646c321187Smrg *red = *green = *blue = vinfo->colormap_size / 2 - 1; 1656c321187Smrg break; 1666c321187Smrg 1676c321187Smrg case TrueColor: 1686c321187Smrg 1696c321187Smrg *red = vinfo->red_mask / lowbit(vinfo->red_mask); 1706c321187Smrg *green = vinfo->green_mask / lowbit(vinfo->green_mask); 1716c321187Smrg *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask); 1726c321187Smrg break; 1736c321187Smrg 1746c321187Smrg case GrayScale: 1756c321187Smrg 1766c321187Smrg if (vinfo->colormap_size > 65000) 1776c321187Smrg ngrays = 4096; 1786c321187Smrg else if (vinfo->colormap_size > 4000) 1796c321187Smrg ngrays = 512; 1806c321187Smrg else if (vinfo->colormap_size < 250) 1816c321187Smrg return 0; 1826c321187Smrg else 1836c321187Smrg ngrays = 12; 1846c321187Smrg gray_allocation(ngrays, red, green, blue); 1856c321187Smrg break; 186c3c75042Smrg 1876c321187Smrg default: 1886c321187Smrg return 0; 1896c321187Smrg } 1906c321187Smrg return 1; 1916c321187Smrg} 1926c321187Smrg 1936c321187Smrg/****************************************************************************/ 1946c321187Smrg/* Determine an appropriate color allocation for the RGB_BEST_MAP. 1956c321187Smrg * 1966c321187Smrg * For a DirectColor or TrueColor visual, the allocation is determined 1976c321187Smrg * by the red_mask, green_mask, and blue_mask members of the visual info. 1986c321187Smrg * 1996c321187Smrg * Otherwise, if the colormap size is an integral power of 2, determine 2006c321187Smrg * the allocation according to the number of bits given to each color, 2016c321187Smrg * with green getting more than red, and red more than blue, if there 2026c321187Smrg * are to be inequities in the distribution. If the colormap size is 2036c321187Smrg * not an integral power of 2, let n = the number of colormap entries. 2046c321187Smrg * Then maximum red value = floor(cube_root(n)) - 1; 2056c321187Smrg * maximum blue value = floor(cube_root(n)) - 1; 2066c321187Smrg * maximum green value = n / ((# red values) * (# blue values)) - 1; 2076c321187Smrg * Which, on a GPX, allows for 252 entries in the best map, out of 254 20853bb355aSmrg * definable colormap entries. 2096c321187Smrg */ 210c3c75042Smrg 2116c321187Smrgstatic void 2126c321187Smrgbest_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green, 2136c321187Smrg unsigned long *blue) 2146c321187Smrg{ 2156c321187Smrg 2166c321187Smrg if (vinfo->class == DirectColor || vinfo->class == TrueColor) 2176c321187Smrg { 2186c321187Smrg *red = vinfo->red_mask; 2196c321187Smrg while ((*red & 01) == 0) 2206c321187Smrg *red >>= 1; 2216c321187Smrg *green = vinfo->green_mask; 2226c321187Smrg while ((*green & 01) == 0) 2236c321187Smrg *green >>=1; 2246c321187Smrg *blue = vinfo->blue_mask; 2256c321187Smrg while ((*blue & 01) == 0) 2266c321187Smrg *blue >>= 1; 2276c321187Smrg } 2286c321187Smrg else 2296c321187Smrg { 2306c321187Smrg register int bits, n; 231c3c75042Smrg 2326c321187Smrg /* Determine n such that n is the least integral power of 2 which is 2336c321187Smrg * greater than or equal to the number of entries in the colormap. 2346c321187Smrg */ 2356c321187Smrg n = 1; 2366c321187Smrg bits = 0; 2376c321187Smrg while (vinfo->colormap_size > n) 2386c321187Smrg { 2396c321187Smrg n = n << 1; 2406c321187Smrg bits++; 2416c321187Smrg } 242c3c75042Smrg 2436c321187Smrg /* If the number of entries in the colormap is a power of 2, determine 2446c321187Smrg * the allocation by "dealing" the bits, first to green, then red, then 2456c321187Smrg * blue. If not, find the maximum integral red, green, and blue values 246c3c75042Smrg * which, when multiplied together, do not exceed the number of 2476c321187Smrg 2486c321187Smrg * colormap entries. 2496c321187Smrg */ 2506c321187Smrg if (n == vinfo->colormap_size) 2516c321187Smrg { 2526c321187Smrg register int r, g, b; 2536c321187Smrg b = bits / 3; 2546c321187Smrg g = b + ((bits % 3) ? 1 : 0); 2556c321187Smrg r = b + (((bits % 3) == 2) ? 1 : 0); 2566c321187Smrg *red = 1 << r; 2576c321187Smrg *green = 1 << g; 2586c321187Smrg *blue = 1 << b; 2596c321187Smrg } 2606c321187Smrg else 2616c321187Smrg { 2626c321187Smrg *red = icbrt_with_bits(vinfo->colormap_size, bits); 263c3c75042Smrg *blue = *red; 2646c321187Smrg *green = (vinfo->colormap_size / ((*red) * (*blue))); 2656c321187Smrg } 2666c321187Smrg (*red)--; 2676c321187Smrg (*green)--; 2686c321187Smrg (*blue)--; 2696c321187Smrg } 2706c321187Smrg return; 2716c321187Smrg} 2726c321187Smrg 2736c321187Smrg/* 2746c321187Smrg * integer cube roots by Newton's method 2756c321187Smrg * 2766c321187Smrg * Stephen Gildea, MIT X Consortium, July 1991 2776c321187Smrg */ 2786c321187Smrg 2796c321187Smrgstatic int 2806c321187Smrgicbrt(int a) 2816c321187Smrg{ 2826c321187Smrg register int bits = 0; 2836c321187Smrg register unsigned n = a; 2846c321187Smrg 2856c321187Smrg while (n) 2866c321187Smrg { 2876c321187Smrg bits++; 2886c321187Smrg n >>= 1; 2896c321187Smrg } 2906c321187Smrg return icbrt_with_bits(a, bits); 2916c321187Smrg} 2926c321187Smrg 2936c321187Smrg 2946c321187Smrgstatic int 2956c321187Smrgicbrt_with_bits(int a, int bits) 2966c321187Smrg /* bits - log 2 of a */ 2976c321187Smrg{ 2986c321187Smrg return icbrt_with_guess(a, a>>2*bits/3); 2996c321187Smrg} 3006c321187Smrg 3016c321187Smrg#ifdef _X_ROOT_STATS 3026c321187Smrgint icbrt_loopcount; 3036c321187Smrg#endif 3046c321187Smrg 3056c321187Smrg/* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */ 3066c321187Smrg 3076c321187Smrg/* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */ 3086c321187Smrg 3096c321187Smrg/* 3106c321187Smrg * Quick and dirty cube roots. Nothing fancy here, just Newton's method. 3116c321187Smrg * Only works for positive integers (since that's all we need). 3126c321187Smrg * We actually return floor(cbrt(a)) because that's what we need here, too. 3136c321187Smrg */ 3146c321187Smrg 3156c321187Smrgstatic int 3166c321187Smrgicbrt_with_guess(int a, int guess) 3176c321187Smrg{ 3186c321187Smrg register int delta; 3196c321187Smrg 3206c321187Smrg#ifdef _X_ROOT_STATS 3216c321187Smrg icbrt_loopcount = 0; 3226c321187Smrg#endif 3236c321187Smrg if (a <= 0) 3246c321187Smrg return 0; 3256c321187Smrg if (guess < 1) 3266c321187Smrg guess = 1; 3276c321187Smrg 3286c321187Smrg do { 3296c321187Smrg#ifdef _X_ROOT_STATS 3306c321187Smrg icbrt_loopcount++; 3316c321187Smrg#endif 3326c321187Smrg delta = (guess - a/(guess*guess))/3; 33305e39ab5Swiz#if defined(DEBUG) && defined(_X_ROOT_STATS) 33405e39ab5Swiz printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta); 3356c321187Smrg#endif 3366c321187Smrg guess -= delta; 3376c321187Smrg } while (delta != 0); 3386c321187Smrg 3396c321187Smrg if (guess*guess*guess > a) 3406c321187Smrg guess--; 3416c321187Smrg 3426c321187Smrg return guess; 3436c321187Smrg} 344