ENTRYPOINT void init_strange(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); #ifndef NO_DBUF Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); #endif ATTRACTOR *Attractor; if (Root == NULL) { if ((Root = (ATTRACTOR *) calloc(MI_NUM_SCREENS(mi), sizeof (ATTRACTOR))) == NULL) return; } Attractor = &Root[MI_SCREEN(mi)]; if (Attractor->Fold == NULL) { int i; if ((Attractor->Fold = (PRM *) calloc(UNIT2 + 1, sizeof (PRM))) == NULL) { free_strange(display, Attractor); return; } for (i = 0; i <= UNIT2; ++i) { DBL x; /* x = ( DBL )(i)/UNIT2; */ /* x = sin( M_PI/2.0*x ); */ /* x = sqrt( x ); */ /* x = x*x; */ /* x = x*(1.0-x)*4.0; */ x = (DBL) (i) / UNIT; x = sin(x); Attractor->Fold[i] = DBL_To_PRM(x); } } if (Attractor->Buffer1 == NULL) if ((Attractor->Buffer1 = (XPoint *) calloc(MAX_POINTS, sizeof (XPoint))) == NULL) { free_strange(display, Attractor); return; } if (Attractor->Buffer2 == NULL) if ((Attractor->Buffer2 = (XPoint *) calloc(MAX_POINTS, sizeof (XPoint))) == NULL) { free_strange(display, Attractor); return; } Attractor->Max_Pt = MAX_POINTS; Attractor->Width = MI_WIDTH(mi); Attractor->Height = MI_HEIGHT(mi); Attractor->Cur_Pt = 0; Attractor->Count = 0; Attractor->Col = NRAND(MI_NPIXELS(mi)); Attractor->Speed = 4; Attractor->Iterate = Funcs[NRAND(2)]; Random_Prm(Attractor->Prm1); Random_Prm(Attractor->Prm2); #ifndef NO_DBUF if (Attractor->dbuf != None) XFreePixmap(display, Attractor->dbuf); Attractor->dbuf = XCreatePixmap(display, window, Attractor->Width, Attractor->Height, 1); /* Allocation checked */ if (Attractor->dbuf != None) { XGCValues gcv; gcv.foreground = 0; gcv.background = 0; #ifndef HAVE_COCOA gcv.graphics_exposures = False; #endif /* HAVE_COCOA */ gcv.function = GXcopy; 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 MI_CLEARWINDOW(mi); /* Do not want any exposure events from XCopyPlane */ XSetGraphicsExposures(display, MI_GC(mi), False); }
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; #ifdef POINTS_HISTORY startedClearing=0; oldPointsIndex=0; #endif if (Root == NULL) { if ((Root = (ATTRACTOR *) calloc(MI_NUM_SCREENS(mi), sizeof (ATTRACTOR))) == NULL) return; } Attractor = &Root[MI_SCREEN(mi)]; if (Attractor->Fold == NULL) { int i; if ((Attractor->Fold = (PRM *) calloc(UNIT2 + 1, sizeof (PRM))) == NULL) { free_strange(display, Attractor); return; } for (i = 0; i <= UNIT2; ++i) { DBL x; /* x = ( DBL )(i)/UNIT2; */ /* x = sin( M_PI/2.0*x ); */ /* x = sqrt( x ); */ /* x = x*x; */ /* x = x*(1.0-x)*4.0; */ x = (DBL) (i) / UNIT; x = sin(x); Attractor->Fold[i] = DBL_To_PRM(x); } } Attractor->Max_Pt = points; if (Attractor->Buffer1 == NULL) if ((Attractor->Buffer1 = (XPoint *) calloc(Attractor->Max_Pt, sizeof (XPoint))) == NULL) { free_strange(display, Attractor); return; } if (Attractor->Buffer2 == NULL) if ((Attractor->Buffer2 = (XPoint *) calloc(Attractor->Max_Pt, sizeof (XPoint))) == NULL) { free_strange(display, Attractor); return; } Attractor->Width = MI_WIDTH(mi); Attractor->Height = MI_HEIGHT(mi); Attractor->Cur_Pt = 0; Attractor->Count = 0; Attractor->Col = NRAND(MI_NPIXELS(mi)); Attractor->Speed = 4; 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; gcv.foreground = 0; gcv.background = 0; #ifndef HAVE_COCOA gcv.graphics_exposures = False; #endif /* HAVE_COCOA */ gcv.function = GXcopy; 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;i<Attractor->Width;i++) { Attractor->accMap[i] = (int*)calloc(Attractor->Height,sizeof(int)); for (j=0;j<Attractor->Height;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;i<NUM_COLS;i++) { float li; #define MINBLUE 1 #define FULLBLUE 128 li = MINBLUE + (255.0-MINBLUE) * log(1.0 + ACC_GAMMA*(float)i/NUM_COLS) / log(1.0 + ACC_GAMMA); if (li<FULLBLUE) { cols[i].red = 0; cols[i].green = 0; cols[i].blue = 65536*li/FULLBLUE; } else { cols[i].red = 65536*(li-FULLBLUE)/(256-FULLBLUE); cols[i].green = 65536*(li-FULLBLUE)/(256-FULLBLUE); cols[i].blue = 65535; } XAllocColor (display, xgwa.colormap, &cols[i]); /* if (!XAllocColor(MI_DISPLAY(mi), cmap, &cols[i])) { if (!XAllocColor(display, cmap, &cols[i])) { cols[i].pixel = WhitePixel (display, DefaultScreen (display)); cols[i].red = cols[i].green = cols[i].blue = 0xFFFF; } */ } /* XSetWindowColormap(display, window, cmap); (void) XSetWMColormapWindows(display, window, &window, 1); XInstallColormap(display, cmap); XStoreColors(display, cmap, cols, 256); */ } #undef A #endif MI_CLEARWINDOW(mi); /* Do not want any exposure events from XCopyPlane */ XSetGraphicsExposures(display, MI_GC(mi), False); }
ENTRYPOINT void draw_strange(ModeInfo * mi) { int i, j, n, Cur_Pt; PRM x, y, xo, yo; DBL u; XPoint *Buf; Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); DBL Lx, Ly; 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; for (j = MAX_PRM - 1; j >= 0; --j) A->Prm[j] = DBL_To_PRM((1.0 - u) * A->Prm1[j] + u * A->Prm2[j]); x = y = DBL_To_PRM(.0); for (n = SKIP_FIRST; n; --n) { (*Iterate) (A, x, y, &xo, &yo); x = xo + NRAND(8) - 4; y = yo + NRAND(8) - 4; } xmax = 0; xmin = UNIT * 4; ymax = 0; ymin = UNIT * 4; A->Cur_Pt = 0; Buf = A->Buffer2; Lx = (DBL) A->Width / UNIT / 2.2; Ly = (DBL) A->Height / UNIT / 2.2; for (n = A->Max_Pt; n; --n) { (*Iterate) (A, x, y, &xo, &yo); Buf->x = (int) (Lx * (x + DBL_To_PRM(1.1))); Buf->y = (int) (Ly * (DBL_To_PRM(1.1) - y)); /* (void) fprintf( stderr, "X,Y: %d %d ", Buf->x, Buf->y ); */ Buf++; A->Cur_Pt++; if (xo > xmax) xmax = xo; else if (xo < xmin) xmin = xo; if (yo > ymax) ymax = yo; else if (yo < ymin) ymin = yo; x = xo + NRAND(8) - 4; y = yo + NRAND(8) - 4; } MI_IS_DRAWN(mi) = True; XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); 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 (MI_NPIXELS(mi) < 2) XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); else XSetForeground(display, gc, MI_PIXEL(mi, A->Col % MI_NPIXELS(mi))); if (A->dbuf != None) { XSetForeground(display, A->dbuf_gc, 1); XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer2, A->Cur_Pt, 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); Buf = A->Buffer1; A->Buffer1 = A->Buffer2; A->Buffer2 = Buf; if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2))) A->Count += 4 * A->Speed; else 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; } A->Col++; }
ENTRYPOINT void draw_strange(ModeInfo * mi) { int i, j, n, Cur_Pt; PRM x, y, xo, yo; DBL u; XPoint *Buf; Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); DBL Lx, Ly; 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) / 40000.0; for (j = MAX_PRM - 1; j >= 0; --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;i<A->Width;i++) { for (j=0;j<A->Height;j++) { A->accMap[i][j] = 0; } } } #endif #endif x = y = DBL_To_PRM(.0); for (n = SKIP_FIRST; n; --n) { (*Iterate) (A, x, y, &xo, &yo); x = xo + NRAND(8) - 4; y = yo + NRAND(8) - 4; } xmax = 0; xmin = UNIT * 4; ymax = 0; ymin = UNIT * 4; A->Cur_Pt = 0; Buf = A->Buffer2; Lx = (DBL) A->Width / UNIT / 2.2; Ly = (DBL) A->Height / UNIT / 2.2; for (n = A->Max_Pt; n; --n) { (*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 && mx<A->Width && my<A->Height) { 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 && oldX<A->Width && oldY<A->Height) { 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 ); */ if (xo > xmax) xmax = xo; else if (xo < xmin) xmin = xo; if (yo > ymax) ymax = yo; else if (yo < ymin) ymin = yo; x = xo + NRAND(8) - 4; y = yo + NRAND(8) - 4; } 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;i<A->Width;i++) { for (j=0;j<A->Height;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 (col<NUM_COLS-1) /* we don't count maxxed out pixels */ pixelCount++; } #endif if (MI_NPIXELS(mi) < 2) XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); else /*XSetForeground(display, gc, MI_PIXEL(mi, A->Col % 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 && pixelCount<A->Width*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 (MI_NPIXELS(mi) < 2) XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); else XSetForeground(display, gc, MI_PIXEL(mi, A->Col % MI_NPIXELS(mi))); if (A->dbuf != None) { XSetForeground(display, A->dbuf_gc, 1); XDrawPoints(display, A->dbuf, A->dbuf_gc, A->Buffer2, A->Cur_Pt, 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); #ifdef useAccumulator } #endif Buf = A->Buffer1; A->Buffer1 = A->Buffer2; A->Buffer2 = Buf; if ((xmax - xmin < DBL_To_PRM(.2)) && (ymax - ymin < DBL_To_PRM(.2))) A->Count += 4 * A->Speed; else 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; } A->Col++; mi->recursion_depth = A->Count; }