1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* ico --- bouncing polyhedra */
3
4 #if 0
5 static const char sccsid[] = "@(#)ico.c 5.00 2000/11/01 xlockmore";
6
7 #endif
8 /*-
9 * Copyright (c) 1987 X Consortium
10 *
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
16 *
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
22 *
23 * Revision History:
24 * 01-Nov-2000: Allocation checks
25 * 27-Mar-2000: Added double buffering for drawings
26 * 10-May-1997: Compatible with xscreensaver
27 * 25-Mar-1997: David Bagley <bagleyd AT verizon.net>
28 * Took ico from the X11R6 distribution. Stripped out
29 * anything complicated... to be added back in later.
30 * added dodecahedron, tetrahedron, and star octahedron.
31 * $XConsortium: ico.c,v 1.47 94/04/17 20:45:15 gildea Exp $
32 */
33
34 /*-
35 original copyright
36 Permission is hereby granted, free of charge, to any person obtaining a copy
37 of this software and associated documentation files (the "Software"), to deal
38 in the Software without restriction, including without limitation the rights
39 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40 copies of the Software, and to permit persons to whom the Software is
41 furnished to do so, subject to the following conditions:
42
43 The above copyright notice and this permission notice shall be included in
44 all copies or substantial portions of the Software.
45
46 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
50 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
51 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52
53 Except as contained in this notice, the name of the X Consortium shall not be
54 used in advertising or otherwise to promote the sale, use or other dealings
55 in this Software without prior written authorization from the X Consortium.
56
57
58 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
59
60 All Rights Reserved
61
62 Permission to use, copy, modify, and distribute this software and its
63 documentation for any purpose and without fee is hereby granted,
64 provided that the above copyright notice appear in all copies and that
65 both that copyright notice and this permission notice appear in
66 supporting documentation, and that the name of Digital not be
67 used in advertising or publicity pertaining to distribution of the
68 software without specific, written prior permission.
69
70 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76 SOFTWARE.
77
78 ******************************************************************/
79 /******************************************************************************
80 * Description
81 * Display a wire-frame rotating icosahedron, with hidden lines removed
82 *****************************************************************************/
83 /*-
84 * Additions by jimmc@sci:
85 * faces and colors
86 * double buffering on the display
87 * additional polyhedra
88 *
89 * multi-thread version by Stephen Gildea, January 1992
90 */
91
92 #ifdef STANDALONE
93 #define MODE_ico
94 #define DEFAULTS "*delay: 100000 \n" \
95 "*count: 0 \n" \
96 "*cycles: 300 \n" \
97 "*ncolors: 200 \n" \
98
99 # define free_ico 0
100 # define reshape_ico 0
101 # define ico_handle_event 0
102 #define UNIFORM_COLORS
103 #define BRIGHT_COLORS
104 #include "xlockmore.h" /* in xscreensaver distribution */
105 #else /* STANDALONE */
106 #include "xlock.h" /* in xlockmore distribution */
107 #define DO_STIPPLE
108 #endif /* STANDALONE */
109 #include "automata.h"
110
111 #ifdef MODE_ico
112
113 #define DEF_FACES "True"
114 #define DEF_EDGES "True"
115 #define DEF_OPAQUE "True"
116
117 static Bool faces;
118 static Bool edges;
119 static Bool opaque;
120
121 static XrmOptionDescRec opts[] =
122 {
123 {(char *) "-faces", (char *) ".ico.faces", XrmoptionNoArg, (caddr_t) "on"},
124 {(char *) "+faces", (char *) ".ico.faces", XrmoptionNoArg, (caddr_t) "off"},
125 {(char *) "-edges", (char *) ".ico.edges", XrmoptionNoArg, (caddr_t) "on"},
126 {(char *) "+edges", (char *) ".ico.edges", XrmoptionNoArg, (caddr_t) "off"},
127 {(char *) "-opaque", (char *) ".ico.opaque", XrmoptionNoArg, (caddr_t) "on"},
128 {(char *) "+opaque", (char *) ".ico.opaque", XrmoptionNoArg, (caddr_t) "off"}
129 };
130 static argtype vars[] =
131 {
132 {(void *) & faces, (char *) "faces", (char *) "Faces", (char *) DEF_FACES, t_Bool},
133 {(void *) & edges, (char *) "edges", (char *) "Edges", (char *) DEF_EDGES, t_Bool},
134 {(void *) & opaque, (char *) "opaque", (char *) "Opaque", (char *) DEF_OPAQUE, t_Bool}
135 };
136 static OptionStruct desc[] =
137 {
138 {(char *) "-/+faces", (char *) "turn on/off drawing of faces"},
139 {(char *) "-/+edges", (char *) "turn on/off drawing of wireframe"},
140 {(char *) "-/+opaque", (char *) "turn on/off drawing of bottom (unless faces true)"}
141 };
142
143 ENTRYPOINT ModeSpecOpt ico_opts =
144 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
145
146 #ifdef USE_MODULES
147 ModStruct ico_description =
148 {"ico", "init_ico", "draw_ico", "release_ico",
149 "refresh_ico", "change_ico", (char *) NULL, &ico_opts,
150 200000, 0, 400, 0, 64, 1.0, "",
151 "Shows a bouncing polyhedron", 0, NULL};
152
153 #endif
154
155 #define MINSIZE 5
156 #define DEFAULT_DELTAX 13
157 #define DEFAULT_DELTAY 9
158
159 /*-
160 * This is the description of one polyhedron file
161 */
162
163 #define MAXVERTS 120
164 /* great rhombicosidodecahedron has 120 vertices */
165 #define MAXNV MAXVERTS
166 #define MAXFACES 30
167 /* (hexakis icosahedron has 120 faces) */
168 #define MAXEDGES 180
169 /* great rhombicosidodecahedron has 180 edges */
170 #define MAXEDGESPERPOLY 20
171
172 typedef struct {
173 double x, y, z;
174 } Point3D;
175
176 /* structure of the include files which define the polyhedra */
177 typedef struct {
178 #ifdef DEFUNCT
179 char *longname; /* long name of object */
180 char *shortname; /* short name of object */
181 char *dual; /* long name of dual */
182 #endif
183 int numverts; /* number of vertices */
184 int numedges; /* number of edges */
185 int numfaces; /* number of faces */
186 Point3D v[MAXVERTS]; /* the vertices */
187 int f[MAXEDGES * 2 + MAXFACES]; /* the faces */
188 } Polyinfo;
189
190 /*-
191 * faces/edges/vert Vertex Config Wythoff Symbol
192 * Platonic Solids:
193 * tetrahedron 4/6/4 {3,3,3} 3|2 3
194 * cube 6/12/8 {4,4,4} 3|2 4
195 * octahedron 8/12/6 {3,3,3,3} 4|2 3
196 * dodecahedron 12/30/20 {5,5,5} 3|2 5
197 * icosahedron 20/30/12 {3,3,3,3,3} 5|2 3
198 *
199 * Edge Transitive Catalan Solids:
200 * rhombic dodecahedron 12/24/14
201 * rhombic triacontahedron 30/60/32
202 *
203 * Space Filling Archimedean Solid:
204 * truncated octahedron
205 *
206 * Polyhedron Compound:
207 * stella octangula
208 *
209 * Kepler-Poinsot Solids (not added yet):
210 * small stellated dodecahedron 12/30/12 {5/2,5/2,5/2,5/2,5/2} 5|2 5/2
211 * great stellated dodecahedron 12/30/20 {5/2,5/2,5/2} 3|2 5/2
212 * great dodecahedron 12/30/12 {5,5,5,5,5}/2 5/2|2 5
213 * great icosahedron 20/30/12 {3,3,3,3,3}/2 5/2|2 3
214 */
215
216 static Polyinfo polygons[] =
217 {
218
219 /* objtetra - structure values for tetrahedron */
220 {
221 #ifdef DEFUNCT
222 "tetrahedron", "tetra", /* long and short names */
223 "tetrahedron", /* long name of dual */
224 #endif
225 4, 6, 4, /* number of vertices, edges, and faces */
226 { /* vertices (x,y,z) */
227 /* all points must be within radius 1 of the origin */
228 #define T 0.57735
229 {T, T, T},
230 {T, -T, -T},
231 {-T, T, -T},
232 {-T, -T, T},
233 #undef T
234 },
235 { /* faces (numfaces + indexes into vertices) */
236 /* faces must be specified clockwise from the outside */
237 3, 2, 1, 0,
238 3, 1, 3, 0,
239 3, 3, 2, 0,
240 3, 2, 3, 1,
241 }
242 },
243
244 /* objcube - structure values for cube */
245
246 {
247 #ifdef DEFUNCT
248 "hexahedron", "cube", /* long and short names */
249 "octahedron", /* long name of dual */
250 #endif
251 8, 12, 6, /* number of vertices, edges, and faces */
252 { /* vertices (x,y,z) */
253 /* all points must be within radius 1 of the origin */
254 #define T 0.57735
255 {T, T, T},
256 {T, T, -T},
257 {T, -T, -T},
258 {T, -T, T},
259 {-T, T, T},
260 {-T, T, -T},
261 {-T, -T, -T},
262 {-T, -T, T},
263 #undef T
264 },
265 { /* faces (numfaces + indexes into vertices) */
266 /* faces must be specified clockwise from the outside */
267 4, 0, 1, 2, 3,
268 4, 7, 6, 5, 4,
269 4, 1, 0, 4, 5,
270 4, 3, 2, 6, 7,
271 4, 2, 1, 5, 6,
272 4, 0, 3, 7, 4,
273 }
274 },
275
276 /* objocta - structure values for octahedron */
277
278 {
279 #ifdef DEFUNCT
280 "octahedron", "octa", /* long and short names */
281 "hexahedron", /* long name of dual */
282 #endif
283 6, 12, 8, /* number of vertices, edges, and faces */
284 { /* vertices (x,y,z) */
285 /* all points must be within radius 1 of the origin */
286 #define T 1.0
287 {T, 0, 0},
288 {-T, 0, 0},
289 {0, T, 0},
290 {0, -T, 0},
291 {0, 0, T},
292 {0, 0, -T},
293 #undef T
294 },
295 { /* faces (numfaces + indexes into vertices) */
296 /* faces must be specified clockwise from the outside */
297 3, 0, 4, 2,
298 3, 0, 2, 5,
299 3, 0, 5, 3,
300 3, 0, 3, 4,
301 3, 1, 2, 4,
302 3, 1, 5, 2,
303 3, 1, 3, 5,
304 3, 1, 4, 3,
305 }
306 },
307
308 /* objdodeca - structure values for dodecahedron */
309
310 {
311 #ifdef DEFUNCT
312 "dodecahedron", "dodeca", /* long and short names */
313 "icosahedron", /* long name of dual */
314 #endif
315 20, 30, 12, /* number of vertices, edges, and faces */
316 { /* vertices (x,y,z) */
317 /* all points must be within radius 1 of the origin */
318 #define G 0.3090169943749474241 /* cos 72 */
319 #define D 0.8090169943749474241 /* cos 36 */
320 #define H 0.5
321 {0, G, D},
322 {0, -G, D},
323 {0, -G, -D},
324 {0, G, -D},
325 {D, 0, G},
326 {-D, 0, G},
327 {-D, 0, -G},
328 {D, 0, -G},
329 {G, D, 0},
330 {-G, D, 0},
331 {-G, -D, 0},
332 {G, -D, 0},
333 {H, H, H},
334 {-H, H, H},
335 {-H, -H, H},
336 {H, -H, H},
337 {H, -H, -H},
338 {H, H, -H},
339 {-H, H, -H},
340 {-H, -H, -H},
341 #undef G
342 #undef D
343 #undef H
344 },
345 { /* faces (numfaces + indexes into vertices) */
346 /* faces must be specified clockwise from the outside */
347 5, 12, 8, 17, 7, 4,
348 5, 5, 6, 18, 9, 13,
349 5, 14, 10, 19, 6, 5,
350 5, 12, 4, 15, 1, 0,
351 5, 13, 9, 8, 12, 0,
352 5, 1, 14, 5, 13, 0,
353 5, 16, 7, 17, 3, 2,
354 5, 19, 10, 11, 16, 2,
355 5, 3, 18, 6, 19, 2,
356 5, 15, 11, 10, 14, 1,
357 5, 3, 17, 8, 9, 18,
358 5, 4, 7, 16, 11, 15,
359 }
360 },
361
362 /* objicosa - structure values for icosahedron */
363
364 {
365 #ifdef DEFUNCT
366 "icosahedron", "icosa", /* long and short names */
367 "dodecahedron", /* long name of dual */
368 #endif
369 12, 30, 20, /* number of vertices, edges, and faces */
370 { /* vertices (x,y,z) */
371 /* all points must be within radius 1 of the origin */
372 #define A 0.26286556
373 #define B 0.42532537
374 #define C 0.68819095
375 #define D 0.8090169943749474241 /* cos 36 */
376 #define E 0.8506508083520399322 /* cossec 36 / 2 */
377 #define F 0.9510565162951535721 /* sin 72 */
378 #define H 0.5
379 {0, 0, -F},
380 {0, E, -B},
381 {D, A, -B},
382 {H, -C, -B},
383 {-H, -C, -B},
384 {-D, A, -B},
385 {H, C, B},
386 {D, -A, B},
387 {0, -E, B},
388 {-D, -A, B},
389 {-H, C, B},
390 {0, 0, F}
391 #undef A
392 #undef B
393 #undef C
394 #undef D
395 #undef E
396 #undef F
397 #undef H
398 },
399 { /* faces (numfaces + indexes into vertices) */
400 /* faces must be specified clockwise from the outside */
401 3, 0, 2, 1,
402 3, 0, 3, 2,
403 3, 0, 4, 3,
404 3, 0, 5, 4,
405 3, 0, 1, 5,
406 3, 1, 6, 10,
407 3, 1, 2, 6,
408 3, 2, 7, 6,
409 3, 2, 3, 7,
410 3, 3, 8, 7,
411 3, 3, 4, 8,
412 3, 4, 9, 8,
413 3, 4, 5, 9,
414 3, 5, 10, 9,
415 3, 5, 1, 10,
416 3, 10, 6, 11,
417 3, 6, 7, 11,
418 3, 7, 8, 11,
419 3, 8, 9, 11,
420 3, 9, 10, 11
421 }
422 },
423
424 /* objrhombicdoeca - structure values for rhombic dodecahedron */
425
426 {
427 #ifdef DEFUNCT
428 "rhombic_dodecahedron", "rhombic", /* long and short names */
429 "cubooctahedron", /* long name of dual */
430 #endif
431 14, 24, 12, /* number of vertices, edges, and faces */
432 { /* vertices (x,y,z) */
433 /* all points must be within radius 1 of the origin */
434 #define T 1.0
435 #define H 0.5
436 {T, 0, 0},
437 {0, T, 0},
438 {0, 0, T},
439 {H, H, H},
440 {H, H, -H},
441 {H, -H, H},
442 {H, -H, -H},
443 {-H, H, H},
444 {-H, H, -H},
445 {-H, -H, H},
446 {-H, -H, -H},
447 {-T, 0, 0},
448 {0, -T, 0},
449 {0, 0, -T},
450 #undef H
451 #undef T
452 },
453 { /* faces (numfaces + indexes into vertices) */
454 /* faces must be specified clockwise from the outside */
455 4, 0, 3, 2, 5,
456 4, 2, 9, 12, 5,
457 4, 2, 7, 11, 9,
458 4, 1, 7, 2, 3,
459 4, 0, 4, 1, 3,
460 4, 0, 5, 12, 6,
461 4, 9, 11, 10, 12,
462 4, 1, 8, 11, 7,
463 4, 0, 6, 13, 4,
464 4, 6, 12, 10, 13,
465 4, 8, 13, 10, 11,
466 4, 1, 4, 13, 8,
467 }
468 },
469
470 /* objtriacont - structure values for rhombic triacontahedron */
471
472 {
473 #ifdef DEFUNCT
474 "rhombic_triacontahedron", "triaconta", /* long and short names */
475 "icosidodecahedron", /* long name of dual */
476 #endif
477 32, 60, 30, /* number of vertices, edges, and faces */
478 { /* vertices (x,y,z) */
479 /* all points must be within radius 1 of the origin */
480 #define G 0.3090169943749474241 /* cos 72 */
481 #define D 0.8090169943749474241 /* cos 36 */
482 #define H 0.5
483 {0, G, D},
484 {0, -G, D},
485 {0, -G, -D},
486 {0, G, -D},
487 {D, 0, G},
488 {-D, 0, G},
489 {-D, 0, -G},
490 {D, 0, -G},
491 {G, D, 0},
492 {-G, D, 0},
493 {-G, -D, 0},
494 {G, -D, 0},
495 {H, H, H},
496 {-H, H, H},
497 {-H, -H, H},
498 {H, -H, H},
499 {H, -H, -H},
500 {H, H, -H},
501 {-H, H, -H},
502 {-H, -H, -H},
503 {0, D, H},
504 {0, -D, H},
505 {0, D, -H},
506 {0, -D, -H},
507 {H, 0, D},
508 {-H, 0, D},
509 {H, 0, -D},
510 {-H, 0, -D},
511 {D, H, 0},
512 {-D, H, 0},
513 {D, -H, 0},
514 {-D, -H, 0},
515 #undef D
516 #undef H
517 #undef G
518 },
519 { /* faces (numfaces + indexes into vertices) */
520 /* faces must be specified clockwise from the outside */
521 4, 8, 20, 12, 28,
522 4, 0, 24, 12, 20,
523 4, 4, 28, 12, 24,
524 4, 8, 22, 9, 20,
525 4, 8, 28, 17, 22,
526 4, 9, 29, 13, 20,
527 4, 0, 20, 13, 25,
528 4, 0, 25, 1, 24,
529 4, 5, 25, 13, 29,
530 4, 9, 22, 18, 29,
531 4, 3, 27, 18, 22,
532 4, 3, 22, 17, 26,
533 4, 6, 29, 18, 27,
534 4, 7, 26, 17, 28,
535 4, 2, 27, 3, 26,
536 4, 4, 30, 7, 28,
537 4, 4, 24, 15, 30,
538 4, 7, 30, 16, 26,
539 4, 1, 21, 15, 24,
540 4, 1, 25, 14, 21,
541 4, 11, 30, 15, 21,
542 4, 11, 23, 16, 30,
543 4, 2, 26, 16, 23,
544 4, 10, 23, 11, 21,
545 4, 2, 23, 19, 27,
546 4, 10, 31, 19, 23,
547 4, 10, 21, 14, 31,
548 4, 5, 31, 14, 25,
549 4, 5, 29, 6, 31,
550 4, 6, 27, 19, 31,
551 }
552 },
553
554 /* objtruncoct - structure values for truncated octahedron */
555
556 {
557 #ifdef DEFUNCT
558 "truncated_octahedron", "mecon", /* long and short names */
559 "tetrakis_hexahedron", /* long name of dual */
560 #endif
561 24, 36, 14, /* number of vertices, edges, and faces */
562 { /* vertices (x,y,z) */
563 /* all points must be within radius 1 of the origin */
564 #define T 0.8506508083520399322 /* cossec 36 / 2 */
565 #define H 0.42532537
566 {T, H, 0},
567 {T, -H, 0},
568 {T, 0, H},
569 {T, 0, -H},
570 {-T, H, 0},
571 {-T, -H, 0},
572 {-T, 0, H},
573 {-T, 0, -H},
574 {H, T, 0},
575 {-H, T, 0},
576 {0, T, H},
577 {0, T, -H},
578 {H, -T, 0},
579 {-H, -T, 0},
580 {0, -T, H},
581 {0, -T, -H},
582 {H, 0, T},
583 {-H, 0, T},
584 {0, H, T},
585 {0, -H, T},
586 {H, 0, -T},
587 {-H, 0, -T},
588 {0, H, -T},
589 {0, -H, -T},
590 #undef H
591 #undef T
592 },
593 { /* faces (numfaces + indexes into vertices) */
594 /* faces must be specified clockwise from the outside */
595 4, 0, 2, 1, 3,
596 4, 4, 7, 5, 6,
597 4, 8, 11, 9, 10,
598 4, 12, 14, 13, 15,
599 4, 16, 18, 17, 19,
600 4, 20, 23, 21, 22,
601 6, 2, 0, 8, 10, 18, 16,
602 6, 0, 3, 20, 22, 11, 8,
603 6, 1, 2, 16, 19, 14, 12,
604 6, 3, 1, 12, 15, 23, 20,
605 6, 4, 6, 17, 18, 10, 9,
606 6, 7, 4, 9, 11, 22, 21,
607 6, 6, 5, 13, 14, 19, 17,
608 6, 5, 7, 21, 23, 15, 13,
609 }
610 },
611
612 /* ico does not draw non-convex polyhedra well. */
613 /* objstar - structure values for octahedron star (stellated octahedron?) */
614 {
615 #ifdef DEFUNCT
616 "stella_octangula", "star", /* long and short names */
617 "stella_octangula", /* long name of dual */
618 #endif
619 14, 36, 24, /* number of vertices, edges, and faces */
620 /*8, 12, 8,*/ /* number of real vertices, edges, and faces */
621 { /* vertices (x,y,z) */
622 /* all points must be within radius 1 of the origin */
623 #define T 0.577
624 {-T, 0, 0},
625 {0, -T, 0},
626 {0, 0, -T},
627 {0, 0, T},
628 {0, T, 0},
629 {T, 0, 0},
630 {-T, -T, -T},
631 {-T, -T, T},
632 {-T, T, -T},
633 {-T, T, T},
634 {T, -T, -T},
635 {T, -T, T},
636 {T, T, -T},
637 {T, T, T},
638 #undef T
639 /*#define T 0.577
640 {T, T, T},
641 {T, -T, -T},
642 {-T, T, -T},
643 {-T, -T, T},
644 {-T, -T, -T},
645 {-T, T, T},
646 {T, -T, T},
647 {T, T, -T},
648 #undef T*/
649
650 },
651 { /* faces (numfaces + indexes into vertices) */
652 /* faces must be specified clockwise from the outside */
653 3, 13, 5, 4,
654 3, 13, 3, 5,
655 3, 13, 4, 3,
656 3, 12, 4, 5,
657 3, 12, 5, 2,
658 3, 12, 2, 4,
659 3, 11, 1, 5,
660 3, 11, 5, 3,
661 3, 11, 3, 1,
662 3, 10, 5, 1,
663 3, 10, 2, 5,
664 3, 10, 1, 2,
665 3, 9, 4, 0,
666 3, 9, 0, 3,
667 3, 9, 3, 4,
668 3, 8, 0, 4,
669 3, 8, 2, 0,
670 3, 8, 4, 2,
671 3, 7, 0, 1,
672 3, 7, 3, 0,
673 3, 7, 1, 3,
674 3, 6, 1, 0,
675 3, 6, 0, 2,
676 3, 6, 2, 1,
677 /*
678 3, 2, 1, 0,
679 3, 1, 3, 0,
680 3, 3, 2, 0,
681 3, 2, 3, 1,
682 3, 6, 5, 4,
683 3, 5, 7, 4,
684 3, 7, 6, 4,
685 3, 6, 7, 5,
686 */
687 }
688 },
689 /* objplane - structure values for plane */
690
691 {
692 #ifdef DEFUNCT
693 "plane", "plane", /* long and short names */
694 "plane", /* long name of dual?? */
695 #endif
696 4, 4, 1, /* number of vertices, edges, and faces */
697 { /* vertices (x,y,z) */
698 /* all points must be within radius 1 of the origin */
699 #define T 1.0
700 {T, 0, 0},
701 {-T, 0, 0},
702 {0, T, 0},
703 {0, -T, 0},
704 #undef T
705 },
706 { /* faces (numfaces + indexes into vertices) */
707 /* faces must be specified clockwise from the outside */
708 4, 0, 2, 1, 3,
709 }
710 },
711
712 /* objpyr - structure values for pyramid */
713
714 {
715 #ifdef DEFUNCT
716 "pyramid", "pyramid", /* long and short names */
717 "pyramid", /* long name of dual */
718 #endif
719 5, 8, 5, /* number of vertices, edges, and faces */
720 { /* vertices (x,y,z) */
721 /* all points must be within radius 1 of the origin */
722 #define T 1.0
723 {T, 0, 0},
724 {-T, 0, 0},
725 {0, T, 0},
726 {0, -T, 0},
727 {0, 0, T},
728 /* {0, 0, -T }, */
729 #undef T
730 },
731 { /* faces (numfaces + indexes into vertices) */
732 /* faces must be specified clockwise from the outside */
733 3, 0, 4, 2,
734 3, 0, 3, 4,
735 3, 1, 2, 4,
736 3, 1, 4, 3,
737 4, 0, 2, 1, 3,
738 }
739 },
740
741 };
742
743 static int polysize = sizeof (polygons) / sizeof (polygons[0]);
744 #define POLYSIZE 8 /* Only the 5 Platonic solids, the 2 edge transitive*/
745 /* Catalan solids and the space filling Archimedean solid work */
746
747 #define POLYBITS(n,w,h)\
748 if ((ip->pixmaps[ip->init_bits]=\
749 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
750 free_ico_screen(display,ip);return;} else {ip->init_bits++;}
751
752 typedef double Transform3D[4][4];
753
754 /* variables that need to be per-thread */
755
756 typedef struct {
757 int loopcount;
758 int object;
759 int width, height;
760 int linewidth;
761 long color;
762 Polyinfo *poly;
763 int polyW, polyH;
764 int currX, currY;
765 int prevX, prevY;
766 int polyDeltaX, polyDeltaY;
767 int deltaWidth, deltaHeight;
768 Bool faces, edges, opaque;
769 char drawnEdges[MAXNV][MAXNV];
770 char drawnPoints[MAXNV];
771 int xv_buffer;
772 Transform3D xform;
773 Point3D xv[2][MAXNV];
774 double wo2, ho2;
775 Pixmap dbuf;
776 GC dbuf_gc;
777 int color_offset;
778 int init_bits;
779 GC stippledGC;
780 Pixmap pixmaps[NUMSTIPPLES - 1];
781 } icostruct;
782
783 static icostruct *icos = (icostruct *) NULL;
784
785 /*-
786 * variables that are not set except maybe in initialization before
787 * any additional threads are created
788 */
789
790
791 static void
icoClearArea(ModeInfo * mi,int x,int y,int w,int h)792 icoClearArea(ModeInfo * mi, int x, int y, int w, int h)
793 {
794 Display *display = MI_DISPLAY(mi);
795
796 #if 1
797 /* my monochrome likes this better */
798 XSetForeground(display, MI_GC(mi), MI_BLACK_PIXEL(mi));
799 XFillRectangle(display, MI_WINDOW(mi), MI_GC(mi), x, y, w, h);
800 #else
801 XClearArea(display, MI_WINDOW(mi), x, y, w, h, 0);
802 #endif
803 }
804
805 /******************************************************************************
806 * Description
807 * Format a 4x4 identity matrix.
808 *
809 * Output
810 * *m Formatted identity matrix
811 *****************************************************************************/
812 static void
IdentMat(register Transform3D m)813 IdentMat(register Transform3D m)
814 {
815 register int i;
816 register int j;
817
818 for (i = 3; i >= 0; --i) {
819 for (j = 3; j >= 0; --j)
820 m[i][j] = 0.0;
821 m[i][i] = 1.0;
822 }
823 }
824
825
826
827 /******************************************************************************
828 * Description
829 * Format a matrix that will perform a rotation transformation
830 * about the specified axis. The rotation angle is measured
831 * counterclockwise about the specified axis when looking
832 * at the origin from the positive axis.
833 *
834 * Input
835 * axis Axis ('x', 'y', 'z') about which to perform rotation
836 * angle Angle (in radians) of rotation
837 * A Pointer to rotation matrix
838 *
839 * Output
840 * *m Formatted rotation matrix
841 *****************************************************************************/
842
843 static void
FormatRotateMat(char axis,double angle,register Transform3D m)844 FormatRotateMat(char axis, double angle, register Transform3D m)
845 {
846 double s, c;
847
848 IdentMat(m);
849
850 s = sin(angle);
851 c = cos(angle);
852
853 switch (axis) {
854 case 'x':
855 m[1][1] = m[2][2] = c;
856 m[1][2] = s;
857 m[2][1] = -s;
858 break;
859 case 'y':
860 m[0][0] = m[2][2] = c;
861 m[2][0] = s;
862 m[0][2] = -s;
863 break;
864 case 'z':
865 m[0][0] = m[1][1] = c;
866 m[0][1] = s;
867 m[1][0] = -s;
868 break;
869 }
870 }
871
872
873 /******************************************************************************
874 * Description
875 * Concatenate two 4-by-4 transformation matrices.
876 *
877 * Input
878 * l multiplicand (left operand)
879 * r multiplier (right operand)
880 *
881 * Output
882 * *m Result matrix
883 *****************************************************************************/
884
885 static void
ConcatMat(register Transform3D l,register Transform3D r,register Transform3D m)886 ConcatMat(register Transform3D l, register Transform3D r,
887 register Transform3D m)
888 {
889 register int i;
890 register int j;
891
892 for (i = 0; i < 4; ++i)
893 for (j = 0; j < 4; ++j)
894 m[i][j] = l[i][0] * r[0][j]
895 + l[i][1] * r[1][j]
896 + l[i][2] * r[2][j]
897 + l[i][3] * r[3][j];
898 }
899
900 /* Set up points, transforms, etc. */
901
902 static void
initPoly(ModeInfo * mi,Polyinfo * poly,int polyW,int polyH,Bool init)903 initPoly(ModeInfo * mi, Polyinfo * poly, int polyW, int polyH, Bool init)
904 {
905 icostruct *ip = &icos[MI_SCREEN(mi)];
906 Point3D *vertices = poly->v;
907 int NV = poly->numverts;
908 Transform3D r1;
909 Transform3D r2;
910
911 #define ROLL_DEGREES 5
912 if ((ip->polyDeltaX < 0 && ip->polyDeltaY < 0) ||
913 (ip->polyDeltaX > 0 && ip->polyDeltaY > 0)) {
914 FormatRotateMat('x', ((ip->polyDeltaX > 0) ?
915 -ROLL_DEGREES : ROLL_DEGREES) * M_PI / 180.0, r1);
916 FormatRotateMat('y', ((ip->polyDeltaY < 0) ?
917 -ROLL_DEGREES : ROLL_DEGREES) * M_PI / 180.0, r2);
918 } else {
919 FormatRotateMat('x', ((ip->polyDeltaX < 0) ?
920 -ROLL_DEGREES : ROLL_DEGREES) * M_PI / 180.0, r1);
921 FormatRotateMat('y', ((ip->polyDeltaY > 0) ?
922 -ROLL_DEGREES : ROLL_DEGREES) * M_PI / 180.0, r2);
923 }
924 ConcatMat(r1, r2, ip->xform);
925 if (init) {
926 (void) memcpy((char *) ip->xv[0], (char *) vertices, NV * sizeof (Point3D));
927 ip->xv_buffer = 0;
928 ip->wo2 = polyW / 2.0;
929 ip->ho2 = polyH / 2.0;
930 }
931 }
932
933 /******************************************************************************
934 * Description
935 * Perform a partial transform on non-homogeneous points.
936 * Given an array of non-homogeneous (3-coordinate) input points,
937 * this routine multiplies them by the 3-by-3 upper left submatrix
938 * of a standard 4-by-4 transform matrix. The resulting non-homogeneous
939 * points are returned.
940 *
941 * Input
942 * n number of points to transform
943 * m 4-by-4 transform matrix
944 * in array of non-homogeneous input points
945 *
946 * Output
947 * *out array of transformed non-homogeneous output points
948 *****************************************************************************/
949
950 static void
PartialNonHomTransform(int n,register Transform3D m,register Point3D * in,register Point3D * out)951 PartialNonHomTransform(int n, register Transform3D m,
952 register Point3D * in, register Point3D * out)
953 {
954 for (; n > 0; --n, ++in, ++out) {
955 out->x = in->x * m[0][0] + in->y * m[1][0] + in->z * m[2][0];
956 out->y = in->x * m[0][1] + in->y * m[1][1] + in->z * m[2][1];
957 out->z = in->x * m[0][2] + in->y * m[1][2] + in->z * m[2][2];
958 }
959 }
960
961
962 /******************************************************************************
963 * Description
964 * Undraw previous polyhedron (by erasing its bounding box).
965 * Rotate and draw the new polyhedron.
966 *
967 * Input
968 * poly the polyhedron to draw
969 * gc X11 graphics context to be used for drawing
970 * currX, currY position of upper left of bounding-box
971 * polyW, polyH size of bounding-box
972 * prevX, prevY position of previous bounding-box
973 *****************************************************************************/
974
975 static void
drawPoly(ModeInfo * mi,Polyinfo * poly,GC gc,int currX,int currY,int polyW,int polyH,int prevX,int prevY)976 drawPoly(ModeInfo * mi, Polyinfo * poly, GC gc,
977 int currX, int currY, int polyW, int polyH, int prevX, int prevY)
978 {
979 Display *display = MI_DISPLAY(mi);
980 Window window = MI_WINDOW(mi);
981 icostruct *ip = &icos[MI_SCREEN(mi)];
982 int *f = poly->f;
983 int NV = poly->numverts;
984 int NF = poly->numfaces;
985
986 register int p0;
987 register int p1;
988 register XPoint *pv2;
989 XSegment *pe;
990 XPoint *pp;
991 register Point3D *pxv;
992 XPoint v2[MAXNV];
993 XPoint pts[MAXNV];
994 XSegment edge_segs[MAXEDGES];
995 register int i;
996 int j, k;
997 register int *pf;
998 int facecolor;
999
1000 int pcount = 0;
1001 double pxvz;
1002 XPoint ppts[MAXEDGESPERPOLY];
1003 Window lwindow;
1004 GC lgc;
1005
1006 /* Switch double-buffer and rotate vertices */
1007
1008 ip->xv_buffer = !ip->xv_buffer;
1009 PartialNonHomTransform(NV, ip->xform,
1010 ip->xv[!ip->xv_buffer], ip->xv[ip->xv_buffer]);
1011
1012
1013 /* Convert 3D coordinates to 2D window coordinates: */
1014
1015 pxv = ip->xv[ip->xv_buffer];
1016 pv2 = v2;
1017 for (i = NV - 1; i >= 0; --i) {
1018 pv2->x = (int) ((pxv->x + 1.0) * ip->wo2) + currX;
1019 pv2->y = (int) ((pxv->y + 1.0) * ip->ho2) + currY;
1020 ++pxv;
1021 ++pv2;
1022 }
1023
1024
1025 /* Accumulate edges to be drawn, eliminating duplicates for speed: */
1026
1027 pxv = ip->xv[ip->xv_buffer];
1028 pv2 = v2;
1029 pf = f;
1030 pe = edge_segs;
1031 pp = pts;
1032 (void) memset(ip->drawnEdges, 0, sizeof (ip->drawnEdges));
1033 (void) memset(ip->drawnPoints, 0, sizeof (ip->drawnPoints));
1034
1035 if (ip->dbuf) {
1036 XSetForeground(display, ip->dbuf_gc, MI_BLACK_PIXEL(mi));
1037 XFillRectangle(display, (Drawable) ip->dbuf, ip->dbuf_gc, 0, 0,
1038 polyW + ip->deltaWidth + ip->linewidth,
1039 polyH + ip->deltaHeight + ip->linewidth);
1040 lwindow = (Drawable) ip->dbuf;
1041 lgc = ip->dbuf_gc;
1042 } else {
1043 lwindow = window;
1044 lgc = gc;
1045 icoClearArea(mi, prevX, prevY, polyW + 1, polyH + 1);
1046 }
1047 for (i = NF - 1; i >= 0; --i, pf += pcount) {
1048
1049 pcount = *pf++; /* number of edges for this face */
1050 pxvz = 0.0;
1051 for (j = 0; j < pcount; j++) {
1052 p0 = pf[j];
1053 pxvz += pxv[p0].z;
1054 }
1055
1056 /* If facet faces away from viewer, don't consider it: */
1057 if (pxvz < 0.0 && (ip->faces || ip->opaque))
1058 continue;
1059
1060 if (ip->faces) {
1061 for (j = 0; j < pcount; j++) {
1062 p0 = pf[j];
1063 ppts[j].x = pv2[p0].x;
1064 ppts[j].y = pv2[p0].y;
1065 if (ip->dbuf) {
1066 ppts[j].x -= (currX - ip->deltaWidth / 2 - ip->linewidth / 2);
1067 ppts[j].y -= (currY - ip->deltaHeight / 2 - ip->linewidth / 2);
1068 }
1069 }
1070 if (MI_NPIXELS(mi) > 2) {
1071 facecolor = (i * MI_NPIXELS(mi) / NF + ip->color_offset) % MI_NPIXELS(mi);
1072 XSetForeground(display, lgc, MI_PIXEL(mi, facecolor));
1073 } else {
1074 XGCValues gcv;
1075 facecolor = (i * (NUMSTIPPLES - 1) / NF + ip->color_offset) % (NUMSTIPPLES - 1);
1076 gcv.stipple = ip->pixmaps[facecolor];
1077 gcv.foreground = MI_WHITE_PIXEL(mi);
1078 gcv.background = MI_BLACK_PIXEL(mi);
1079 XChangeGC(MI_DISPLAY(mi), ip->stippledGC,
1080 GCStipple | GCForeground | GCBackground, &gcv);
1081 lgc = ip->stippledGC;
1082 /* XSetForeground(display, lgc, MI_WHITE_PIXEL(mi)); */
1083 }
1084 XFillPolygon(display, lwindow, lgc,
1085 ppts, pcount, Convex, CoordModeOrigin);
1086 }
1087 if (ip->edges) {
1088 for (j = 0; j < pcount; j++) {
1089 if (j < pcount - 1)
1090 k = j + 1;
1091 else
1092 k = 0;
1093 p0 = pf[j];
1094 p1 = pf[k];
1095 if (!ip->drawnEdges[p0][p1]) {
1096 ip->drawnEdges[p0][p1] = 1;
1097 ip->drawnEdges[p1][p0] = 1;
1098 pe->x1 = pv2[p0].x;
1099 pe->y1 = pv2[p0].y;
1100 pe->x2 = pv2[p1].x;
1101 pe->y2 = pv2[p1].y;
1102 if (ip->dbuf) {
1103 pe->x1 -= (currX - ip->deltaWidth / 2 - ip->linewidth / 2);
1104 pe->y1 -= (currY - ip->deltaHeight / 2 - ip->linewidth / 2);
1105 pe->x2 -= (currX - ip->deltaWidth / 2 - ip->linewidth / 2);
1106 pe->y2 -= (currY - ip->deltaHeight / 2 - ip->linewidth / 2);
1107 }
1108 ++pe;
1109 }
1110 }
1111 } else {
1112 for (j = 0; j < pcount; j++) {
1113 p0 = pf[j];
1114 if (!ip->drawnPoints[p0]) {
1115 ip->drawnPoints[p0] = 1;
1116 pp->x = pv2[p0].x;
1117 pp->y = pv2[p0].y;
1118 if (ip->dbuf) {
1119 pp->x -= (currX - ip->deltaWidth / 2 - ip->linewidth / 2);
1120 pp->y -= (currY - ip->deltaHeight / 2 - ip->linewidth / 2);
1121 }
1122 ++pp;
1123 }
1124 }
1125 }
1126 }
1127 /* Erase previous, draw current icosahedrons; sync for smoothness. */
1128
1129 if (ip->edges) {
1130 if (MI_NPIXELS(mi) <= 2)
1131 if (ip->faces) {
1132 XSetForeground(display, lgc, ip->color);
1133 } else {
1134 XSetForeground(display, lgc, MI_WHITE_PIXEL(mi));
1135 }
1136 else {
1137 ip->color = (ip->color + 1) % MI_NPIXELS(mi);
1138 XSetForeground(display, lgc, MI_PIXEL(mi, ip->color));
1139 }
1140 XSetLineAttributes(display, lgc, ip->linewidth,
1141 LineSolid, CapRound, JoinRound);
1142 XDrawSegments(display, lwindow, lgc, edge_segs, pe - edge_segs);
1143 XSetLineAttributes(display, lgc, 1,
1144 LineSolid, CapNotLast, JoinRound);
1145 } else if (!ip->faces) {
1146 if (MI_NPIXELS(mi) <= 2)
1147 XSetForeground(display, lgc, MI_WHITE_PIXEL(mi));
1148 else {
1149 ip->color = (ip->color + 1) % MI_NPIXELS(mi);
1150 XSetForeground(display, lgc, MI_PIXEL(mi, ip->color));
1151 }
1152 #if 0
1153 /* just does not look that good */
1154 if (ip->linewidth <= 1)
1155 XDrawPoints(display, lwindow, lgc, pts, pp - pts, CoordModeOrigin);
1156 else
1157 #endif
1158 {
1159 for (j = 0; j < pp-pts; j++)
1160 XFillArc(display, lwindow, lgc,
1161 pts[j].x - ip->linewidth / 2, pts[j].y - ip->linewidth / 2, ip->linewidth, ip->linewidth, 0, 23040);
1162
1163 }
1164 }
1165 if (ip->dbuf) {
1166 XCopyArea(display, (Drawable) ip->dbuf, window, gc, 0, 0,
1167 polyW + 1 + ip->deltaWidth + ip->linewidth,
1168 polyH + 1 + ip->deltaHeight + ip->linewidth,
1169 currX - ip->deltaWidth / 2 - ip->linewidth / 2,
1170 currY - ip->deltaHeight / 2 - ip->linewidth / 2);
1171 }
1172 XFlush(display);
1173 }
1174
1175 static void
free_ico_screen(Display * display,icostruct * ip)1176 free_ico_screen(Display *display, icostruct *ip)
1177 {
1178 int shade;
1179
1180 if (ip == NULL) {
1181 return;
1182 }
1183 if (ip->stippledGC != None) {
1184 XFreeGC(display, ip->stippledGC);
1185 ip->stippledGC = None;
1186 }
1187 for (shade = 0; shade < ip->init_bits; shade++) {
1188 if (ip->pixmaps[shade] != None) {
1189 XFreePixmap(display, ip->pixmaps[shade]);
1190 ip->pixmaps[shade] = None;
1191 }
1192 }
1193 if (ip->dbuf != None) {
1194 XFreePixmap(display, ip->dbuf);
1195 ip->dbuf = None;
1196 }
1197 if (ip->dbuf_gc != None) {
1198 XFreeGC(display, ip->dbuf_gc);
1199 ip->dbuf_gc = None;
1200 }
1201 ip = NULL;
1202 }
1203
1204 ENTRYPOINT void
init_ico(ModeInfo * mi)1205 init_ico(ModeInfo * mi)
1206 {
1207 Display * display = MI_DISPLAY(mi);
1208 Window window = MI_WINDOW(mi);
1209 int size = MI_SIZE(mi);
1210 icostruct *ip;
1211
1212 MI_INIT(mi, icos);
1213 ip = &icos[MI_SCREEN(mi)];
1214
1215 ip->width = MI_WIDTH(mi);
1216 ip->height = MI_HEIGHT(mi);
1217 ip->linewidth = NRAND((ip->width + ip->height) / 200 + 1) + 2;
1218
1219 if (MI_NPIXELS(mi) <= 2) {
1220 if (ip->stippledGC == None) {
1221 XGCValues gcv;
1222
1223 gcv.fill_style = FillOpaqueStippled;
1224 if ((ip->stippledGC = XCreateGC(display, window, GCFillStyle,
1225 &gcv)) == None) {
1226 free_ico_screen(display, ip);
1227 return;
1228 }
1229 }
1230 if (ip->init_bits == 0) {
1231 int i;
1232
1233 for (i = 1; i < NUMSTIPPLES; i++) {
1234 POLYBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
1235 }
1236 }
1237 }
1238
1239 if (MI_IS_FULLRANDOM(mi)) {
1240 ip->faces = (Bool) (LRAND() & 1);
1241 ip->edges = (Bool) (LRAND() & 1);
1242 ip->opaque = (!(NRAND(4) == 0));
1243 } else {
1244 ip->edges = edges;
1245 ip->faces = faces;
1246 ip->opaque = opaque;
1247 }
1248
1249 if (size < -MINSIZE)
1250 ip->polyW = NRAND(MIN(-size, MAX(MINSIZE,
1251 MIN(ip->width, ip->height) / 4)) - MINSIZE + 1) + MINSIZE;
1252 else if (size < MINSIZE) {
1253 if (!size)
1254 ip->polyW = MAX(MINSIZE, MIN(ip->width, ip->height) / 4);
1255 else
1256 ip->polyW = MINSIZE;
1257 } else
1258 ip->polyW = MIN(size, MAX(MINSIZE,
1259 MIN(ip->width, ip->height) / 4));
1260
1261 ip->polyH = ip->polyW;
1262 ip->polyDeltaX = ip->polyW / DEFAULT_DELTAY + 1;
1263 ip->polyDeltaY = ip->polyH / DEFAULT_DELTAX + 1;
1264 ip->currX = NRAND(ip->width - ip->polyW);
1265 ip->currY = NRAND(ip->height - ip->polyH);
1266
1267 /* Bounce the box in the window */
1268
1269 ip->deltaWidth = ip->polyDeltaX * 2;
1270 ip->deltaHeight = ip->polyDeltaY * 2;
1271 ip->polyDeltaX *= ((LRAND() & 1) ? 1 : -1);
1272 ip->polyDeltaY *= ((LRAND() & 1) ? 1 : -1);
1273
1274 ip->loopcount = 0;
1275
1276 ip->object = MI_COUNT(mi) - 1;
1277 if (ip->object < 0 || ip->object >= polysize) {
1278 /* avoid pyramid and star (drawing errors) count = 7 & 8
1279 also avoid plane (boring) count = 6
1280 but allow direct access */
1281 ip->object = NRAND(POLYSIZE);
1282 }
1283 ip->poly = polygons + ip->object;
1284 if (MI_NPIXELS(mi) > 2)
1285 ip->color = NRAND(MI_NPIXELS(mi));
1286 else if (ip->faces && ip->edges)
1287 ip->color = (LRAND() & 1) ? MI_WHITE_PIXEL(mi) : MI_BLACK_PIXEL(mi);
1288
1289 ip->color_offset = NRAND(MI_NPIXELS(mi));
1290 #ifndef NO_DBUF
1291 if (ip->dbuf != None)
1292 XFreePixmap(display, ip->dbuf);
1293 ip->dbuf = XCreatePixmap(display, window,
1294 ip->polyW + ip->deltaWidth + ip->linewidth,
1295 ip->polyH + ip->deltaHeight + ip->linewidth,
1296 MI_DEPTH(mi));
1297 /* Allocation checked */
1298 if (ip->dbuf != None) {
1299 XGCValues gcv;
1300
1301 gcv.foreground = 0;
1302 gcv.background = 0;
1303 gcv.graphics_exposures = False;
1304 gcv.function = GXcopy;
1305
1306 if (ip->dbuf_gc != None)
1307 XFreeGC(display, ip->dbuf_gc);
1308 if ((ip->dbuf_gc = XCreateGC(display, (Drawable) ip->dbuf,
1309 GCForeground | GCBackground | GCGraphicsExposures | GCFunction,
1310 &gcv)) == None) {
1311 XFreePixmap(display, ip->dbuf);
1312 ip->dbuf = None;
1313 } else {
1314 XFillRectangle(display, (Drawable) ip->dbuf, ip->dbuf_gc,
1315 0, 0, ip->polyW + ip->deltaWidth + ip->linewidth,
1316 ip->polyH + ip->deltaHeight + ip->linewidth);
1317 /*XSetBackground(display, MI_GC(mi), MI_BLACK_PIXEL(mi));
1318 XSetFunction(display, MI_GC(mi), GXcopy);*/
1319 }
1320 }
1321 #endif
1322
1323 MI_CLEARWINDOW(mi);
1324
1325 /* don't want any exposure events from XCopyPlane */
1326 XSetGraphicsExposures(display, MI_GC(mi), False);
1327
1328
1329 initPoly(mi, ip->poly, ip->polyW, ip->polyH, True);
1330 }
1331
1332 ENTRYPOINT void
draw_ico(ModeInfo * mi)1333 draw_ico(ModeInfo * mi)
1334 {
1335 icostruct *ip;
1336
1337 if (icos == NULL)
1338 return;
1339 ip = &icos[MI_SCREEN(mi)];
1340 if ((MI_NPIXELS(mi) <= 2) && (ip->stippledGC == None))
1341 return;
1342
1343 MI_IS_DRAWN(mi) = True;
1344 if (++ip->loopcount > MI_CYCLES(mi))
1345 init_ico(mi);
1346
1347 ip->prevX = ip->currX;
1348 ip->prevY = ip->currY;
1349
1350 ip->currX += ip->polyDeltaX;
1351 if (ip->currX < 0 || ip->currX + ip->polyW > ip->width) {
1352
1353 ip->currX -= 2 * ip->polyDeltaX;
1354 ip->polyDeltaX = -ip->polyDeltaX;
1355 /* spin should change after hitting wall */
1356 initPoly(mi, ip->poly, ip->polyW, ip->polyH, False);
1357 }
1358 ip->currY += ip->polyDeltaY;
1359 if (ip->currY < 0 || ip->currY + ip->polyH > ip->height) {
1360 ip->currY -= 2 * ip->polyDeltaY;
1361 ip->polyDeltaY = -ip->polyDeltaY;
1362 /* spin should change after hitting wall */
1363 initPoly(mi, ip->poly, ip->polyW, ip->polyH, False);
1364 }
1365 drawPoly(mi, ip->poly, MI_GC(mi),
1366 ip->currX, ip->currY, ip->polyW, ip->polyH, ip->prevX, ip->prevY);
1367 }
1368 ENTRYPOINT void
release_ico(ModeInfo * mi)1369 release_ico(ModeInfo * mi)
1370 {
1371 if (icos != NULL) {
1372 int screen;
1373
1374 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1375 free_ico_screen(MI_DISPLAY(mi), &icos[screen]);
1376 free(icos);
1377 icos = (icostruct *) NULL;
1378 }
1379 }
1380
1381 #ifndef STANDALONE
1382 ENTRYPOINT void
refresh_ico(ModeInfo * mi)1383 refresh_ico(ModeInfo * mi)
1384 {
1385 MI_CLEARWINDOW(mi);
1386 }
1387
1388 ENTRYPOINT void
change_ico(ModeInfo * mi)1389 change_ico(ModeInfo * mi)
1390 {
1391 icostruct *ip;
1392
1393 if (icos == NULL)
1394 return;
1395 ip = &icos[MI_SCREEN(mi)];
1396 if (MI_NPIXELS(mi) <= 2 && ip->stippledGC == None)
1397 return;
1398
1399 if (MI_COUNT(mi) <= 0 || MI_COUNT(mi) > POLYSIZE) {
1400 ip->object = (ip->object + 1) % (POLYSIZE);
1401 ip->poly = polygons + ip->object;
1402 }
1403 ip->loopcount = 0;
1404
1405 MI_CLEARWINDOWCOLORMAPFAST(mi, MI_GC(mi), MI_BLACK_PIXEL(mi));
1406
1407 initPoly(mi, ip->poly, ip->polyW, ip->polyH, True);
1408 }
1409 #endif
1410
1411 XSCREENSAVER_MODULE ("Ico", ico)
1412
1413 #endif /* MODE_ico */
1414