1 /* -*- Mode: C; tab-width: 4 -*-
2 * ifs --- Modified iterated functions system.
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)ifs.c 4.02 97/04/01 xlockmore";
8 /* Copyright (c) 1997 by Massimino Pascal (Pascal.Massimon@ens.fr)
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.
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.
24 * 10-May-97: jwz@jwz.org: turned into a standalone program.
25 * Made it render into an offscreen bitmap and then copy
26 * that onto the screen, to reduce flicker.
30 # define PROGCLASS "IFS"
31 # define HACK_INIT init_ifs
32 # define HACK_DRAW draw_ifs
33 # define ifs_opts xlockmore_opts
34 # define DEFAULTS "*delay: 20000 \n" \
36 # define SMOOTH_COLORS
37 # include "xlockmore.h" /* from the xscreensaver distribution */
38 #else /* !STANDALONE */
39 # include "xlock.h" /* from the xlockmore distribution */
40 #endif /* !STANDALONE */
42 ModeSpecOpt ifs_opts = {
43 0, NULL, 0, NULL, NULL };
45 /*****************************************************/
46 /*****************************************************/
49 typedef short int F_PT;
51 /* typedef float F_PT; */
53 /*****************************************************/
56 #define UNIT ( 1<<FIX )
59 /* settings for a PC 120Mhz... */
60 #define MAX_DEPTH_2 10
65 #define DBL_To_F_PT(x) (F_PT)( (DBL)(UNIT)*(x) )
67 /*****************************************************/
69 static int Max_Colors;
70 static ModeInfo *The_MI;
73 static Display *display;
77 /*****************************************************/
79 typedef struct Similitude_Struct SIMI;
80 typedef struct Fractal_Struct FRACTAL;
82 struct Similitude_Struct {
86 F_PT Ct, St, Ct2, St2;
91 struct Fractal_Struct {
94 SIMI Components[5 * MAX_SIMI];
97 int Width, Height, Lx, Ly;
98 DBL r_mean, dr_mean, dr2_mean;
100 XPoint *Buffer1, *Buffer2;
101 Pixmap dbuf; /* jwz */
105 static FRACTAL *Root = NULL, *Cur_F;
110 /*****************************************************/
111 /*****************************************************/
114 Gauss_Rand(DBL c, DBL A, DBL S)
118 y = (DBL) LRAND() / MAXRAND;
119 y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
126 Half_Gauss_Rand(DBL c, DBL A, DBL S)
130 y = (DBL) LRAND() / MAXRAND;
131 y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
136 Random_Simis(FRACTAL * F, SIMI * Cur, int i)
139 Cur->c_x = Gauss_Rand(0.0, .8, 4.0);
140 Cur->c_y = Gauss_Rand(0.0, .8, 4.0);
141 Cur->r = Gauss_Rand(F->r_mean, F->dr_mean, 3.0);
142 Cur->r2 = Half_Gauss_Rand(0.0, F->dr2_mean, 2.0);
143 Cur->A = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0);
144 Cur->A2 = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0);
149 /***************************************************************/
152 init_ifs(ModeInfo * mi)
158 Root = (FRACTAL *) calloc(
159 MI_NUM_SCREENS(mi), sizeof (FRACTAL));
163 Fractal = &Root[MI_SCREEN(mi)];
165 if (Fractal->Max_Pt) {
166 free(Fractal->Buffer1);
167 free(Fractal->Buffer2);
169 i = (NRAND(4)) + 2; /* Number of centers */
172 Fractal->Depth = MAX_DEPTH_3;
173 Fractal->r_mean = .6;
174 Fractal->dr_mean = .4;
175 Fractal->dr2_mean = .3;
179 Fractal->Depth = MAX_DEPTH_4;
180 Fractal->r_mean = .5;
181 Fractal->dr_mean = .4;
182 Fractal->dr2_mean = .3;
186 Fractal->Depth = MAX_DEPTH_5;
187 Fractal->r_mean = .5;
188 Fractal->dr_mean = .4;
189 Fractal->dr2_mean = .3;
194 Fractal->Depth = MAX_DEPTH_2;
195 Fractal->r_mean = .7;
196 Fractal->dr_mean = .3;
197 Fractal->dr2_mean = .4;
200 /* (void) fprintf( stderr, "N=%d\n", i ); */
201 Fractal->Nb_Simi = i;
202 Fractal->Max_Pt = Fractal->Nb_Simi - 1;
203 for (i = 0; i <= Fractal->Depth + 2; ++i)
204 Fractal->Max_Pt *= Fractal->Nb_Simi;
206 Fractal->Buffer1 = (XPoint *) calloc(Fractal->Max_Pt, sizeof (XPoint));
207 if (Fractal->Buffer1 == NULL)
209 Fractal->Buffer2 = (XPoint *) calloc(Fractal->Max_Pt, sizeof (XPoint));
210 if (Fractal->Buffer2 == NULL)
214 Fractal->Width = MI_WIN_WIDTH(mi);
215 Fractal->Height = MI_WIN_HEIGHT(mi);
218 Fractal->Lx = (Fractal->Width - 1) / 2;
219 Fractal->Ly = (Fractal->Height - 1) / 2;
220 Fractal->Col = NRAND(MI_NPIXELS(mi) - 1) + 1;
222 Random_Simis(Fractal, Fractal->Components, 5 * MAX_SIMI);
224 Fractal->dbuf = XCreatePixmap(MI_DISPLAY(mi), MI_WINDOW(mi),
225 Fractal->Width, Fractal->Height, 1);
231 gcv.function = GXcopy;
232 Fractal->dbuf_gc = XCreateGC(MI_DISPLAY(mi), Fractal->dbuf,
233 GCForeground|GCBackground|GCFunction,
235 XFillRectangle(MI_DISPLAY(mi), Fractal->dbuf,
236 Fractal->dbuf_gc, 0,0, Fractal->Width, Fractal->Height);
238 XSetBackground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi));
239 XSetFunction(MI_DISPLAY(mi), MI_GC(mi), GXcopy);
242 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
246 if (Fractal->Buffer1 != NULL)
247 free(Fractal->Buffer1);
248 if (Fractal->Buffer2 != NULL)
249 free(Fractal->Buffer2);
250 Fractal->Buffer1 = NULL;
251 Fractal->Buffer2 = NULL;
257 /***************************************************************/
261 # define inline /* */
265 Transform(SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
270 xo = (xo * Simi->R) / UNIT;
272 yo = (yo * Simi->R) / UNIT;
275 xx = (xx * Simi->R2) / UNIT;
277 yy = (yy * Simi->R2) / UNIT;
279 *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx;
280 *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy;
283 /***************************************************************/
286 Trace(F_PT xo, F_PT yo)
291 Cur = Cur_F->Components;
292 for (i = Cur_F->Nb_Simi; i; --i, Cur++) {
293 Transform(Cur, xo, yo, &x, &y);
294 Buf->x = Lx + (x * Lx / (UNIT * 2));
295 Buf->y = Ly - (y * Ly / (UNIT * 2));
299 if (D && ((x - xo) >> 4) && ((y - yo) >> 4)) {
308 Draw_Fractal(FRACTAL * F)
314 for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
315 Cur->Cx = DBL_To_F_PT(Cur->c_x);
316 Cur->Cy = DBL_To_F_PT(Cur->c_y);
318 Cur->Ct = DBL_To_F_PT(cos(Cur->A));
319 Cur->St = DBL_To_F_PT(sin(Cur->A));
320 Cur->Ct2 = DBL_To_F_PT(cos(Cur->A2));
321 Cur->St2 = DBL_To_F_PT(sin(Cur->A2));
323 Cur->R = DBL_To_F_PT(Cur->r);
324 Cur->R2 = DBL_To_F_PT(Cur->r2);
334 for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
337 for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
340 Transform(Simi, xo, yo, &x, &y);
348 XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(The_MI));
349 if (F->dbuf) /* jwz */
351 XSetForeground(display, F->dbuf_gc, 0);
352 /* XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer1, F->Cur_Pt,
354 XFillRectangle(display, F->dbuf, F->dbuf_gc, 0, 0,
355 F->Width, F->Height);
358 XDrawPoints(display, window, gc, F->Buffer1, F->Cur_Pt,
362 XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(The_MI));
364 XSetForeground(display, gc, MI_PIXEL(The_MI, F->Col % Max_Colors));
368 XSetForeground(display, F->dbuf_gc, 1);
369 XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer2, Cur_Pt,
373 XDrawPoints(display, window, gc, F->Buffer2, Cur_Pt, CoordModeOrigin);
377 XCopyPlane(display, F->dbuf, window, gc, 0,0,F->Width,F->Height,0,0, 1);
381 F->Buffer1 = F->Buffer2;
387 draw_ifs(ModeInfo * mi)
391 DBL u, uu, v, vv, u0, u1, u2, u3;
392 SIMI *S, *S1, *S2, *S3, *S4;
395 display = MI_DISPLAY(mi);
396 window = MI_WINDOW(mi);
398 Max_Colors = MI_NPIXELS(mi);
400 F = &Root[MI_SCREEN(mi)];
402 u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0;
413 S2 = S1 + F->Nb_Simi;
414 S3 = S2 + F->Nb_Simi;
415 S4 = S3 + F->Nb_Simi;
417 for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
418 S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
419 S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
420 S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
421 S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
422 S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
423 S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
428 if (F->Count >= 1000 / F->Speed) {
431 S2 = S1 + F->Nb_Simi;
432 S3 = S2 + F->Nb_Simi;
433 S4 = S3 + F->Nb_Simi;
435 for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
436 S2->c_x = 2.0 * S4->c_x - S3->c_x;
437 S2->c_y = 2.0 * S4->c_y - S3->c_y;
438 S2->r = 2.0 * S4->r - S3->r;
439 S2->r2 = 2.0 * S4->r2 - S3->r2;
440 S2->A = 2.0 * S4->A - S3->A;
441 S2->A2 = 2.0 * S4->A2 - S3->A2;
445 Random_Simis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
447 Random_Simis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
457 /***************************************************************/
460 release_ifs(ModeInfo * mi)
467 for (i = 0; i < MI_NUM_SCREENS(mi); ++i) {
468 if (Root[i].Buffer1 != NULL)
469 free(Root[i].Buffer1);
470 if (Root[i].Buffer2 != NULL)
471 free(Root[i].Buffer2);
473 XFreePixmap(MI_DISPLAY(mi), Root[i].dbuf);
475 XFreeGC(MI_DISPLAY(mi), Root[i].dbuf_gc);