X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fstrange.c;h=632d347a49c14af1d93fad503796a160272c9c76;hb=4ade52359b6eba3621566dac79793a33aa4c915f;hp=a1bda34f70ad7ef277fc405f86b84e81d74164c4;hpb=ce3185de9d9705e259f2b60dd4b5509007fa17d4;p=xscreensaver diff --git a/hacks/strange.c b/hacks/strange.c index a1bda34f..632d347a 100644 --- a/hacks/strange.c +++ b/hacks/strange.c @@ -1,47 +1,91 @@ -/* -*- Mode: C; tab-width: 4 -*- - * strange --- Strange attractors are not so hard to find... - */ -#if !defined( lint ) && !defined( SABER ) -static const char sccsid[] = "@(#)strange.c 4.02 97/04/01 xlockmore"; +/* -*- Mode: C; tab-width: 4 -*- */ +/* strange --- strange attractors */ + +#if 0 +static const char sccsid[] = "@(#)strange.c 5.00 2000/11/01 xlockmore"; #endif -/* Copyright (c) 1997 by Massimino Pascal (Pascal.Massimon@ens.fr) - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation. - * - * This file is provided AS IS with no warranties of any kind. The author - * shall have no liability with respect to the infringement of copyrights, - * trade secrets or any patents by this file or any part thereof. In no - * event will the author be liable for any lost revenue or profits or - * other special, indirect and consequential damages. - * - * Revision History: - * 30-Jul-98: sineswiper@resonatorsoft.com: added curve factor (discovered - * while experimenting with the Gauss_Rand function). - * 10-May-97: jwz@jwz.org: turned into a standalone program. - * Made it render into an offscreen bitmap and then copy - * that onto the screen, to reduce flicker. - */ +/*- +* Copyright (c) 1997 by Massimino Pascal +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose and without fee is hereby granted, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation. +* +* This file is provided AS IS with no warranties of any kind. The author +* shall have no liability with respect to the infringement of copyrights, +* trade secrets or any patents by this file or any part thereof. In no +* event will the author be liable for any lost revenue or profits or +* other special, indirect and consequential damages. +* +* Revision History: +* 01-Nov-2000: Allocation checks +* 10-May-1997: jwz@jwz.org: turned into a standalone program. +* Made it render into an offscreen bitmap and then copy +* that onto the screen, to reduce flicker. +* +* strange attractors are not so hard to find... +*/ + +/* TODO: Bring over tweaks from 3.x version. +* For a good idea of what's missing, diff strange.c.20081107-good2 against strange.c-3.29 +* We forked from the 3.29 series at 20081107, so anything added since then may be missing. +*/ #ifdef STANDALONE -# define PROGCLASS "Strange" -# define HACK_INIT init_strange -# define HACK_DRAW draw_strange -# define strange_opts xlockmore_opts -# define DEFAULTS "*delay: 2000 \n" \ - "*ncolors: 100 \n" +# define MODE_strange +# define DEFAULTS "*delay: 10000 \n" \ + "*ncolors: 100 \n" \ + "*fpsSolid: True \n" \ + "*ignoreRotation: True \n" \ + # define SMOOTH_COLORS -# include "xlockmore.h" /* from the xscreensaver distribution */ -#else /* !STANDALONE */ -# include "xlock.h" /* from the xlockmore distribution */ +# define refresh_strange 0 +# define strange_handle_event 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ #endif /* !STANDALONE */ -/*****************************************************/ -/*****************************************************/ +#ifdef MODE_strange +#define DEF_CURVE "10" +#define DEF_POINTS "5500" + +/*static int curve;*/ +static int points; + +static XrmOptionDescRec opts[] = +{ +/* {"-curve", ".strange.curve", XrmoptionSepArg, 0}, */ + {"-points", ".strange.points", XrmoptionSepArg, 0}, +}; +static argtype vars[] = +{ +/* {&curve, "curve", "Curve", DEF_CURVE, t_Int},*/ + {&points, "points", "Points", DEF_POINTS, t_Int}, +}; +static OptionStruct desc[] = +{ +/* {"-curve", "set the curve factor of the attractors"},*/ + {"-points", "change the number of points/iterations each frame"}, +}; +ENTRYPOINT ModeSpecOpt strange_opts = +{sizeof opts / sizeof opts[0], opts, +sizeof vars / sizeof vars[0], vars, desc}; + +#ifdef USE_MODULES +ModStruct strange_description = +{"strange", "init_strange", "draw_strange", "release_strange", +"init_strange", "init_strange", (char *) NULL, &strange_opts, +1000, 1, 1, 1, 64, 1.0, "", +"Shows strange attractors", 0, NULL}; +#endif + +#ifdef HAVE_COCOA +# define NO_DBUF +#endif typedef float DBL; typedef int PRM; @@ -51,56 +95,63 @@ typedef int PRM; /* #define UNIT2 (3140*UNIT/1000) */ #define SKIP_FIRST 100 -#define MAX_POINTS 5500 #define DBL_To_PRM(x) (PRM)( (DBL)(UNIT)*(x) ) -#define DO_FOLD(a) (a)<0 ? -Fold[ (-(a))&(UNIT2-1) ] : Fold[ (a)&(UNIT2-1) ] +#define DO_FOLD(a) (a)<0 ? -A->Fold[ (-(a))&(UNIT2-1) ] : A->Fold[ (a)&(UNIT2-1) ] -/* - #define DO_FOLD(a) (a)<-UNIT2 ? -Fold[(-(a))%UNIT2] : (a)<0 ? -Fold[ -(a) ] +#if 0 +#define DO_FOLD(a) (a)<-UNIT2 ? -A->Fold[(-(a))%UNIT2] : (a)<0 ? -A->Fold[ -(a) ] :\ +(a)>UNIT2 ? A->Fold[ (a)%UNIT2 ] : A->Fold[ (a) ] +#define DO_FOLD(a) DBL_To_PRM( sin( (DBL)(a)/UNIT ) ) +#define DO_FOLD(a) (a)<0 ? DBL_To_PRM( exp( 16.0*(a)/UNIT2 ) )-1.0 : \ +DBL_To_PRM( 1.0-exp( -16.0*(a)/UNIT2 ) ) +#endif - : \ (a)>UNIT2 ? Fold[ (a)%UNIT2 ] : Fold[ (a) ] */ -/* #define DO_FOLD(a) DBL_To_PRM( sin( (DBL)(a)/UNIT ) ) */ -/* - #define DO_FOLD(a) (a)<0 ? DBL_To_PRM( exp( 16.0*(a)/UNIT2 ) )-1.0 : \ - DBL_To_PRM( 1.0-exp( -16.0*(a)/UNIT2 ) ) */ +/* useAccumulator performs two functions: +* If it is defined, then support for the accumulator will be compiled. +* It is also the condition for which the accumulator renderer will engage. +*/ +#define useAccumulator (Root->Max_Pt > 6000) +#define ACC_GAMMA 10.0 +#define NUM_COLS 150 +/* Extra options: */ +#define VARY_SPEED_TO_AVOID_BOREDOM +#define POINTS_HISTORY +#define MERGE_FRAMES 3 /******************************************************************/ #define MAX_PRM 3*5 -typedef struct { +typedef struct _ATTRACTOR { DBL Prm1[MAX_PRM], Prm2[MAX_PRM]; - void (*Iterate) (PRM, PRM, PRM *, PRM *); + PRM Prm[MAX_PRM], *Fold; + void (*Iterate) (struct _ATTRACTOR *, PRM, PRM, PRM *, PRM *); XPoint *Buffer1, *Buffer2; int Cur_Pt, Max_Pt; int Col, Count, Speed; int Width, Height; - Pixmap dbuf; /* jwz */ - GC dbuf_gc; + Pixmap dbuf; /* jwz */ + GC dbuf_gc; + #ifdef useAccumulator + int **accMap; + #endif } ATTRACTOR; -static ATTRACTOR *Root; -static PRM xmin, xmax, ymin, ymax; -static PRM Prm[MAX_PRM]; -static PRM *Fold = NULL; - -static int curve; - -static XrmOptionDescRec opts[] = -{ - {"-curve", ".strange.curve", XrmoptionSepArg, (caddr_t) "10"}, -}; -static OptionStruct desc[] = -{ - {"-curve", "set the curve factor of the attractors"}, -}; +static ATTRACTOR *Root = (ATTRACTOR *) NULL; -ModeSpecOpt strange_opts = { 1, opts, 0, NULL, desc }; +#ifdef useAccumulator +static XColor* cols; +#endif -/******************************************************************/ -/******************************************************************/ +#ifdef POINTS_HISTORY +static int numOldPoints; +static int* oldPointsX; +static int* oldPointsY; +static int oldPointsIndex; +static int startedClearing; +#endif static DBL Amp_Prm[MAX_PRM] = { @@ -118,11 +169,10 @@ static DBL Mid_Prm[MAX_PRM] = static DBL Gauss_Rand(DBL c, DBL A, DBL S) { - DBL y,z; + DBL y; y = (DBL) LRAND() / MAXRAND; - z = curve / 10; - y = A * (z - exp(-y * y * S)) / (z - exp(-S)); + y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S)); if (NRAND(2)) return (c + y); else @@ -140,10 +190,10 @@ Random_Prm(DBL * Prm) /***************************************************************/ - /* 2 examples of non-linear map */ + /* 2 examples of non-linear map */ static void -Iterate_X2(PRM x, PRM y, PRM * xo, PRM * yo) +Iterate_X2(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo) { PRM xx, yy, xy, x2y, y2x, Tmp; @@ -153,16 +203,16 @@ Iterate_X2(PRM x, PRM y, PRM * xo, PRM * yo) y2x = (yy * x) / UNIT; xy = (x * y) / UNIT; - Tmp = Prm[1] * xx + Prm[2] * xy + Prm[3] * yy + Prm[4] * x2y; - Tmp = Prm[0] - y + (Tmp / UNIT); + Tmp = A->Prm[1] * xx + A->Prm[2] * xy + A->Prm[3] * yy + A->Prm[4] * x2y; + Tmp = A->Prm[0] - y + (Tmp / UNIT); *xo = DO_FOLD(Tmp); - Tmp = Prm[6] * xx + Prm[7] * xy + Prm[8] * yy + Prm[9] * y2x; - Tmp = Prm[5] + x + (Tmp / UNIT); + Tmp = A->Prm[6] * xx + A->Prm[7] * xy + A->Prm[8] * yy + A->Prm[9] * y2x; + Tmp = A->Prm[5] + x + (Tmp / UNIT); *yo = DO_FOLD(Tmp); } static void -Iterate_X3(PRM x, PRM y, PRM * xo, PRM * yo) +Iterate_X3(ATTRACTOR * A, PRM x, PRM y, PRM * xo, PRM * yo) { PRM xx, yy, xy, x2y, y2x, Tmp_x, Tmp_y, Tmp_z; @@ -172,60 +222,99 @@ Iterate_X3(PRM x, PRM y, PRM * xo, PRM * yo) y2x = (yy * x) / UNIT; xy = (x * y) / UNIT; - Tmp_x = Prm[1] * xx + Prm[2] * xy + Prm[3] * yy + Prm[4] * x2y; - Tmp_x = Prm[0] - y + (Tmp_x / UNIT); + Tmp_x = A->Prm[1] * xx + A->Prm[2] * xy + A->Prm[3] * yy + A->Prm[4] * x2y; + Tmp_x = A->Prm[0] - y + (Tmp_x / UNIT); Tmp_x = DO_FOLD(Tmp_x); - Tmp_y = Prm[6] * xx + Prm[7] * xy + Prm[8] * yy + Prm[9] * y2x; - Tmp_y = Prm[5] + x + (Tmp_y / UNIT); + Tmp_y = A->Prm[6] * xx + A->Prm[7] * xy + A->Prm[8] * yy + A->Prm[9] * y2x; + Tmp_y = A->Prm[5] + x + (Tmp_y / UNIT); Tmp_y = DO_FOLD(Tmp_y); - Tmp_z = Prm[11] * xx + Prm[12] * xy + Prm[13] * yy + Prm[14] * y2x; - Tmp_z = Prm[10] + x + (Tmp_z / UNIT); + Tmp_z = A->Prm[11] * xx + A->Prm[12] * xy + A->Prm[13] * yy + A->Prm[14] * y2x; + Tmp_z = A->Prm[10] + x + (Tmp_z / UNIT); Tmp_z = UNIT + Tmp_z * Tmp_z / UNIT; *xo = (Tmp_x * UNIT) / Tmp_z; *yo = (Tmp_y * UNIT) / Tmp_z; } -static void (*Funcs[2]) (PRM, PRM, PRM *, PRM *) = { +static void (*Funcs[2]) (ATTRACTOR *, PRM, PRM, PRM *, PRM *) = { Iterate_X2, Iterate_X3 }; /***************************************************************/ -void +static void +free_strange(Display *display, ATTRACTOR *A) +{ + if (A->Buffer1 != NULL) { + (void) free((void *) A->Buffer1); + A->Buffer1 = (XPoint *) NULL; + } + if (A->Buffer2 != NULL) { + (void) free((void *) A->Buffer2); + A->Buffer2 = (XPoint *) NULL; + } + if (A->dbuf) { + XFreePixmap(display, A->dbuf); + A->dbuf = None; + } + if (A->dbuf_gc) { + XFreeGC(display, A->dbuf_gc); + A->dbuf_gc = None; + } + if (A->Fold != NULL) { + (void) free((void *) A->Fold); + A->Fold = (PRM *) NULL; + } +} + +ENTRYPOINT void draw_strange(ModeInfo * mi) { - int i, j, n, Max_Colors, Cur_Pt; + int i, j, n, Cur_Pt; PRM x, y, xo, yo; DBL u; - ATTRACTOR *A; XPoint *Buf; - Display *display; - GC gc; - Window window; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + GC gc = MI_GC(mi); DBL Lx, Ly; - void (*Iterate) (PRM, PRM, PRM *, PRM *); - - display = MI_DISPLAY(mi); - window = MI_WINDOW(mi); - gc = MI_GC(mi); - Max_Colors = MI_NPIXELS(mi); + void (*Iterate) (ATTRACTOR *, PRM, PRM, PRM *, PRM *); + PRM xmin, xmax, ymin, ymax; + ATTRACTOR *A; + if (Root == NULL) + return; A = &Root[MI_SCREEN(mi)]; + if (A->Fold == NULL) + return; Cur_Pt = A->Cur_Pt; Iterate = A->Iterate; - u = (DBL) (A->Count) / 1000.0; + u = (DBL) (A->Count) / 40000.0; for (j = MAX_PRM - 1; j >= 0; --j) - Prm[j] = DBL_To_PRM((1.0 - u) * A->Prm1[j] + u * A->Prm2[j]); + A->Prm[j] = DBL_To_PRM((1.0 - u) * A->Prm1[j] + u * A->Prm2[j]); + + /* We collect the accumulation of the orbits in the 2d int array field. */ +#ifndef POINTS_HISTORY + #ifdef useAccumulator + if (useAccumulator) { + for (i=0;iWidth;i++) { + for (j=0;jHeight;j++) { + A->accMap[i][j] = 0; + + } + } + } + #endif +#endif x = y = DBL_To_PRM(.0); for (n = SKIP_FIRST; n; --n) { - (*Iterate) (x, y, &xo, &yo); + (*Iterate) (A, x, y, &xo, &yo); x = xo + NRAND(8) - 4; y = yo + NRAND(8) - 4; } @@ -239,12 +328,41 @@ draw_strange(ModeInfo * mi) Lx = (DBL) A->Width / UNIT / 2.2; Ly = (DBL) A->Height / UNIT / 2.2; for (n = A->Max_Pt; n; --n) { - (*Iterate) (x, y, &xo, &yo); - Buf->x = (short) (Lx * (x + DBL_To_PRM(1.1))); - Buf->y = (short) (Ly * (DBL_To_PRM(1.1) - y)); + (*Iterate) (A, x, y, &xo, &yo); + #ifdef useAccumulator + if (useAccumulator) { + int mx,my; + mx = (short) ( A->Width*0.1 + A->Width*0.8 * (xo - xmin) / (xmax - xmin) ); + my = (short) ( A->Width*0.1 + (A->Height - A->Width*0.2) * (yo - ymin) / (ymax - ymin) ); + if (mx>=0 && my>=0 && mxWidth && myHeight) { + A->accMap[mx][my]++; + } +#ifdef POINTS_HISTORY + /* #define clearOldPoint(i) { if (startedClearing) { field[oldPoints[i].x][oldPoints[i].y]--; } } + #define saveUnplot(X,Y) { clearOldPoint(oldPointsIndex) oldPoints[oldPointsIndex].x = X; oldPoints[oldPointsIndex].y = Y; oldPointsIndex = (oldPointsIndex + 1) % numOldPoints; if (oldPointsIndex==0) { startedClearing=1; } } + saveUnplot(mx,my) */ + if (startedClearing) { + int oldX = oldPointsX[oldPointsIndex]; + int oldY = oldPointsY[oldPointsIndex]; + if (oldX>=0 && oldY>=0 && oldXWidth && oldYHeight) { + A->accMap[oldX][oldY]--; + } + } + oldPointsX[oldPointsIndex] = mx; + oldPointsY[oldPointsIndex] = my; + oldPointsIndex = (oldPointsIndex + 1) % numOldPoints; + if (oldPointsIndex==0) { startedClearing=1; } +#endif + } else { + #endif + Buf->x = (int) (Lx * (x + DBL_To_PRM(1.1))); + Buf->y = (int) (Ly * (DBL_To_PRM(1.1) - y)); + Buf++; + A->Cur_Pt++; + #ifdef useAccumulator + } + #endif /* (void) fprintf( stderr, "X,Y: %d %d ", Buf->x, Buf->y ); */ - Buf++; - A->Cur_Pt++; if (xo > xmax) xmax = xo; else if (xo < xmin) @@ -257,34 +375,102 @@ draw_strange(ModeInfo * mi) y = yo + NRAND(8) - 4; } - XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); - - if (A->dbuf) /* jwz */ - { + MI_IS_DRAWN(mi) = True; + + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + + #ifdef useAccumulator + if (useAccumulator) { + float colorScale; + int col; + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + int pixelCount = 0; + #endif + colorScale = (A->Width*A->Height/640.0/480.0*800000.0/(float)A->Max_Pt*(float)NUM_COLS/256); + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, 0); + XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height); + } else { + XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); + XFillRectangle(display, window, gc, 0, 0, A->Width, A->Height); + } + for (i=0;iWidth;i++) { + for (j=0;jHeight;j++) { + if (A->accMap[i][j]>0) { + col = (float)A->accMap[i][j] * colorScale; + if (col>NUM_COLS-1) { + col = NUM_COLS-1; + } + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + if (col>0) { + if (colCol % MI_NPIXELS(mi)));*/ + XSetForeground(display, gc, cols[col].pixel); + if (A->dbuf != None) { + XSetForeground(display, A->dbuf_gc, cols[col].pixel); + XDrawPoint(display, A->dbuf, A->dbuf_gc, i, j); + } else { + XSetForeground(display, gc, cols[col].pixel); + XDrawPoint(display, window, gc, i, j); + } + } + } + } + if (A->dbuf != None) { + XCopyArea(display, A->dbuf, window, gc, 0, 0, A->Width, A->Height, 0, 0); + } + #ifdef VARY_SPEED_TO_AVOID_BOREDOM + /* Increaase the rate of change of the parameters if the attractor has become visually boring. */ + if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2))) { + A->Speed *= 1.25; + } else if (pixelCount>0 && pixelCountWidth*A->Height/1000) { + A->Speed *= 1.25; /* A->Count = 1000; */ + } else { + A->Speed = 4; /* reset to normal/default */ + } + if (A->Speed > 32) + A->Speed = 32; + A->Count += A->Speed; + if (A->Count >= 1000) { + for (i = MAX_PRM - 1; i >= 0; --i) + A->Prm1[i] = A->Prm2[i]; + Random_Prm(A->Prm2); + A->Count = 0; + } + #endif + } else { + #endif + + if (A->dbuf != None) { /* jwz */ XSetForeground(display, A->dbuf_gc, 0); -/* XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer1, - Cur_Pt,CoordModeOrigin);*/ - XFillRectangle(display, A->dbuf, A->dbuf_gc, 0,0, A->Width, A->Height); - } - else - XDrawPoints(display, window, gc, A->Buffer1, Cur_Pt, CoordModeOrigin); - - if (Max_Colors < 2) - XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi)); +/* XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer1, + Cur_Pt,CoordModeOrigin); */ + XFillRectangle(display, A->dbuf, A->dbuf_gc, 0, 0, A->Width, A->Height); + } else + XDrawPoints(display, window, gc, A->Buffer1, Cur_Pt, CoordModeOrigin); + + if (MI_NPIXELS(mi) < 2) + XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); else - XSetForeground(display, gc, MI_PIXEL(mi, A->Col % Max_Colors)); + XSetForeground(display, gc, MI_PIXEL(mi, A->Col % MI_NPIXELS(mi))); - if (A->dbuf) - { + if (A->dbuf != None) { XSetForeground(display, A->dbuf_gc, 1); XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer2, A->Cur_Pt, - CoordModeOrigin); - } - else - XDrawPoints(display, window, gc, A->Buffer2, A->Cur_Pt, CoordModeOrigin); + CoordModeOrigin); + XCopyPlane(display, A->dbuf, window, gc, 0, 0, A->Width, A->Height, 0, 0, 1); + } else + XDrawPoints(display, window, gc, A->Buffer2, A->Cur_Pt, CoordModeOrigin); - if (A->dbuf) - XCopyPlane(display, A->dbuf, window, gc, 0,0,A->Width,A->Height,0,0, 1); + #ifdef useAccumulator + } + #endif Buf = A->Buffer1; A->Buffer1 = A->Buffer2; @@ -301,31 +487,42 @@ draw_strange(ModeInfo * mi) A->Count = 0; } A->Col++; + mi->recursion_depth = A->Count; } /***************************************************************/ -void +ENTRYPOINT void init_strange(ModeInfo * mi) { + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); +#ifndef NO_DBUF + GC gc = MI_GC(mi); +#endif ATTRACTOR *Attractor; - curve = get_integer_resource ("curve", "Integer"); - if (curve <= 0) curve = 10; +#ifdef POINTS_HISTORY + startedClearing=0; + oldPointsIndex=0; +#endif if (Root == NULL) { - Root = (ATTRACTOR *) calloc( - MI_NUM_SCREENS(mi), sizeof (ATTRACTOR)); - if (Root == NULL) + if ((Root = (ATTRACTOR *) calloc(MI_NUM_SCREENS(mi), + sizeof (ATTRACTOR))) == NULL) return; } - if (Fold == NULL) { + Attractor = &Root[MI_SCREEN(mi)]; + + if (Attractor->Fold == NULL) { int i; - Fold = (PRM *) calloc(UNIT2 + 1, sizeof (PRM)); - if (Fold == NULL) + if ((Attractor->Fold = (PRM *) calloc(UNIT2 + 1, + sizeof (PRM))) == NULL) { + free_strange(display, Attractor); return; + } for (i = 0; i <= UNIT2; ++i) { DBL x; @@ -336,21 +533,27 @@ init_strange(ModeInfo * mi) /* x = x*(1.0-x)*4.0; */ x = (DBL) (i) / UNIT; x = sin(x); - Fold[i] = DBL_To_PRM(x); + Attractor->Fold[i] = DBL_To_PRM(x); } } - Attractor = &Root[MI_SCREEN(mi)]; - Attractor->Buffer1 = (XPoint *) calloc(MAX_POINTS, sizeof (XPoint)); + Attractor->Max_Pt = points; + if (Attractor->Buffer1 == NULL) - goto Abort; - Attractor->Buffer2 = (XPoint *) calloc(MAX_POINTS, sizeof (XPoint)); + if ((Attractor->Buffer1 = (XPoint *) calloc(Attractor->Max_Pt, + sizeof (XPoint))) == NULL) { + free_strange(display, Attractor); + return; + } if (Attractor->Buffer2 == NULL) - goto Abort; - Attractor->Max_Pt = MAX_POINTS; + if ((Attractor->Buffer2 = (XPoint *) calloc(Attractor->Max_Pt, + sizeof (XPoint))) == NULL) { + free_strange(display, Attractor); + return; + } - Attractor->Width = MI_WIN_WIDTH(mi); - Attractor->Height = MI_WIN_HEIGHT(mi); + Attractor->Width = MI_WIDTH(mi); + Attractor->Height = MI_HEIGHT(mi); Attractor->Cur_Pt = 0; Attractor->Count = 0; Attractor->Col = NRAND(MI_NPIXELS(mi)); @@ -359,62 +562,141 @@ init_strange(ModeInfo * mi) Attractor->Iterate = Funcs[NRAND(2)]; Random_Prm(Attractor->Prm1); Random_Prm(Attractor->Prm2); +#ifndef NO_DBUF + if (Attractor->dbuf != None) + XFreePixmap(display, Attractor->dbuf); +#ifdef useAccumulator +#define colorDepth ( useAccumulator ? MI_DEPTH(mi) : 1 ) +#else +#define colorDepth 1 +#endif + Attractor->dbuf = XCreatePixmap(display, window, + Attractor->Width, Attractor->Height, colorDepth); + /* Allocation checked */ + if (Attractor->dbuf != None) { + XGCValues gcv; - Attractor->dbuf = XCreatePixmap(MI_DISPLAY(mi), MI_WINDOW(mi), - Attractor->Width, Attractor->Height, 1); - if (Attractor->dbuf) - { - XGCValues gcv; gcv.foreground = 0; gcv.background = 0; +#ifndef HAVE_COCOA + gcv.graphics_exposures = False; +#endif /* HAVE_COCOA */ gcv.function = GXcopy; - Attractor->dbuf_gc = XCreateGC(MI_DISPLAY(mi), Attractor->dbuf, - GCForeground|GCBackground|GCFunction, - &gcv); - XFillRectangle(MI_DISPLAY(mi), Attractor->dbuf, - Attractor->dbuf_gc, 0,0, Attractor->Width, - Attractor->Height); - XSetBackground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi)); - XSetFunction(MI_DISPLAY(mi), MI_GC(mi), GXcopy); - } - - XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); - return; - - Abort: - if (Attractor->Buffer1 != NULL) - free(Attractor->Buffer1); - if (Attractor->Buffer2 != NULL) - free(Attractor->Buffer2); - Attractor->Buffer1 = NULL; - Attractor->Buffer2 = NULL; - Attractor->Cur_Pt = 0; - return; + + if (Attractor->dbuf_gc != None) + XFreeGC(display, Attractor->dbuf_gc); + + if ((Attractor->dbuf_gc = XCreateGC(display, Attractor->dbuf, +#ifndef HAVE_COCOA + GCGraphicsExposures | +#endif /* HAVE_COCOA */ + GCFunction | GCForeground | GCBackground, + &gcv)) == None) { + XFreePixmap(display, Attractor->dbuf); + Attractor->dbuf = None; + } else { + XFillRectangle(display, Attractor->dbuf, Attractor->dbuf_gc, + 0, 0, Attractor->Width, Attractor->Height); + XSetBackground(display, gc, MI_BLACK_PIXEL(mi)); + XSetFunction(display, gc, GXcopy); + } + } +#endif + + +#ifdef useAccumulator + #define A Attractor + if (useAccumulator) { + XWindowAttributes xgwa; + int i,j; + XGetWindowAttributes (display, window, &xgwa); + /* cmap = xgwa.colormap; */ + /* cmap = XCreateColormap(display, window, MI_VISUAL(mi), AllocAll); */ + Attractor->accMap = (int**)calloc(Attractor->Width,sizeof(int*)); + for (i=0;iWidth;i++) { + Attractor->accMap[i] = (int*)calloc(Attractor->Height,sizeof(int)); + for (j=0;jHeight;j++) { + Attractor->accMap[i][j] = 0; + } + } +#ifdef POINTS_HISTORY + numOldPoints = A->Max_Pt * MERGE_FRAMES; + oldPointsX = (int*)calloc(numOldPoints,sizeof(int)); + oldPointsY = (int*)calloc(numOldPoints,sizeof(int)); +#endif + cols = (XColor*)calloc(NUM_COLS,sizeof(XColor)); + for (i=0;iWidth;i++) { + (void) free((void *) Root->accMap[i]); + } + (void) free((void *) Root->accMap); +#endif +#ifdef POINTS_HISTORY + free(oldPointsX); + free(oldPointsY); +#endif + for (screen = 0; screen < MI_NUM_SCREENS(mi); ++screen) + free_strange(MI_DISPLAY(mi), &Root[screen]); + (void) free((void *) Root); + Root = (ATTRACTOR *) NULL; } - free(Root); - Root = NULL; - if (Fold != NULL) - free(Fold); - Fold = NULL; } + +XSCREENSAVER_MODULE ("Strange", strange) + +#endif /* MODE_strange */