CmapAlloc.c

Go to the documentation of this file.
00001 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
00002 
00003 /* 
00004 
00005 Copyright 1989, 1994, 1998  The Open Group
00006 
00007 Permission to use, copy, modify, distribute, and sell this software and its
00008 documentation for any purpose is hereby granted without fee, provided that
00009 the above copyright notice appear in all copies and that both that
00010 copyright notice and this permission notice appear in supporting
00011 documentation.
00012 
00013 The above copyright notice and this permission notice shall be included in
00014 all copies or substantial portions of the Software.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00019 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 Except as contained in this notice, the name of The Open Group shall not be
00024 used in advertising or otherwise to promote the sale, use or other dealings
00025 in this Software without prior written authorization from The Open Group.
00026 
00027 */
00028 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.6 2001/01/17 19:42:53 dawes Exp $ */
00029 
00030 /*
00031  * Author:  Donna Converse, MIT X Consortium
00032  */
00033 
00034 #include <X11/Xlib.h>
00035 #include <X11/Xatom.h>
00036 #include <X11/Xutil.h>
00037 #include <X11/Xmu/StdCmap.h>
00038 #include <stdio.h>
00039 
00040 #define lowbit(x) ((x) & (~(x) + 1))
00041 
00042 /*
00043  * Prototypes
00044  */
00045 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
00046                             unsigned long*);
00047 static int default_allocation(XVisualInfo*, unsigned long*,
00048                               unsigned long*, unsigned long*);
00049 static void gray_allocation(int, unsigned long*, unsigned long*,
00050                             unsigned long*);
00051 static int icbrt(int);
00052 static int icbrt_with_bits(int, int);
00053 static int icbrt_with_guess(int, int);
00054 
00055 /* To determine the best allocation of reds, greens, and blues in a 
00056  * standard colormap, use XmuGetColormapAllocation.
00057  *      vinfo           specifies visual information for a chosen visual
00058  *      property        specifies one of the standard colormap property names
00059  *      red_max         returns maximum red value 
00060  *      green_max       returns maximum green value
00061  *      blue_max        returns maximum blue value
00062  *
00063  * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
00064  * It is assumed that the visual is appropriate for the colormap property.
00065  */
00066 
00067 Status
00068 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
00069                          unsigned long *red_max,
00070                          unsigned long *green_max,
00071                          unsigned long *blue_max)
00072 {
00073     Status      status = 1;
00074 
00075     if (vinfo->colormap_size <= 2)
00076         return 0;
00077 
00078     switch (property)
00079     {
00080       case XA_RGB_DEFAULT_MAP:
00081         status = default_allocation(vinfo, red_max, green_max, blue_max);
00082         break;
00083       case XA_RGB_BEST_MAP:
00084         best_allocation(vinfo, red_max, green_max, blue_max);
00085         break;
00086       case XA_RGB_GRAY_MAP:
00087         gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
00088         break;
00089       case XA_RGB_RED_MAP:
00090         *red_max = vinfo->colormap_size - 1;
00091         *green_max = *blue_max = 0;
00092         break;
00093       case XA_RGB_GREEN_MAP:
00094         *green_max = vinfo->colormap_size - 1;
00095         *red_max = *blue_max = 0;
00096         break;
00097       case XA_RGB_BLUE_MAP:
00098         *blue_max = vinfo->colormap_size - 1;
00099         *red_max = *green_max = 0;
00100         break;
00101       default:
00102         status = 0;
00103     }
00104     return status;
00105 }
00106 
00107 /****************************************************************************/
00108 /* Determine the appropriate color allocations of a gray scale.
00109  *
00110  * Keith Packard, MIT X Consortium
00111  */
00112 
00113 static void
00114 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
00115                 unsigned long *blue_max)
00116 {
00117     *red_max = (n * 30) / 100;
00118     *green_max = (n * 59) / 100; 
00119     *blue_max = (n * 11) / 100; 
00120     *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
00121 }
00122 
00123 /****************************************************************************/
00124 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
00125  * If a map has less than a minimum number of definable entries, we do not
00126  * produce an allocation for an RGB_DEFAULT_MAP.  
00127  *
00128  * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
00129  * 12 each.  For 8 planes, let n = the number of colormap entries, which may
00130  * be 256 or 254.  Then, maximum red value = floor(cube_root(n - 125)) - 1.
00131  * Maximum green and maximum blue values are identical to maximum red.
00132  * This leaves at least 125 cells which clients can allocate.
00133  *
00134  * Return 0 if an allocation has been determined, non-zero otherwise.
00135  */
00136 
00137 static int
00138 default_allocation(XVisualInfo *vinfo, unsigned long *red,
00139                    unsigned long *green, unsigned long *blue)
00140 {
00141     int                 ngrays;         /* number of gray cells */
00142 
00143     switch (vinfo->class) {
00144       case PseudoColor:
00145 
00146         if (vinfo->colormap_size > 65000)
00147             /* intended for displays with 16 planes */
00148             *red = *green = *blue = (unsigned long) 27;
00149         else if (vinfo->colormap_size > 4000)
00150             /* intended for displays with 12 planes */
00151             *red = *green = *blue = (unsigned long) 12;
00152         else if (vinfo->colormap_size < 250)
00153             return 0;
00154         else
00155             /* intended for displays with 8 planes */
00156             *red = *green = *blue = (unsigned long)
00157                 (icbrt(vinfo->colormap_size - 125) - 1);
00158         break;
00159 
00160       case DirectColor:
00161 
00162         if (vinfo->colormap_size < 10)
00163             return 0;
00164         *red = *green = *blue = vinfo->colormap_size / 2 - 1;
00165         break;
00166 
00167       case TrueColor:
00168 
00169         *red = vinfo->red_mask / lowbit(vinfo->red_mask);
00170         *green = vinfo->green_mask / lowbit(vinfo->green_mask);
00171         *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
00172         break;
00173 
00174       case GrayScale:
00175 
00176         if (vinfo->colormap_size > 65000)
00177             ngrays = 4096;
00178         else if (vinfo->colormap_size > 4000)
00179             ngrays = 512;
00180         else if (vinfo->colormap_size < 250)
00181             return 0;
00182         else
00183             ngrays = 12;
00184         gray_allocation(ngrays, red, green, blue);
00185         break;
00186         
00187       default:
00188         return 0;
00189     }
00190     return 1;
00191 }
00192 
00193 /****************************************************************************/
00194 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
00195  *
00196  * For a DirectColor or TrueColor visual, the allocation is determined
00197  * by the red_mask, green_mask, and blue_mask members of the visual info.
00198  *
00199  * Otherwise, if the colormap size is an integral power of 2, determine
00200  * the allocation according to the number of bits given to each color,
00201  * with green getting more than red, and red more than blue, if there
00202  * are to be inequities in the distribution.  If the colormap size is
00203  * not an integral power of 2, let n = the number of colormap entries.
00204  * Then maximum red value = floor(cube_root(n)) - 1;
00205  *      maximum blue value = floor(cube_root(n)) - 1;
00206  *      maximum green value = n / ((# red values) * (# blue values)) - 1;
00207  * Which, on a GPX, allows for 252 entries in the best map, out of 254
00208  * defineable colormap entries.
00209  */
00210  
00211 static void
00212 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
00213                 unsigned long *blue)
00214 {
00215 
00216     if (vinfo->class == DirectColor ||  vinfo->class == TrueColor)
00217     {
00218         *red = vinfo->red_mask;
00219         while ((*red & 01) == 0)
00220             *red >>= 1;
00221         *green = vinfo->green_mask;
00222         while ((*green & 01) == 0)
00223             *green >>=1;
00224         *blue = vinfo->blue_mask;
00225         while ((*blue & 01) == 0)
00226             *blue >>= 1;
00227     }
00228     else
00229     {
00230         register int bits, n;
00231         
00232         /* Determine n such that n is the least integral power of 2 which is
00233          * greater than or equal to the number of entries in the colormap.
00234          */
00235         n = 1;
00236         bits = 0;
00237         while (vinfo->colormap_size > n)
00238         {
00239             n = n << 1;
00240             bits++;
00241         }
00242         
00243         /* If the number of entries in the colormap is a power of 2, determine
00244          * the allocation by "dealing" the bits, first to green, then red, then
00245          * blue.  If not, find the maximum integral red, green, and blue values
00246          * which, when multiplied together, do not exceed the number of 
00247 
00248          * colormap entries.
00249          */
00250         if (n == vinfo->colormap_size)
00251         {
00252             register int r, g, b;
00253             b = bits / 3;
00254             g = b + ((bits % 3) ? 1 : 0);
00255             r = b + (((bits % 3) == 2) ? 1 : 0);
00256             *red = 1 << r;
00257             *green = 1 << g;
00258             *blue = 1 << b;
00259         }
00260         else
00261         {
00262             *red = icbrt_with_bits(vinfo->colormap_size, bits);
00263             *blue = *red;       
00264             *green = (vinfo->colormap_size / ((*red) * (*blue)));
00265         }
00266         (*red)--;
00267         (*green)--;
00268         (*blue)--;
00269     }
00270     return;
00271 }
00272 
00273 /*
00274  * integer cube roots by Newton's method
00275  *
00276  * Stephen Gildea, MIT X Consortium, July 1991
00277  */
00278 
00279 static int
00280 icbrt(int a)
00281 {
00282     register int bits = 0;
00283     register unsigned n = a;
00284 
00285     while (n)
00286     {
00287         bits++;
00288         n >>= 1;
00289     }
00290     return icbrt_with_bits(a, bits);
00291 }
00292 
00293 
00294 static int
00295 icbrt_with_bits(int a, int bits)
00296      /* bits - log 2 of a */
00297 {
00298     return icbrt_with_guess(a, a>>2*bits/3);
00299 }
00300 
00301 #ifdef _X_ROOT_STATS
00302 int icbrt_loopcount;
00303 #endif
00304 
00305 /* Newton's Method:  x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
00306 
00307 /* for cube roots, x^3 - a = 0,  x_new = x - 1/3 (x - a/x^2) */
00308 
00309 /*
00310  * Quick and dirty cube roots.  Nothing fancy here, just Newton's method.
00311  * Only works for positive integers (since that's all we need).
00312  * We actually return floor(cbrt(a)) because that's what we need here, too.
00313  */
00314 
00315 static int
00316 icbrt_with_guess(int a, int guess)
00317 {
00318     register int delta;
00319 
00320 #ifdef _X_ROOT_STATS
00321     icbrt_loopcount = 0;
00322 #endif
00323     if (a <= 0)
00324         return 0;
00325     if (guess < 1)
00326         guess = 1;
00327 
00328     do {
00329 #ifdef _X_ROOT_STATS
00330         icbrt_loopcount++;
00331 #endif
00332         delta = (guess - a/(guess*guess))/3;
00333 #ifdef DEBUG
00334         printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
00335 #endif
00336         guess -= delta;
00337     } while (delta != 0);
00338 
00339     if (guess*guess*guess > a)
00340         guess--;
00341 
00342     return guess;
00343 }

Generated on Sun Mar 4 15:03:56 2007 for Scilab [trunk] by  doxygen 1.5.1