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