00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
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
00056
00057
00058
00059
00060
00061
00062
00063
00064
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
00109
00110
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
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static int
00138 default_allocation(XVisualInfo *vinfo, unsigned long *red,
00139 unsigned long *green, unsigned long *blue)
00140 {
00141 int ngrays;
00142
00143 switch (vinfo->class) {
00144 case PseudoColor:
00145
00146 if (vinfo->colormap_size > 65000)
00147
00148 *red = *green = *blue = (unsigned long) 27;
00149 else if (vinfo->colormap_size > 4000)
00150
00151 *red = *green = *blue = (unsigned long) 12;
00152 else if (vinfo->colormap_size < 250)
00153 return 0;
00154 else
00155
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
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
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
00233
00234
00235 n = 1;
00236 bits = 0;
00237 while (vinfo->colormap_size > n)
00238 {
00239 n = n << 1;
00240 bits++;
00241 }
00242
00243
00244
00245
00246
00247
00248
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
00275
00276
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
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
00306
00307
00308
00309
00310
00311
00312
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 }