From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/abstractile.c | 1605 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1605 insertions(+) create mode 100644 hacks/abstractile.c (limited to 'hacks/abstractile.c') diff --git a/hacks/abstractile.c b/hacks/abstractile.c new file mode 100644 index 0000000..b4394f1 --- /dev/null +++ b/hacks/abstractile.c @@ -0,0 +1,1605 @@ +/* + * Copyright (c) 2004-2009 Steve Sundstrom + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#include "screenhack.h" +#include "colors.h" +#include "hsv.h" +#include +#include +#include +/*#include */ + +#define MODE_CREATE 0 /* init, create, then finish sleep */ +#define MODE_ERASE 1 /* erase, then reset colors */ +#define MODE_DRAW 2 + +#define DIR_NONE 0 +#define DIR_UP 1 +#define DIR_DOWN 2 +#define DIR_LEFT 3 +#define DIR_RIGHT 4 + +#define LINE_FORCE 1 +#define LINE_NEW 2 +#define LINE_BRIN 3 +#define LINE_BROUT 4 + +#define PT_UL 0 +#define PT_MP 1 +#define PT_LR 2 +#define PT_NL 3 + +#define D3D_NONE 0 +#define D3D_BLOCK 1 +#define D3D_NEON 2 +#define D3D_TILED 3 + +#define TILE_RANDOM 0 +#define TILE_FLAT 1 +#define TILE_THIN 2 +#define TILE_OUTLINE 3 +#define TILE_BLOCK 4 +#define TILE_NEON 5 +#define TILE_TILED 6 + +#define BASECOLORS 30 +#define SHADES 12 +#define MAXCOLORS 40 +#define LAYERS 4 +#define PATTERNS 40 +#define SHAPES 18 +#define DRAWORDERS 40 +#define COLORMAPS 20 +#define WAVES 6 +#define STRETCHES 8 + +struct lineStruct { + unsigned int x, y, len, obj, color, ndol; + int deo; + Bool hv; +}; + +struct gridStruct { + unsigned int line, hl, hr, vu, vd, dhl, dhr, dvu, dvd; +}; + +/* basically the same as global variables, but used to keep them in a bucket + and pass them around easier like the original C++ implementation */ +struct state { + /* window values */ + Display *display; + Window window; + XWindowAttributes xgwa; + GC fgc, bgc; + XColor colors[255]; + + /* memory values */ + struct lineStruct *dline, *eline; + struct gridStruct *grid; + unsigned int *zlist, *fdol; + Bool *odi; + /* draw, erase, fill, init, line, object, z indexes */ + unsigned int di, ei, fi, ii, bi, li, eli, oi, zi; + /* size variables */ + int gridx, gridy; /* grid size */ + unsigned int gridn; + int lwid, bwid, swid;/* line width, background width, shadow width */ + int narray, max_wxh; + int elwid, elpu, egridx, egridy; /* for now */ + /* fill variables */ + int bnratio; /* ratio of branch lines to new lines */ + int maxlen; /* maximum length of line */ + int forcemax; /* make line be max possible length */ + int olen; /* open length set by findopen */ + int bln; /* blocking line number set by findopen, -1=edge */ + /* color variables */ + int ncolors; /* number of colors for screen */ + int shades; + int rco[MAXCOLORS]; /* random ordering of colors for deo */ + int cmap; + int layers; + Bool newcols; /* can we create new colormaps with each screen */ + /* draw variables */ + int dmap, emap; /* pattern by which line draw order is determined */ + int dvar, evar; /* random number added to .deo to vary */ + int ddir, edir; /* draw/erase in forward direction or reverse */ + int lpu; /* lines drawn per update used to adjust speed */ + int d3d; + int round; + int outline; + /* layered draw variables */ + int pattern[LAYERS], shape[LAYERS], mix[LAYERS]; + int csw[LAYERS], wsx[LAYERS], wsy[LAYERS], sec[LAYERS]; + int cs1[LAYERS], cs2[LAYERS], cs3[LAYERS]; int cs4[LAYERS]; + int wave[LAYERS], waveh[LAYERS], wavel[LAYERS]; + int rx1[LAYERS], rx2[LAYERS], rx3[LAYERS]; + int ry1[LAYERS], ry2[LAYERS], ry3[LAYERS]; + /* misc variables */ + int mode, sleep, speed, tile, dialog; + Bool grid_full, resized; + struct timeval time; +}; + +static int +_min(int a, int b) +{ + if (a<=b) + return(a); + return(b); +} + +static int +_max(int a, int b) +{ + if (a>=b) + return(a); + return(b); +} + +static int +_dist(struct state *st, int x1, int x2, int y1, int y2, int s) +{ + double xd=x1-x2; + double yd=y1-y2; + switch(s) { + case 0: + return((int)sqrt(xd*xd+yd*yd)); + case 1: + return((int)sqrt(xd*xd*st->cs1[0]*2+yd*yd)); + case 2: + return((int)sqrt(xd*xd+yd*yd*st->cs2[0]*2)); + default: + return((int)sqrt(xd*xd*st->cs1[0]/st->cs2[0]+yd*yd*st->cs3[0]/st->cs4[0])); + } +} + +static int +_wave(struct state *st, int x, int h, int l, int wave) +{ + l+=1; + switch(wave) { + case 0: /* cos wave*/ + return((int)(cos((double)x*M_PI/l)*h)); + case 1: /* double wave*/ + case 2: /* double wave*/ + return((int)(cos((double)x*M_PI/l)*h)+(int)(sin((double)x*M_PI/l/st->cs1[1])*h)); + case 3: /* zig zag */ + return(abs((x%(l*2)-l))*h/l); + case 4: /* giant zig zag */ + return(abs((x%(l*4)-l*2))*h*3/l); + case 5: /* sawtooth */ + return((x%(l))*h/l); + default: /* no wave */ + return(0); + } +} + +static int +_triangle(struct state *st, int x, int y, int rx, int ry, int t) +{ + switch(t) { + case 1: + return(_min(_min(x+y+rx-(st->gridx/2),st->gridx-x+y),(st->gridy-y+(ry/2))*3/2)); + case 2: + return(_min(_min(x-rx,y-ry),(rx+ry-x-y)*2/3)); + case 3: + return(_min(_min(st->gridx-x-rx,y-ry),(rx+ry-st->gridx+x-y)*2/3)); + case 4: + return(_min(_min(x-rx,st->gridy-y-ry),(rx+ry-x-st->gridy+y)*2/3)); + } + return(_min(_min(st->gridx-x-rx,st->gridy-y-ry),(rx+ry-st->gridx+x-st->gridy+y)*2/3)); +} + +static void +_init_zlist(struct state *st) +{ + unsigned int tmp, y, z; + + st->gridx=st->xgwa.width/st->lwid; + st->gridy=st->xgwa.height/st->lwid; + if ((st->gridx <= 0) || (st->gridy <= 0)) abort(); + st->gridn=st->gridx*st->gridy; + /* clear grid */ + for (z=0; zgridn; z++) { + st->grid[z].line=st->grid[z].hl=st->grid[z].hr=st->grid[z].vu=st->grid[z].vd=st->grid[z].dhl=st->grid[z].dhr=st->grid[z].dvu=st->grid[z].dvd=0; + st->zlist[z]=z; + } + /* rather than pull x,y points randomly and wait to hit final empy cells a + list of all points is created and mixed so empty cells do get hit last */ + for (z=0; zgridn; z++) { + y=random()%st->gridn; + tmp=st->zlist[y]; + st->zlist[y]=st->zlist[z]; + st->zlist[z]=tmp; + } +} + +static void +make_color_ramp_rgb (Screen *screen, Visual *visual, Colormap cmap, + int r1, int g1, int b1, int r2, int g2, int b2, + XColor *colors, int *ncolorsP, Bool closed_p) +{ + int h1, h2; + double s1, s2, v1, v2; + rgb_to_hsv(r1, g1, b1, &h1, &s1, &v1); + rgb_to_hsv(r2, g2, b2, &h2, &s2, &v2); + make_color_ramp(screen, visual, cmap, h1, s1, v1, h2, s2, v2, + colors, ncolorsP, False, True, 0); +} + + +static void +_init_colors(struct state *st) +{ + int col[BASECOLORS]; + int c1, c2, c3, h1, h2, h3; + int r1, g1, b1, r2, g2, b2, r3, g3, b3; + double s1, s2, s3, v1, v2, v3; + XColor tmp_col1[16], tmp_col2[16], tmp_col3[16]; + + unsigned short basecol[BASECOLORS][3]={ + /* 0 dgray */ {0x3333,0x3333,0x3333}, + /* 1 dbrown */ {0x6666,0x3333,0x0000}, + /* 2 dred */ {0x9999,0x0000,0x0000}, + /* 3 orange */ {0xFFFF,0x6666,0x0000}, + /* 4 gold */ {0xFFFF,0xCCCC,0x0000}, + /* 5 olive */ {0x6666,0x6666,0x0000}, + /* 6 ivy */ {0x0000,0x6666,0x0000}, + /* 7 dgreen */ {0x0000,0x9999,0x0000}, + /* 8 bluegray */ {0x3333,0x6666,0x6666}, + /* 9 dblue */ {0x0000,0x0000,0x9999}, + /* 10 blue */ {0x3333,0x3333,0xFFFF}, + /* 11 dpurple */ {0x6666,0x0000,0xCCCC}, + /* 12 purple */ {0x6666,0x3333,0xFFFF}, + /* 13 violet */ {0x9999,0x3333,0x9999}, + /* 14 magenta */ {0xCCCC,0x3333,0xCCCC}, + /* lights */ + /* 15 gray */ {0x3333,0x3333,0x3333}, + /* 16 brown */ {0x9999,0x6666,0x3333}, + /* 17 tan */ {0xCCCC,0x9999,0x3333}, + /* 18 red */ {0xFFFF,0x0000,0x0000}, + /* 19 lorange */ {0xFFFF,0x9999,0x0000}, + /* 20 yellow */ {0xFFFF,0xFFFF,0x0000}, + /* 21 lolive */ {0x9999,0x9999,0x0000}, + /* 22 green */ {0x3333,0xCCCC,0x0000}, + /* 23 lgreen */ {0x3333,0xFFFF,0x3333}, + /* 24 cyan */ {0x0000,0xCCCC,0xCCCC}, + /* 25 sky */ {0x3333,0xFFFF,0xFFFF}, + /* 26 marine */ {0x3333,0x6666,0xFFFF}, + /* 27 lblue */ {0x3333,0xCCCC,0xFFFF}, + /* 28 lpurple */ {0x9999,0x9999,0xFFFF}, + /* 29 pink */ {0xFFFF,0x9999,0xFFFF}}; + + if (st->d3d) { + st->shades = (st->d3d==D3D_TILED) ? 5 : st->lwid/2+1; + st->ncolors=4+random()%4; + if (st->cmap>0) { /* tint the basecolors a bit */ + for (c1=0; c1cmap%4) { + case 0: /* all */ + for (c1=0; c1ncolors; c1++) + col[c1]=random()%BASECOLORS; + break; + case 1: /* darks */ + for (c1=0; c1ncolors; c1++) + col[c1]=random()%15; + break; + case 2: /* semi consecutive darks */ + col[0]=random()%15; + for (c1=1; c1ncolors; c1++) + col[c1]=(col[c1-1]+1+random()%2)%15; + break; + case 3: /* consecutive darks */ + col[0]=random()%(15-st->ncolors); + for (c1=1; c1ncolors; c1++) + col[c1]=col[c1-1]+1; + break; + } + for (c1=0; c1ncolors; c1++) { + /* adjust colors already set */ + for (h1=c1*st->shades-1; h1>=0; h1--) + st->colors[h1+st->shades]=st->colors[h1]; + make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + basecol[col[c1]][0], basecol[col[c1]][1], basecol[col[c1]][2], + 0xFFFF, 0xFFFF, 0xFFFF, st->colors, &st->shades, + False); + } + return; + } + /* not 3d */ + st->shades=1; + if (st->cmap%2) { /* basecolors */ + if (random()%3) { + c1=random()%15; + c2=(c1+3+(random()%5))%15; + c3=(c2+3+(random()%5))%15; + } else { + c1=random()%BASECOLORS; + c2=(c1+5+(random()%10))%BASECOLORS; + c3=(c2+5+(random()%10))%BASECOLORS; + } + r1=basecol[c1][0]; + g1=basecol[c1][1]; + b1=basecol[c1][2]; + r2=basecol[c2][0]; + g2=basecol[c2][1]; + b2=basecol[c2][2]; + r3=basecol[c3][0]; + g3=basecol[c3][1]; + b3=basecol[c3][2]; + } else { /* random rgb's */ + r1=random()%65535; + g1=random()%65535; + b1=random()%65535; + r2=(r1+16384+random()%32768)%65535; + g2=(g1+16384+random()%32768)%65535; + b2=(b1+16384+random()%32768)%65535; + r3=(r2+16384+random()%32768)%65535; + g3=(g2+16384+random()%32768)%65535; + b3=(b2+16384+random()%32768)%65535; + } + switch(st->cmap) { + case 0: /* make_color_ramp color->color */ + case 1: + case 2: /* make_color_ramp color->white */ + case 3: + st->ncolors=5+random()%5; + if (st->cmap>1) + r2=g2=b2=0xFFFF; + make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + r1, g1, b1, r2, g2, b2, + st->colors, &st->ncolors, random()%2); + break; + case 4: /* 3 color make_color_loop */ + case 5: + case 6: + case 7: + st->ncolors=8+random()%12; + rgb_to_hsv(r1, g1, b1, &h1, &s1, &v1); + rgb_to_hsv(r2, g2, b2, &h2, &s2, &v2); + rgb_to_hsv(r3, g3, b3, &h3, &s3, &v3); + + make_color_loop(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + h1, s1, v1, h2, s2, v2, h3, s3, v3, + st->colors, &st->ncolors, True, False); + break; + case 8: /* random smooth */ + case 9: + st->ncolors=(random()%4)*6+12; + make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, + st->xgwa.colormap, st->colors, &st->ncolors, + True, False, True); + break; + case 10: /* rainbow */ + st->ncolors=(random()%4)*6+12; + make_uniform_colormap (st->xgwa.screen, st->xgwa.visual, + st->xgwa.colormap, st->colors, &st->ncolors, + True, False, True); + break; + case 11: /* dark to light blend */ + case 12: + case 13: + case 14: + st->ncolors=7; + make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + r1, g1, b1, 0xFFFF, 0xFFFF, 0xFFFF, + tmp_col1, &st->ncolors, False); + make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + r2, g2, b2, 0xFFFF, 0xFFFF, 0xFFFF, + tmp_col2, &st->ncolors, False); + if (st->cmap<13) { + for(c1=0; c1<=4; c1++) { + st->colors[c1*2]=tmp_col1[c1]; + st->colors[c1*2+1]=tmp_col2[c1]; + } + st->ncolors=10; + } else { + make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, + r3, g3, b3, 0xFFFF, 0xFFFF, 0xFFFF, + tmp_col3, &st->ncolors, False); + for(c1=0; c1<=4; c1++) { + st->colors[c1*3]=tmp_col1[c1]; + st->colors[c1*3+1]=tmp_col2[c1]; + st->colors[c1*3+2]=tmp_col3[c1]; + } + st->ncolors=15; + } + break; + default: /* random */ + st->ncolors=(random()%4)*6+12; + make_random_colormap (st->xgwa.screen, st->xgwa.visual, + st->xgwa.colormap, st->colors, &st->ncolors, + False, True, False, True); + break; + } + + /* set random color order for drawing and erasing */ + for (c1=0; c1rco[c1]=c1; + for (c1=0; c1rco[c1]; + st->rco[c1]=st->rco[c3]; + st->rco[c3]=c2; + } +} + +static int _comparedeo(const void *i, const void *j) +{ + struct lineStruct *h1, *h2; + + h1=(struct lineStruct *)i; + h2=(struct lineStruct *)j; + if (h1->deo > h2->deo) + return(1); + if (h1->deo < h2->deo) + return(-1); + return(0); +} + +static int +_hv(struct state *st, int x, int y, int d1, int d2, int pn, Bool de) +{ + int v1, v2, r; + + switch (d1) { + case 0: + v1 = (de) ? st->egridx-x : st->gridx-x; + break; + case 1: + v1 = y; + break; + case 2: + v1 = x; + break; + default: + v1 = (de) ? st->egridy-y : st->gridy-y; + break; + } + switch (d2) { + case 0: + v2 = (de) ? st->egridx-x : st->gridx-x; + break; + case 1: + v2 = y; + break; + case 2: + v2 = x; + break; + default: + v2 = (de) ? st->egridy-y : st->gridy-y; + break; + } + r = (de) ? (st->dline[st->li].hv) ? (v1+10000)*pn : (v2+10000)*-pn : + (st->eline[st->li].hv) ? (v1+10000)*pn : (v2+10000)*-pn; + return(r); +} + +static int +_getdeo(struct state *st, int x, int y, int map, int de) +{ + int cr; + switch(map) { + case 0: /* horizontal one side */ + return(x); + case 1: /* vertical one side */ + return(y); + case 2: /* horizontal two side */ + return(_min(x,st->gridx-x)+1); + case 3: /* vertical two side */ + return(_min(y,st->gridy-y)+1); + case 4: /* square */ + return(_max(abs(x-st->rx3[de]),abs(y-st->ry3[de]))+1); + case 5: /* two squares */ + return(_min(_max(abs(x-(st->rx3[de]/2)),abs(y-st->ry3[de])),_max(abs(x-(st->gridx-(st->rx2[de]/2))),abs(y-st->ry2[de])))+1); + case 6: /* horizontal rectangle */ + return(_max(abs(x-st->rx3[de]),abs(y-(st->ry3[de]))*st->cs1[de])+1); + case 7: /* vertical rectangle */ + return(_max(abs(x-st->rx3[de])*st->cs1[de],abs(y-(st->ry3[de])))+1); + case 8: /* + cross */ + return(_min(abs(x-st->rx3[de]),abs(y-(st->ry3[de])))+1); + case 9: /* diagonal */ + return((x*3/4+y)+1); + case 10: /* opposite diagonal */ + return((x*3/4+st->gridy-y)+1); + case 11: /* diamond */ + return((abs(x-st->rx3[de])+abs(y-st->ry3[de]))/2+1); + case 12: /* two diamonds */ + return(_min(abs(x-(st->rx3[de]/2))+abs(y-st->ry3[de]),abs(x-(st->gridx-(st->rx2[de]/2)))+abs(y-st->ry2[de]))/2+1); + case 13: /* circle */ + return(_dist(st,x,st->rx3[de],y,st->ry3[de],0)+1); + case 14: /* horizontal ellipse */ + return(_dist(st,x,st->rx3[de],y,st->ry3[de],1)+1); + case 15: /* vertical ellipse */ + return(_dist(st,x,st->rx3[de],y,st->ry3[de],2)+1); + case 16: /* two circles */ + return(_min(_dist(st,x,st->rx3[de]/2,y,st->ry3[de],0),_dist(st,x,st->gridx-(st->rx2[de]/2),y,st->ry2[de],0))+1); + case 17: /* horizontal straight wave */ + return(x+_wave(st,st->gridy+y,st->csw[0]*st->cs1[0],st->csw[0]*st->cs2[0],st->wave[de])); + case 18: /* vertical straight wave */ + return(y+_wave(st,st->gridx+x,st->csw[0]*st->cs1[0],st->csw[0]*st->cs2[0],st->wave[de])); + case 19: /* horizontal wavey wave */ + return(x+_wave(st,st->gridy+y+((x/5)*st->edir),st->csw[de]*st->cs1[de],st->csw[de]*st->cs2[de],st->wave[de])+1); + case 20: /* vertical wavey wave */ + return(y+_wave(st,st->gridx+x+((y/5)*st->edir),st->csw[de]*st->cs1[de],st->csw[de]*st->cs2[de],st->wave[de])+1); +/* no d3d for 21,22 */ + case 21: /* simultaneous directional */ + return(_hv(st,x,y,st->cs1[0]%2,st->cs2[0]%2,1,de)); + case 22: /* reverse directional */ + return(_hv(st,x,y,st->cs1[0]%2,st->cs2[0]%2,-1,de)); + case 23: /* length */ + if (de) + return(st->dline[st->li].len*1000+random()%5000); + else + return(st->eline[st->li].len*1000+random()%5000); + case 24: /* object */ + case 25: + case 26: + case 27: + if (de) + return(st->dline[st->li].obj*100); + else + return(st->eline[st->li].obj*100); + default: /* color */ + cr = (de) ? st->dline[st->li].color : st->eline[st->li].color; + if (map<34) cr=st->rco[cr]; + if ((map%6<4) || (de)) { /* by color */ + cr*=1000; + cr+=random()%1000; + } else if (map%6==4) { /* by color horizontaly */ + cr*=st->gridx; + cr+=(x+random()%(st->gridx/2)); + } else { /* by color vertically */ + cr*=st->gridy; + cr+=(y+random()%(st->gridy/2)); + } + return(cr); + } + return(1); +} + +static void +_init_screen(struct state *st) +{ + int nstr, x; + struct lineStruct *tmp; + + /* malloc memory in case of resize */ + if (st->resized) { + st->max_wxh=st->xgwa.width*st->xgwa.height; + if (st->dline!=NULL) + free(st->dline); + if (st->eline!=NULL) + free(st->eline); + if (st->grid!=NULL) + free(st->grid); + if (st->zlist!=NULL) + free(st->zlist); + if (st->fdol!=NULL) + free(st->fdol); + if (st->odi!=NULL) + free(st->odi); + st->narray = (st->xgwa.width+1)*(st->xgwa.height+1)/4+1; + st->dline = calloc(st->narray, sizeof(struct lineStruct)); + st->eline = calloc(st->narray, sizeof(struct lineStruct)); + st->grid = calloc(st->narray, sizeof(struct gridStruct)); + st->zlist = calloc(st->narray, sizeof(unsigned int)); + st->fdol = calloc(st->narray, sizeof(unsigned int)); + st->odi = calloc(st->narray, sizeof(Bool)); + if ((st->dline == NULL) || (st->eline == NULL) || + (st->grid == NULL) || (st->zlist == NULL) || + (st->fdol == NULL) || (st->odi == NULL)) { + fprintf(stderr, "not enough memory\n"); + exit(1); + } + st->dialog = (st->xgwa.width<500) ? 1 : 0; + st->resized=False; + } + if (st->ii) { + /* swap st->dline and st->eline pointers to resort and erase */ + tmp=st->eline; + st->eline=st->dline; + st->dline=tmp; + st->eli=st->li; + st->elwid=st->lwid; + st->elpu=st->lpu; + st->egridx=st->gridx; + st->egridy=st->gridy; + + /* create new erase order */ + for (st->li=1; st->li<=st->eli; st->li++) + st->eline[st->li].deo=(_getdeo(st,st->eline[st->li].x,st->eline[st->li].y,st->emap,0) + (random()%st->evar) + (random()%st->evar))*st->edir; + qsort(st->eline, st->eli+1, sizeof(struct lineStruct), _comparedeo); + } + st->ii++; + + /* clear arrays and other counters */ + st->di=st->ei=st->fi=st->li=st->oi=st->zi=0; + st->grid_full=False; + /* li starts from 1 */ + st->dline[0].x=st->dline[0].y=st->dline[0].len=0; + /* to keep it first after sorting so di is never null */ + st->dline[0].deo=-999999999; + + /* set random screen variables */ + st->lwid = (st->ii==1) ? 3 : 2+((random()%6)%4); + st->d3d = ((st->tile==TILE_FLAT) || (st->tile==TILE_THIN) || + (st->tile==TILE_OUTLINE)) ? D3D_NONE : + (st->tile==TILE_BLOCK) ? D3D_BLOCK : + (st->tile==TILE_NEON) ? D3D_NEON : + (st->tile==TILE_TILED) ? D3D_TILED : + /* force TILE_D3D on first screen to properly load all shades */ + ((st->ii==1) && (!st->newcols)) ? D3D_TILED : (random()%5)%4; +/* st->d3d=D3D_BLOCK; st->lwid=2; */ + st->outline = (st->tile==TILE_OUTLINE) ? 1 : + ((st->tile!=TILE_RANDOM) || (random()%5)) ? 0 : 1; + st->round = (st->d3d==D3D_NEON) ? 1 : + ((st->d3d==D3D_BLOCK) || (st->outline) || (random()%6)) ? 0 : 1; + if ((st->d3d) || (st->outline) || (st->round)) + st->lwid+=2; + if ((!st->d3d) && (!st->round) && (!st->outline) && (st->lwid>3)) + st->lwid-=2; + if (st->d3d==D3D_TILED) + st->lwid++; + if (st->tile==TILE_THIN) + st->lwid=2; + + _init_zlist(st); + + st->maxlen=(st->lwid>6) ? 2+(random()%4) : + (st->lwid>4) ? 2+(random()%8)%6 : + (st->lwid>2) ? 2+(random()%12)%8 : 2+(random()%15)%10; + st->bnratio = 4+(random()%4)+(random()%4); + st->forcemax = (random()%6) ? 0 : 1; + + if ((st->ii==1) || (st->newcols)) + _init_colors(st); + + st->dmap = (st->emap+5+(random()%5))%DRAWORDERS; + + st->dmap=20+random()%20; + + st->dvar = (st->dmap>22) ? 100 : 10+(st->csw[0]*(random()%5)); + st->ddir= (random()%2) ? 1 : -1; + + st->emap = (st->dmap+10+(random()%10))%20; + st->evar = (st->emap>22) ? 100 : 10+(st->csw[0]*(random()%5)); + st->edir= (random()%2) ? 1 : -1; + + st->layers= (random()%2) ? 2 : (random()%2) ? 1 : (random()%2) ? 3 : 4; + st->cmap=(st->cmap+5+(random()%10))%COLORMAPS; + + for (x=0; xpattern[x]=random()%PATTERNS; + st->shape[x]=random()%SHAPES; + st->mix[x]=random()%20; + nstr = (st->lwid==2) ? 20+random()%12 : + (st->lwid==3) ? 16+random()%8 : + (st->lwid==4) ? 12+random()%6 : + (st->lwid==5) ? 10+random()%5 : + (st->lwid==6) ? 8+random()%4 : + 5+random()%5; + st->csw[x] = _max(5,st->gridy/nstr); + st->wsx[x] = (st->wsx[x]+3+(random()%3))%STRETCHES; + st->wsy[x] = (st->wsy[x]+3+(random()%3))%STRETCHES; + st->sec[x] = random()%5; + if ((!st->dialog) && (st->sec[x]<2)) st->csw[x]/=2; + st->cs1[x] = (st->dialog) ? 1+random()%3 : 2+random()%5; + st->cs2[x] = (st->dialog) ? 1+random()%3 : 2+random()%5; + st->cs3[x] = (st->dialog) ? 1+random()%3 : 2+random()%5; + st->cs4[x] = (st->dialog) ? 1+random()%3 : 2+random()%5; + st->wave[x]=random()%WAVES; + st->wavel[x]=st->csw[x]*(2+random()%6); + st->waveh[x]=st->csw[x]*(1+random()%3); + st->rx1[x]=(st->gridx/10+random()%(st->gridx*8/10)); + st->ry1[x]=(st->gridy/10+random()%(st->gridy*8/10)); + st->rx2[x]=(st->gridx*2/10+random()%(st->gridx*6/10)); + st->ry2[x]=(st->gridy*2/10+random()%(st->gridy*6/10)); + st->rx3[x]=(st->gridx*3/10+random()%(st->gridx*4/10)); + st->ry3[x]=(st->gridy*3/10+random()%(st->gridy*4/10)); + } +} + +static int +_shape(struct state *st, int x, int y, int rx, int ry, int n) +{ + switch(st->shape[n]) { + case 0: /* square/rectangle */ + case 1: + case 2: + return(1+_max(abs(x-rx)*st->cs1[n]/st->cs2[n],abs(y-ry)*st->cs3[n]/st->cs4[n])); + case 3: /* diamond */ + case 4: + return(1+(abs(x-rx)*st->cs1[n]/st->cs2[n]+abs(y-ry)*st->cs3[n]/st->cs4[n])); + case 5: /* 8 point star */ + return(1+_min(_max(abs(x-rx),abs(y-ry))*3/2,abs(x-rx)+abs(y-ry))); + case 6: /* circle/oval */ + case 7: + case 8: + return(1+_dist(st,x,rx,y,ry,st->cs1[n])); + case 9: /* black hole circle */ + return(1+(st->gridx*st->gridy/(1+(_dist(st,x,rx,y,ry,st->cs2[n]))))); + case 10: /* sun */ + return(1+_min(abs(x-rx)*st->gridx/(abs(y-ry)+1),abs(y-ry)*st->gridx/(abs(x-rx)+1))); + case 11: /* 2 circles+inverted circle */ + return(1+(_dist(st,x,rx,y,ry,st->cs1[n])*_dist(st,x,(rx*3)%st->gridx,y,(ry*5)%st->gridy,st->cs1[n])/(1+_dist(st,x,(rx*4)%st->gridx,y,(ry*7)%st->gridy,st->cs1[n])))); + case 12: /* star */ + return(1+(int)sqrt(abs((x-rx)*(y-ry)))); + case 13: /* centered ellipse */ + return(1+_dist(st,x,rx,y,ry,0)+_dist(st,x,st->gridx-rx,y,st->gridy-ry,0)); + default: /* triangle */ + return(1+_triangle(st,x,y,rx,ry,st->cs4[n])); + } + return(1+_triangle(st,x,y,rx,ry,st->cs4[n])); +} + +static int +_pattern(struct state *st, int x, int y, int n) +{ + int v=0, ox; + ox=x; + switch(st->wsx[n]) { + case 0: /* slants */ + x+=y/(1+st->cs4[n]); + break; + case 1: + x+=(st->gridy-y)/(1+st->cs4[n]); + break; + case 2: /* curves */ + x+=_wave(st,y,st->gridx/(1+st->cs1[n]),st->gridy,0); + break; + case 3: + x+=_wave(st,st->gridy-y,st->gridy/(1+st->cs1[n]),st->gridy,0); + break; + case 4: /* U curves */ + x+=_wave(st,y,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0); + break; + case 5: + x-=_wave(st,y,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0); + break; + } + switch(st->wsy[0]) { + case 0: /* slants */ + y+=ox/(1+st->cs1[n]); + break; + case 1: + y+=(st->gridx-ox)/(1+st->cs1[n]); + break; + case 2: /* curves */ + y+=_wave(st,ox,st->gridx/(1+st->cs1[n]),st->gridx,0); + break; + case 3: + y+=_wave(st,st->gridx-ox,st->gridx/(1+st->cs1[n]),st->gridx,0); + break; + case 4: /* U curves */ + y+=_wave(st,ox,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0); + break; + case 5: + y-=_wave(st,ox,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0); + break; + } + switch(st->pattern[n]) { + case 0: /* horizontal stripes */ + v=y; + break; + case 1: /* vertical stripes */ + v=x; + break; + case 2: /* diagonal stripes */ + v=(x+(y*st->cs1[n]/st->cs2[n])); + break; + case 3: /* reverse diagonal stripes */ + v=(x-(y*st->cs1[n]/st->cs2[n])); + break; + case 4: /* checkerboard */ + v=(y/st->csw[n]*3+x/st->csw[n])*st->csw[n]; + break; + case 5: /* diagonal checkerboard */ + v=((x+y)/2/st->csw[n]+(x+st->gridy-y)/2/st->csw[n]*3)*st->csw[n]; + break; + case 6: /* + cross */ + v=st->gridx+(_min(abs(x-st->rx3[n]),abs(y-st->ry3[n]))*2); + break; + case 7: /* double + cross */ + v=_min(_min(abs(x-st->rx2[n]),abs(y-st->ry2[n])),_min(abs(x-st->rx1[n]),abs(y-st->ry1[n])))*2; + break; + case 8: /* X cross */ + v=st->gridx+(_min(abs(x-st->rx3[n])*st->cs1[n]/st->cs2[n]+abs(y-st->ry2[n])*st->cs3[n]/st->cs4[n],abs(x-st->rx3[n])*st->cs1[n]/st->cs2[n]-abs(y-st->ry3[n])*st->cs3[n]/st->cs4[n])*2); + break; + case 9: /* double X cross */ + v=_min(_min(abs(x-st->rx2[n])+abs(y-st->ry2[n]),abs(x-st->rx2[n])-abs(y-st->ry2[n])),_min(abs(x-st->rx1[n])+abs(y-st->ry1[n]),abs(x-st->rx1[n])-abs(y-st->ry1[n])))*2; + break; + case 10: /* horizontal stripes/waves */ + v=st->gridy+(y+_wave(st,x,st->waveh[n],st->wavel[n],st->wave[n])); + break; + case 11: /* vertical stripes/waves */ + v=st->gridx+(x+_wave(st,y,st->waveh[n],st->wavel[n],st->wave[n])); + break; + case 12: /* diagonal stripes/waves */ + v=st->gridx+(x+(y*st->cs1[n]/st->cs2[n])+_wave(st,x,st->waveh[n],st->wavel[n],st->wave[n])); + break; + case 13: /* diagonal stripes/waves */ + v=st->gridx+(x-(y*st->cs1[n]/st->cs2[n])+_wave(st,y,st->waveh[n],st->wavel[n],st->wave[n])); + break; + case 14: /* horizontal spikey waves */ + v=y+(st->csw[n]*st->cs4[n]/st->cs3[n])+_wave(st,x+((y/st->cs3[n])*st->edir),st->csw[n]/2*st->cs1[n]/st->cs2[n],st->csw[n]/2*st->cs2[n]/st->cs1[n],st->wave[n]); + break; + case 15: /* vertical spikey waves */ + v=x+(st->csw[n]*st->cs1[n]/st->cs2[n])+_wave(st,y+((x/st->cs3[n])*st->edir),st->csw[n]/2*st->cs1[n]/st->cs2[n],st->csw[n]/2*st->cs3[n]/st->cs4[n],st->wave[n]); + break; + case 16: /* big slanted hwaves */ + v=st->gridy-y-(x*st->cs1[n]/st->cs3[n])+(st->csw[n]*st->cs1[n]*st->cs2[n]) +_wave(st,x,st->csw[n]/3*st->cs1[n]*st->cs2[n],st->csw[n]/3*st->cs3[n]*st->cs2[n],st->wave[n]); + break; + case 17: /* big slanted vwaves */ + v=x-(y*st->cs1[n]/st->cs3[n])+(st->csw[n]*st->cs1[n]*st->cs2[n]) +_wave(st,y, st->csw[n]/3*st->cs1[n]*st->cs2[n], st->csw[n]/3*st->cs3[n]*st->cs2[n], st->wave[n]); + break; + case 18: /* double hwave */ + v=y+(y+st->csw[n]*st->cs3[n])+_wave(st,x,st->csw[n]/3*st->cs3[n],st->csw[n]/3*st->cs2[n],st->wave[n])+_wave(st,x,st->csw[n]/3*st->cs4[n],st->csw[n]/3*st->cs1[n]*3/2,st->wave[n]); + break; + case 19: /* double vwave */ + v=x+(x+st->csw[n]*st->cs1[n])+_wave(st,y,st->csw[n]/3*st->cs1[n],st->csw[n]/3*st->cs3[n],st->wave[n])+_wave(st,y,st->csw[n]/3*st->cs2[n],st->csw[n]/3*st->cs4[n]*3/2,st->wave[n]); + break; + case 20: /* one shape */ + case 21: + case 22: + v=_shape(st,x, y, st->rx3[n], st->ry3[n], n); + break; + case 23: /* two shapes */ + case 24: + case 25: + v=_min(_shape(st,x, y, st->rx1[n], st->ry1[n], n),_shape(st,x, y, st->rx2[n], st->ry2[n], n)); + break; + case 26: /* two shapes opposites */ + case 27: + v=_min(_shape(st,x, y, st->rx2[n], st->ry2[n], n),_shape(st,x, y, st->gridx-st->rx2[n], st->gridy-st->rx2[n], n)); + break; + case 28: /* two shape checkerboard */ + case 29: + v=((_shape(st,x, y, st->rx1[n], st->ry1[n], n)/st->csw[n])+(_shape(st,x, y, st->rx2[n], st->ry2[n], n)/st->csw[n]))*st->csw[n]; + break; + case 30: /* two shape blob */ + case 31: + v=(_shape(st,x, y, st->rx1[n], st->ry1[n], n)+_shape(st,x, y, st->rx2[n], st->ry2[n], n))/2; + break; + case 32: /* inverted two shape blob */ + case 33: + v=(_shape(st,x, y, st->rx1[n], st->ry1[n], n)+_shape(st,st->gridx-x, st->gridy-y, st->rx1[n], st->ry1[n], n))/2; + break; + case 34: /* three shapes */ + case 35: + v=_min(_shape(st,x, y, st->rx3[n], st->ry3[n], n),_min(_shape(st,x, y, st->rx1[n], st->ry1[n], n),_shape(st,x, y, st->rx2[n], st->ry2[n], n))); + break; + case 36: /* three shape blob */ + case 37: + v=(_shape(st,x, y, st->rx1[n], st->ry1[n], n)+_shape(st,x, y, st->rx2[n], st->ry2[n], n)+_shape(st,x, y, st->rx3[n], st->ry3[n], n))/3; + break; + case 38: /* 4 shapes */ + v=(_min(_shape(st,x, y, st->rx2[n], st->ry2[n], n),_shape(st,x, y, st->gridx-st->rx2[n], st->gridy-st->ry2[n], n)),_min(_shape(st,x, y, st->gridx-st->rx2[n], st->ry2[n], n),_shape(st,x, y, st->rx2[n], st->gridy-st->ry2[n], n))); + break; + case 39: /* four rainbows */ + v=(_min(_shape(st,x, y, st->gridx-st->rx2[n]/2, st->csw[n], n),_shape(st,x, y, st->csw[n], st->ry2[n]/2, n)),_min(_shape(st,x, y, st->rx2[n]/2, st->gridy-st->csw[n], n),_shape(st,x, y, st->gridx-st->csw[n], st->gridy-(st->ry2[n]/2), n))); + break; + } + /* stretch or contract stripe */ + switch(st->sec[n]) { + case 0: + v=(int)sqrt((int)sqrt(abs(v)*st->gridx)*st->gridx); + break; + case 1: + v=((int)pow(v,2)/st->gridx); + break; + } + return (abs(v)); +} + +static int +_getcolor(struct state *st, int x, int y) +{ + int n, cv[LAYERS]; + + cv[0] = 0; + for (n=0; nlayers; n++) { + cv[n]=_pattern(st,x,y,n); + /* first wave/shape */ + cv[0] = (!n) ? cv[0]/st->csw[0] : + /* checkerboard+1 */ + (st->mix[n]<5) ? (cv[0]*st->csw[0]+cv[n])/st->csw[n] : + /* checkerboard+ncol/2 */ + (st->mix[n]<12) ? cv[0]+(cv[n]/st->csw[n]*st->ncolors/2) : + /* add mix */ + (st->mix[n]<16) ? cv[0]+(cv[n]/st->csw[n]) : + /* subtract mix */ + (st->mix[n]<18) ? cv[0]-(cv[n]/st->csw[n]) : + /* r to l morph mix */ + (st->mix[n]==18) ? ((cv[0]*x)+(cv[n]*(st->gridx-x)/st->csw[n]))/st->gridx : + /* u to d morph mix */ + ((cv[0]*y)+(cv[n]*(st->gridy-y)/st->csw[n]))/st->gridy; + } + return(cv[0]); +} + +/* return value=line direction + st->olen=open space to edge or next blocking line + st->bln=blocking line number or -1 if edge blocks */ +static int +_findopen(struct state *st, int x, int y, int z) +{ + int dir, od[4], no=0; + + if (((st->grid[z].hl) || (st->grid[z].hr)) && + ((st->grid[z].vu) || (st->grid[z].vd))) + return(DIR_NONE); + if ((z>st->gridx) && (!st->grid[z].hl) && (!st->grid[z].hr) && + (!st->grid[z-st->gridx].line)) { + od[no]=DIR_UP; + no++; + } + if ((zgridn-st->gridx) && (!st->grid[z].hl) && + (!st->grid[z].hr) && (!st->grid[z+st->gridx].line)) { + od[no]=DIR_DOWN; + no++; + } + if ((x) && (!st->grid[z].hl) && (!st->grid[z].hr) && + (!st->grid[z-1].line)) { + od[no]=DIR_LEFT; + no++; + } + if (((z+1)%st->gridx) && (!st->grid[z].hl) && (!st->grid[z].hr) && + (!st->grid[z+1].line)) { + od[no]=DIR_RIGHT; + no++; + } + if (!no) + return(DIR_NONE); + dir=od[random()%no]; + st->olen=st->bln=0; + while ((st->olen<=st->maxlen) && (!st->bln)) { + st->olen++; + if (dir==DIR_UP) + st->bln = (y-st->olen<0) ? -1 : + st->grid[z-(st->olen*st->gridx)].line; + if (dir==DIR_DOWN) + st->bln = (y+st->olen>=st->gridy) ? -1 : + st->grid[z+(st->olen*st->gridx)].line; + if (dir==DIR_LEFT) + st->bln = (x-st->olen<0) ? -1 : + st->grid[z-st->olen].line; + if (dir==DIR_RIGHT) + st->bln = (x+st->olen>=st->gridx) ? -1 : + st->grid[z+st->olen].line; + } + st->olen--; + return(dir); +} + +static void +_fillgrid(struct state *st) +{ + unsigned int gridc, n, add; + + gridc=st->gridx*st->dline[st->li].y+st->dline[st->li].x; + add = (st->dline[st->li].hv) ? 1 : st->gridx; + for (n=0; n<=st->dline[st->li].len; n++) { + if (n) + gridc+=add; + if (!st->grid[gridc].line) { + st->fi++; + st->grid[gridc].line=st->li; + } + if (st->dline[st->li].hv) { + if (n) + st->grid[gridc].hr=st->li; + if (ndline[st->li].len) + st->grid[gridc].hl=st->li; + } else { + if (n) + st->grid[gridc].vd=st->li; + if (ndline[st->li].len) + st->grid[gridc].vu=st->li; + } + if (st->fi>=st->gridn) { + st->grid_full=True; + return; + } + } +} + +static void +_newline(struct state *st) +{ + int bl, bz, dir, lt, x, y, z; + + bl=0; + z=st->zlist[st->zi]; + x=z%st->gridx; + y=z/st->gridx; + st->zi++; + dir=_findopen(st,x,y,z); + + if (!st->grid[z].line) { + /* this is an empty space, make a new line unless nothing is open around it */ + if (dir==DIR_NONE) { + /* nothing is open, force a len 1 branch in any direction */ + lt=LINE_FORCE; + while ((dir==DIR_NONE) || + ((dir==DIR_UP) && (!y)) || + ((dir==DIR_DOWN) && (y+1==st->gridy)) || + ((dir==DIR_LEFT) && (!x)) || + ((dir==DIR_RIGHT) && (x+1==st->gridx))) { + dir=random()%4; + } + bz = (dir==DIR_UP) ? z-st->gridx : (dir==DIR_DOWN) ? z+st->gridx : (dir==DIR_LEFT) ? z-1 : z+1; + bl = st->grid[bz].line; + } else if ((st->bnratio>1) && (st->bln>0) && + (st->olenmaxlen) && (random()%st->bnratio)) { + /* branch into blocking line */ + lt=LINE_BRIN; + bl = st->bln; + } else { + /* make a new line and new object */ + lt=LINE_NEW; + st->oi++; + } + } else { + /* this is a filled space, make a branch unless nothing is open around it */ + if (dir==DIR_NONE) + return; + /* make a branch out of this line */ + lt=LINE_BROUT; + bl=st->grid[z].line; + } + st->li++; + st->dline[st->li].len = (lt==LINE_FORCE) ? 1 : (lt==LINE_BRIN) ? + st->olen+1 : (!st->forcemax) ? st->olen : 1+random()%st->olen; + st->dline[st->li].x=x; + if (dir==DIR_LEFT) + st->dline[st->li].x-=st->dline[st->li].len; + st->dline[st->li].y=y; + if (dir==DIR_UP) + st->dline[st->li].y-=st->dline[st->li].len; + st->dline[st->li].hv = ((dir==DIR_LEFT) || (dir==DIR_RIGHT)) ? + True : False; + st->dline[st->li].obj = (lt==LINE_NEW) ? st->oi : + st->dline[bl].obj; + if (lt==LINE_NEW) { + int color = (_getcolor(st,x,y))%st->ncolors; + if (color < 0) color += st->ncolors; + st->dline[st->li].color = color; + } else { + st->dline[st->li].color = st->dline[bl].color; + } + st->dline[st->li].deo=(_getdeo(st,x,y,st->dmap,1) + + (random()%st->dvar) + (random()%st->dvar))*st->ddir; + st->dline[st->li].ndol=0; + _fillgrid(st); +} + +static void +_create_screen(struct state *st) +{ + while(!st->grid_full) + _newline(st); + qsort(st->dline, st->li+1, sizeof(struct lineStruct), _comparedeo); +/*st->lpu=st->li/20/((6-st->speed)*3); + Used to use a computed lpu, lines per update to control draw speed + draw 1/lpu of the lines before each XSync which takes a split second + the higher the lpu, the quicker the screen draws. This worked somewhat + after the 4->5 update, however with the Mac updating so much more slowly, + values tuned for it draw the screen in a blink on Linux. Therefore we + draw 1/200th of the screen with each update and sleep, if necessary */ + st->lpu = (st->dialog) ? st->li/50 : st->li/200; + if (!st->lpu) st->lpu = 1; + st->bi=1; + st->mode=MODE_ERASE; +} + +static void +_fill_outline(struct state *st, int di) +{ + int x, y, h, w; + + if (!di) + return; + x=st->dline[di].x*st->lwid+1; + y=st->dline[di].y*st->lwid+1; + if (st->dline[di].hv) { + w=(st->dline[di].len+1)*st->lwid-3; + h=st->lwid-3; + } else { + w=st->lwid-3; + h=(st->dline[di].len+1)*st->lwid-3; + } + XFillRectangle (st->display, st->window, st->bgc, x, y, w, h); +} + +static void +_XFillRectangle(struct state *st, int di, int adj) +{ + int a, b, x, y, w, h; + + x=st->dline[di].x*st->lwid; + y=st->dline[di].y*st->lwid; + if (st->dline[di].hv) { + w=(st->dline[di].len+1)*st->lwid-1; + h=st->lwid-1; + } else { + w=st->lwid-1; + h=(st->dline[di].len+1)*st->lwid-1; + } + switch (st->d3d) { + case D3D_NEON: + x+=adj; + y+=adj; + w-=adj*2; + h-=adj*2; + break; + case D3D_BLOCK: + x+=adj; + y+=adj; + w-=st->lwid/2-1; + h-=st->lwid/2-1; + break; + } + if (!st->round) { + XFillRectangle(st->display, st->window, st->fgc, x, y, w, h); + } else { + if (hlwid) { /* horizontal */ + a=(h-1)/2; + for (b=0; b<=a; b++) + XFillRectangle(st->display, st->window, st->fgc, + x+b, y+a-b, w-b*2, h-((a-b)*2)); + } else { /* vertical */ + a=(w-1)/2; + for (b=0; b<=a; b++) + XFillRectangle(st->display, st->window, st->fgc, + x+a-b, y+b, w-((a-b)*2), h-b*2); + } + } +} + +static void +_XFillTriangle(struct state *st, int color, int x1, int y1, int x2, int y2, + int x3, int y3) +{ + XPoint points[3]; + + points[0].x=x1; + points[0].y=y1; + points[1].x=x2; + points[1].y=y2; + points[2].x=x3; + points[2].y=y3; + XSetForeground(st->display, st->fgc, st->colors[color].pixel); + XFillPolygon (st->display, st->window, st->fgc, points, 3, Convex, + CoordModeOrigin); +} + +static void +_XFillPolygon4(struct state *st, int color, int x1, int y1, int x2, int y2, + int x3, int y3, int x4, int y4) +{ + XPoint points[4]; + + points[0].x=x1; + points[0].y=y1; + points[1].x=x2; + points[1].y=y2; + points[2].x=x3; + points[2].y=y3; + points[3].x=x4; + points[3].y=y4; + XSetForeground(st->display, st->fgc, st->colors[color].pixel); + XFillPolygon (st->display, st->window, st->fgc, points, 4, Convex, + CoordModeOrigin); +} + +static void +_draw_tiled(struct state *st, int color) +{ + int a, c, d, x, y, z, m1, m2, lr, nl, w, h; + a = (st->dline[st->di].hv) ? 1 : st->gridx; + z = st->dline[st->di].y*st->gridx+st->dline[st->di].x; + m1 = (st->lwid-1)/2; + m2 = st->lwid/2; + lr = st->lwid-1; + nl = st->lwid; + + /* draw tiles one grid cell at a time */ + for (c=0; c<=st->dline[st->di].len; c++) { + if (st->dline[st->di].hv) { + x = (st->dline[st->di].x+c)*st->lwid; + y = st->dline[st->di].y*st->lwid; + if (c) + st->grid[z].dhr=st->di; + if (cdline[st->di].len) + st->grid[z].dhl=st->di; + } else { + x = st->dline[st->di].x*st->lwid; + y = (st->dline[st->di].y+c)*st->lwid; + if (c) + st->grid[z].dvd=st->di; + if (cdline[st->di].len) + st->grid[z].dvu=st->di; + } + d=0; + if (st->grid[z].dhl) + d+=8; + if (st->grid[z].dhr) + d+=4; + if (st->grid[z].dvu) + d+=2; + if (st->grid[z].dvd) + d++; + /* draw line base */ + switch (d) { + case 1: + case 2: /* vertical */ + case 3: + case 5: + case 6: + case 7: + case 11: + case 15: + h = ((d==1) || (d==5)) ? lr : nl; + XSetForeground(st->display, st->fgc, + st->colors[color].pixel); + XFillRectangle (st->display, st->window, st->fgc, + x, y, m2, h); + XSetForeground(st->display, st->fgc, + st->colors[color+3].pixel); + XFillRectangle (st->display, st->window, st->fgc, + x+m2, y, m1, h); + break; + case 4: + case 8: /* horizontal */ + case 9: + case 10: + case 12: + case 13: + case 14: + w = (d==4) ? lr : nl; + XSetForeground(st->display, st->fgc, + st->colors[color+1].pixel); + XFillRectangle (st->display, st->window, st->fgc, + x, y, w, m2); + XSetForeground(st->display, st->fgc, + st->colors[color+2].pixel); + XFillRectangle (st->display, st->window, st->fgc, + x, y+m2, w, m1); + break; + } + /* draw angles */ + switch(d) { + case 1: /* bottom end ^ */ + _XFillTriangle(st,color+2, x, y+lr, x+lr, y+lr, x+m2, y+m2); + break; + case 2: /* top end \/ */ + _XFillTriangle(st,color+1, x, y, x+lr, y, x+m2, y+m2); + break; + case 4: /* right end < */ + _XFillTriangle(st,color+3, x+lr, y, x+lr, y+lr, x+m2, y+m2); + break; + case 5: /* LR corner */ + _XFillTriangle(st,color+1, x, y+m2, x+m2, y+m2, x, y); + _XFillPolygon4(st,color+2, x, y+m2, x+m2, y+m2, x+lr, y+lr, x, y+lr); + break; + case 6: /* UR corner */ + _XFillPolygon4(st,color+1, x, y+m2, x+m2, y+m2, x+lr, y, x, y); + _XFillTriangle(st,color+2, x, y+m2, x+m2, y+m2, x, y+lr); + break; + case 7: /* T > into line */ + _XFillTriangle(st,color+1, x, y+m2, x+m2, y+m2, x, y); + _XFillTriangle(st,color+2, x, y+m2, x+m2, y+m2, x, y+lr); + break; + case 8: /* left end > */ + _XFillTriangle(st,color, x, y, x, y+lr, x+m2, y+m2); + break; + case 9: /* LL corner */ + _XFillPolygon4(st,color, x+m2, y, x+m2, y+m2, x, y+lr, x, y); + _XFillTriangle(st,color+3, x+m2, y, x+m2, y+m2, x+lr, y); + break; + case 10: /* UL corner */ + _XFillPolygon4(st,color, x+m2, y+nl, x+m2, y+m2, x, y, x, y+nl); + _XFillPolygon4(st,color+3, x+m2, y+nl, x+m2, y+m2, x+lr, y+lr, x+lr, y+nl); + break; + case 11: /* T < into line */ + _XFillPolygon4(st,color+1, x+nl, y+m2, x+m2, y+m2, x+lr, y, x+nl, y); + _XFillPolygon4(st,color+2, x+nl, y+m2, x+m2, y+m2, x+lr, y+lr, x+nl, y+lr); + break; + case 13: /* T \/ into line */ + _XFillTriangle(st,color, x+m2, y, x+m2, y+m2, x, y); + _XFillTriangle(st,color+3, x+m2, y, x+m2, y+m2, x+lr, y); + break; + case 14: /* T ^ into line */ + _XFillPolygon4(st,color, x+m2, y+nl, x+m2, y+m2, x, y+lr, x, y+nl); + _XFillPolygon4(st,color+3, x+m2, y+nl, x+m2, y+m2, x+lr, y+lr, x+lr, y+nl); + break; + case 15: /* X intersection */ + _XFillTriangle(st,color+1, x, y+m2, x+m2, y+m2, x, y); + _XFillTriangle(st,color+2, x, y+m2, x+m2, y+m2, x, y+lr); + _XFillPolygon4(st,color+1, x+nl, y+m2, x+m2, y+m2, x+lr, y, x+nl, y); + _XFillPolygon4(st,color+2, x+nl, y+m2, x+m2, y+m2, x+lr, y+lr, x+nl, y+lr); + break; + } + z+=a; + } +} + +static long +_mselapsed(struct state *st) +{ + struct timeval t; + gettimeofday(&t, NULL); + t.tv_sec -= st->time.tv_sec; + t.tv_usec -= st->time.tv_usec; + return ((long)t.tv_sec*1000000+t.tv_usec); +} + +static void +_draw_lines(struct state *st) +{ + int n, z, a, color, sh, di; + if (st->bi==1) + for (a=0; a<=st->oi; a++) + st->fdol[a]=0; + + for (st->di=st->bi; st->di<_min(st->li+1,st->bi+st->lpu); st->di++) { + color=(st->dline[st->di].color%st->ncolors)*st->shades; + XSetForeground(st->display, st->fgc, st->colors[color].pixel); + + switch (st->d3d) { + case D3D_NEON: + st->dline[st->di].ndol=st->fdol[st->dline[st->di].obj]; + st->fdol[st->dline[st->di].obj]=st->di; + for (sh=0; shlwid/2; sh++) { + XSetForeground(st->display, st->fgc, + st->colors[color+sh].pixel); + di=st->di; + while(di>0) { + _XFillRectangle(st,di,sh); + di=st->dline[di].ndol; + } + } + break; + case D3D_BLOCK: + st->dline[st->di].ndol=st->fdol[st->dline[st->di].obj]; + st->fdol[st->dline[st->di].obj]=st->di; + for (sh=0; shlwid/2; sh++) { + XSetForeground(st->display, st->fgc, + st->colors[color+(st->lwid/2)-sh-1].pixel); + di=st->di; + while(di>0) { + _XFillRectangle(st,di,sh); + di=st->dline[di].ndol; + } + } + break; + case D3D_TILED: + _draw_tiled(st,color); + break; + default: /* D3D_NONE */ + _XFillRectangle(st,st->di,0); + if (st->outline) { + _fill_outline(st, st->di); + z=st->dline[st->di].y*st->gridx+st->dline[st->di].x; + a = (st->dline[st->di].hv) ? 1 : st->gridx; + for (n=0; n<=st->dline[st->di].len; n++) { + _fill_outline(st, st->grid[z].dhl); + _fill_outline(st, st->grid[z].dhr); + _fill_outline(st, st->grid[z].dvu); + _fill_outline(st, st->grid[z].dvd); + if (st->dline[st->di].hv) { + if (n) + st->grid[z].dhr=st->di; + if (ndline[st->di].len) + st->grid[z].dhl=st->di; + } else { + if (n) + st->grid[z].dvd=st->di; + if (ndline[st->di].len) + st->grid[z].dvu=st->di; + } + z+=a; + } + } + break; + } + } + if (st->di>st->li) { + st->bi=1; + st->mode=MODE_CREATE; + } else { + st->bi+=st->lpu; + } +} + +static void +_erase_lines(struct state *st) +{ + if (!st->ii) + return; + for (st->di=st->bi; st->di<_min(st->eli+1,st->bi+st->elpu); st->di++) { + if (st->eline[st->di].hv) { + XFillRectangle (st->display, st->window, st->bgc, + st->eline[st->di].x*st->elwid, + st->eline[st->di].y*st->elwid, + (st->eline[st->di].len+1)*st->elwid, st->elwid); + } else { + XFillRectangle (st->display, st->window, st->bgc, + st->eline[st->di].x*st->elwid, + st->eline[st->di].y*st->elwid, + st->elwid, (st->eline[st->di].len+1)*st->elwid); + } + if (st->di==st->eli) /* clear just in case */ + XFillRectangle(st->display, st->window, st->bgc, 0, 0, + st->xgwa.width, st->xgwa.height); + } + if (st->di>st->eli) { + st->bi=1; + if (st->resized) { + st->mode=MODE_CREATE; + } else { + st->mode=MODE_DRAW; + } + } else { + st->bi+=st->elpu; + } +} + +static void * +abstractile_init(Display *display, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; +/* struct utsname os;*/ + + char *tile = get_string_resource(display, "tile", "Tile"); + if (tile && !strcmp(tile, "random")) st->tile = TILE_RANDOM; + else if (tile && !strcmp(tile, "flat")) st->tile = TILE_FLAT; + else if (tile && !strcmp(tile, "thin")) st->tile = TILE_THIN; + else if (tile && !strcmp(tile, "outline")) st->tile = TILE_OUTLINE; + else if (tile && !strcmp(tile, "block")) st->tile = TILE_BLOCK; + else if (tile && !strcmp(tile, "neon")) st->tile = TILE_NEON; + else if (tile && !strcmp(tile, "tiled")) st->tile = TILE_TILED; + else { + if (tile && *tile && !!strcmp(tile, "random")) + fprintf(stderr, "%s: unknown tile option %s\n", progname, tile); + st->tile = TILE_RANDOM; + } + + st->speed = get_integer_resource(display, "speed", "Integer"); + if (st->speed < 0) st->speed = 0; + if (st->speed > 5) st->speed = 5; + st->sleep = get_integer_resource(display, "sleep", "Integer"); + if (st->sleep < 0) st->sleep = 0; + if (st->sleep > 60) st->sleep = 60; + + st->display=display; + st->window=window; + + /* get screen size and create Graphics Contexts */ + XGetWindowAttributes (display, window, &st->xgwa); + gcv.foreground = get_pixel_resource(display, st->xgwa.colormap, + "foreground", "Foreground"); + st->fgc = XCreateGC (display, window, GCForeground, &gcv); + gcv.foreground = get_pixel_resource(display, st->xgwa.colormap, + "background", "Background"); + st->bgc = XCreateGC (display, window, GCForeground, &gcv); + +/* Um, no. This is obscene. -jwz. + uname(&os); + st->newcols=((!strcmp(os.sysname,"Linux")) || (!strcmp(os.sysname,"Darwin"))) + ? True : False; +*/ + st->newcols=False; + + st->mode=MODE_CREATE; + st->ii=0; + st->resized=True; + return st; +} + +static unsigned long +abstractile_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int mse, usleep; + + gettimeofday(&st->time, NULL); + + /* If the window is too small, do nothing, sorry! */ + if (st->xgwa.width > 20 && st->xgwa.height > 20) { + switch (st->mode) { + case MODE_CREATE: + _init_screen(st); + _create_screen(st); + break; + case MODE_ERASE: + _erase_lines(st); + break; + case MODE_DRAW: + _draw_lines(st); + break; + } + } + mse=_mselapsed(st); + usleep = ((!st->ii) && (st->mode==MODE_CREATE)) ? 0 : + (st->mode==MODE_CREATE) ? st->sleep*1000000-mse : + /* speed=0-5, goal is 10,8,6,4,2,0 sec normal and 5,4,3,2,1,0 dialog */ + (5-st->speed)*(2-st->dialog)*100000/st->lpu-mse; + if (usleep>=0) + return usleep; + return 0; +} + +static void +abstractile_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + st->xgwa.width = w; + st->xgwa.height = h; + if (w*h>st->max_wxh) + st->resized=True; +} + +static Bool +abstractile_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (screenhack_event_helper (dpy, window, event)) + { + st->mode=MODE_CREATE; + return True; + } + + return False; +} + +static void +abstractile_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + +static const char *abstractile_defaults [] = { + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*sleep: 3", + "*speed: 3", + "*tile: random", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec abstractile_options [] = { + { "-sleep", ".sleep", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-tile", ".tile", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Abstractile", abstractile) -- cgit v1.2.3-55-g7522