ftp://updates.redhat.com/enterprise/2.1AS/en/os/SRPMS/xscreensaver-3.33-4.rhel21...
[xscreensaver] / hacks / whirlygig.c
1 /*  Whirlygig -- an experiment in X programming
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  *  When I was in trigonometry class as a kid, I remember being fascinated
12  *  by the beauty of the shapes one receives when playing with sine waves
13  *  Here is a little experiment to show that beauty is simple
14  */
15 #include <math.h>
16 #include "screenhack.h"
17 #include <stdio.h>
18
19 static XColor colors[1000];
20 static int ncolors = 1000;
21 static int current_color = 0;
22
23 int 
24 draw_dot(Display *dpy, 
25          Window window, 
26          Colormap cmap, 
27          GC fgc, GC bgc,
28          int current_time,
29          int origin_x, int origin_y,
30          int screen_num, double xspeed, double yspeed,
31          int whirlies, int nlines) 
32 {
33     int size, last_size;  /* The size of my dot */
34     int start_arc = 0;  /* Start my circle at 0 degrees */
35     int end_arc = 23040;  /*  The number of degrees in a X circle (360 * 64) */
36     int horiz, vert;    /*  These will contain the new x,y coordinates to put my dot */
37     int last_horiz ,last_vert;  /*  These contain the positions to black out */
38     int last_time;
39     int count, line_count;
40     int line_offset, last_line_offset;
41     int color_offset;
42     XWindowAttributes xgwa;
43     XGetWindowAttributes (dpy, window, &xgwa);
44     if (++current_color >= ncolors)
45         current_color = 0;
46     for (count = 0; count < whirlies; count++) { 
47         color_offset = (current_color + (10 * count )) % ncolors;
48         if (current_time == count) { 
49             last_time = current_time; 
50         }
51         else {
52             current_time = current_time + count;
53             last_time = current_time - 1;
54         }
55         last_horiz = compute_x(last_time, origin_x, xspeed);
56         last_vert = compute_y(last_time, origin_y, yspeed);
57         horiz = compute_x(current_time, origin_x, xspeed);
58         vert = compute_y(current_time, origin_y, yspeed);
59         for (line_count = 0; line_count < nlines; line_count++) { 
60             last_line_offset = (int)(80.0 * line_count * sin((double)last_time / 90));
61             line_offset = (int)(80.0 * line_count * sin((double)current_time / 90));
62             last_size = (int)(15.0 + 5.0 * sin((double)last_time / 180.0));
63             size = (int)(15.0 + 5.0 * sin((double)current_time / 180.0));
64                 /* Get rid of the old circle */
65             XSetForeground(dpy, bgc, BlackPixel(dpy, screen_num));
66             XFillArc(dpy, window, bgc, last_horiz, last_line_offset+last_vert, last_size, last_size, start_arc, end_arc);
67                 /* Draw in the new circle */
68             XSetForeground(dpy, bgc, colors[color_offset].pixel);
69             XFillArc(dpy, window, bgc, horiz, line_offset+vert, size, size, start_arc, end_arc);
70         } 
71     }
72     XSync (dpy, False); 
73     if (current_time == 23040)
74     { 
75         return(1);
76     }
77     else 
78     {
79         return(0);
80     }
81 }
82
83 int compute_x(int the_time, int origin, double xspeed) 
84 {
85     double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI;
86     double the_cosine = cos((double)the_time / (180.0 * xspeed));
87     double dist_mod_x = cos((double)funky) * (origin - 50);
88     int horiz_pos = origin + (the_cosine * dist_mod_x);
89     return(horiz_pos);
90 }
91
92 int compute_y(int the_time, int origin, double yspeed)
93 {
94     double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI;
95     double the_sine = sin((double)the_time / (180.0 * yspeed));
96     double dist_mod_y = sin((double)funky) * (origin - 50);
97     int vert_pos = origin + (the_sine * dist_mod_y);
98     return(vert_pos);
99 }
100
101 char *progclass = "Whirlygig";
102
103 char *defaults [] = {
104   ".background:         black",
105   ".foreground:         white",
106   "*xspeed:             1.0",
107   "*yspeed:             1.0",
108   "*whirlies:           10",
109   "*nlines:             1",
110   0
111 };
112
113 XrmOptionDescRec options [] = {
114   { "-xspeed",          ".xspeed", XrmoptionSepArg, 0 },
115   { "-yspeed",          ".yspeed", XrmoptionSepArg, 0 },
116   { "-whirlies",         ".whirlies",XrmoptionSepArg, 0 },
117   { "-nlines",         ".nlines",XrmoptionSepArg, 0 },
118   { 0, 0, 0, 0 }
119 };
120
121 void screenhack (Display *dpy, Window window)
122 {
123     GC fgc, bgc;  /* the foreground and background graphics contexts */
124     XGCValues gcv;      /* The structure to hold the GC data */
125     XWindowAttributes xgwa;       /*  A structure to hold window data */
126     Bool writable = get_boolean_resource ("cycle", "Boolean");
127     double xspeed = get_float_resource( "xspeed", "Float");
128     double yspeed = get_float_resource( "yspeed", "Float");
129     int whirlies = get_integer_resource( "whirlies", "Integer");
130     int nlines = get_integer_resource( "nlines", "Integer");
131     int time_counter = 0;  /* This will be incremented in my while loop so that I can move my circle */
132     int screen_num = DefaultScreen(dpy);
133     int half_width, half_height;
134     XGetWindowAttributes (dpy, window, &xgwa);
135
136     half_width = xgwa.width / 2;
137     half_height = xgwa.height / 2;
138
139     gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, xgwa.colormap);
140     fgc = XCreateGC (dpy, window, GCForeground, &gcv);
141     gcv.foreground = get_pixel_resource("background", "Background", dpy, xgwa.colormap);
142     bgc = XCreateGC (dpy, window, GCForeground, &gcv);
143     make_uniform_colormap (dpy, xgwa.visual, xgwa.colormap, 
144                            colors, &ncolors, 
145                            True, &writable, True);
146     mono_p = True;
147     if (!mono_p)
148     {
149         GC tmp = fgc;
150         fgc = bgc;
151         bgc = tmp;
152     }
153
154     while (1)
155     {
156             /* draw_dot will return an interger.  If this interger is 0, then continue incrementing 
157                time_counter, if it is 1, then reset it to zero...  It should only become 1 with the sine
158                is 0 and the cosine is 1 */
159         if (draw_dot(dpy, window, xgwa.colormap, fgc, bgc, time_counter, half_width, half_height, screen_num, xspeed , yspeed, whirlies, nlines) == 1) {
160             time_counter = 1;
161         }
162         else {
163             time_counter++;
164         }
165         screenhack_handle_events (dpy);
166
167         if (!writable)
168             usleep(10);
169     }
170 }
171