source: trunk/third/xscreensaver/utils/alpha.c @ 15683

Revision 15683, 6.0 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15682, which included commits to RCS files with non-trunk default branches.
Line 
1/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
2 *  Jamie Zawinski <jwz@jwz.org>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation.  No representations are made about the suitability of this
9 * software for any purpose.  It is provided "as is" without express or
10 * implied warranty.
11 */
12
13/* Beauty is only skin deep, unless you've got an alpha channel. */
14
15
16#include "utils.h"
17#include "alpha.h"
18#include "visual.h"
19#include "hsv.h"
20#include "yarandom.h"
21#include "resources.h"
22
23#include <X11/Xutil.h>
24
25#ifndef countof
26# define countof(x) (sizeof(*(x))/sizeof((x)))
27#endif
28
29
30/* I don't believe this fucking language doesn't have builtin exponentiation.
31   I further can't believe that the fucking ^ character means fucking XOR!! */
32static int
33i_exp (int i, int j)
34{
35  int k = 1;
36  while (j--) k *= i;
37  return k;
38}
39
40
41static void
42merge_colors (int argc, XColor **argv, XColor *into_color, int mask,
43              Bool additive_p)
44{
45  int j;
46  *into_color = *argv [0];
47  into_color->pixel |= mask;
48
49  for (j = 1; j < argc; j++)
50    {
51# define SHORT_INC(x,y) (x = ((((x)+(y)) > 0xFFFF) ? 0xFFFF : ((x)+(y))))
52# define SHORT_DEC(x,y) (x = ((((x)-(y)) < 0)      ? 0      : ((x)-(y))))
53      if (additive_p)
54        {
55          SHORT_INC (into_color->red,   argv[j]->red);
56          SHORT_INC (into_color->green, argv[j]->green);
57          SHORT_INC (into_color->blue,  argv[j]->blue);
58        }
59      else
60        {
61          SHORT_DEC (into_color->red,   argv[j]->red);
62          SHORT_DEC (into_color->green, argv[j]->green);
63          SHORT_DEC (into_color->blue,  argv[j]->blue);
64        }
65# undef SHORT_INC
66# undef SHORT_DEC
67    }
68}
69
70static void
71permute_colors (XColor *pcolors, XColor *colors,
72                int count,
73                unsigned long *plane_masks,
74                Bool additive_p)
75{
76  int out = 0;
77  int max = i_exp (2, count);
78  if (count > 31) abort ();
79  for (out = 1; out < max; out++)
80    {
81      XColor *argv [32];
82      int this_mask = 0;
83      int argc = 0;
84      int bit;
85      for (bit = 0; bit < 32; bit++)
86        if (out & (1<<bit))
87          {
88            argv [argc++] = &pcolors [bit];
89            this_mask |= plane_masks [bit];
90          }
91      merge_colors (argc, argv, &colors [out-1], this_mask, additive_p);
92    }
93}
94
95
96static int
97allocate_color_planes (Display *dpy, Colormap cmap,
98                       int nplanes, unsigned long *plane_masks,
99                       unsigned long *base_pixel_ret)
100{
101  while (nplanes > 1 &&
102         !XAllocColorCells (dpy, cmap, False, plane_masks, nplanes,
103                            base_pixel_ret, 1))
104    nplanes--;
105
106  return nplanes;
107}
108                       
109
110static void
111initialize_transparency_colormap (Display *dpy, Colormap cmap,
112                                  int nplanes,
113                                  unsigned long base_pixel,
114                                  unsigned long *plane_masks,
115                                  XColor *colors,
116                                  Bool additive_p)
117{
118  int i;
119  int total_colors = i_exp (2, nplanes);
120  XColor *all_colors = (XColor *) calloc (total_colors, sizeof (XColor));
121
122  for (i = 0; i < nplanes; i++)
123    colors[i].pixel = base_pixel | plane_masks [i];
124  permute_colors (colors, all_colors, nplanes, plane_masks, additive_p);
125
126  /* clone the default background of the window into our "base" pixel */
127  all_colors [total_colors - 1].pixel =
128    get_pixel_resource ("background", "Background", dpy, cmap);
129  XQueryColor (dpy, cmap, &all_colors [total_colors - 1]);
130  all_colors [total_colors - 1].pixel = base_pixel;
131
132  for (i = 0; i < total_colors; i++)
133    all_colors[i].flags = DoRed|DoGreen|DoBlue;
134  XStoreColors (dpy, cmap, all_colors, total_colors);
135  XFree ((XPointer) all_colors);
136}
137
138
139Bool
140allocate_alpha_colors (Screen *screen, Visual *visual, Colormap cmap,
141                       int *nplanesP, Bool additive_p,
142                       unsigned long **plane_masks,
143                       unsigned long *base_pixelP)
144{
145  Display *dpy = DisplayOfScreen (screen);
146  XColor *colors;
147  int nplanes = *nplanesP;
148  int i;
149
150  if (!has_writable_cells (screen, visual))
151    cmap = 0;
152
153  if (!cmap)            /* A TrueColor visual, or similar. */
154    {
155      int depth = visual_depth (screen, visual);
156      unsigned long masks;
157      XVisualInfo vi_in, *vi_out;
158
159      /* Find out which bits the R, G, and B components actually occupy
160         on this visual. */
161      vi_in.screen = screen_number (screen);
162      vi_in.visualid = XVisualIDFromVisual (visual);
163      vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
164                               &vi_in, &i);
165      if (! vi_out) abort ();
166      masks = vi_out[0].red_mask | vi_out[0].green_mask | vi_out[0].blue_mask;
167      XFree ((char *) vi_out);
168
169      if (nplanes > depth)
170        nplanes = depth;
171      *nplanesP = nplanes;
172      *base_pixelP = 0;
173      *plane_masks = (unsigned long *) calloc(sizeof(unsigned long), nplanes);
174
175      /* Pick the planar values randomly, but constrain them to fall within
176         the bit positions of the R, G, and B fields. */
177      for (i = 0; i < nplanes; i++)
178        (*plane_masks)[i] = random() & masks;
179
180    }
181  else                  /* A PseudoColor visual, or similar. */
182    {
183      if (nplanes > 31) nplanes = 31;
184      *plane_masks = (unsigned long *) malloc(sizeof(unsigned long) * nplanes);
185
186      nplanes = allocate_color_planes (dpy, cmap, nplanes, *plane_masks,
187                                   base_pixelP);
188      *nplanesP = nplanes;
189
190      if (nplanes <= 1)
191        {
192          free(*plane_masks);
193          *plane_masks = 0;
194          return False;
195        }
196
197      colors = (XColor *) calloc (nplanes, sizeof (XColor));
198      for (i = 0; i < nplanes; i++)
199        {
200          /* pick the base colors. If we are in subtractive mode, pick higher
201             intensities. */
202          hsv_to_rgb (random () % 360,
203                      frand (1.0),
204                      frand (0.5) + (additive_p ? 0.2 : 0.5),
205                      &colors[i].red,
206                      &colors[i].green,
207                      &colors[i].blue);
208        }
209      initialize_transparency_colormap (dpy, cmap, nplanes,
210                                        *base_pixelP, *plane_masks, colors,
211                                        additive_p);
212      XFree ((XPointer) colors);
213    }
214  return True;
215}
Note: See TracBrowser for help on using the repository browser.