2 * Copyright (c) 2004-2009 Steve Sundstrom
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 #include "screenhack.h"
19 /*#include <sys/utsname.h>*/
21 #define MODE_CREATE 0 /* init, create, then finish sleep */
22 #define MODE_ERASE 1 /* erase, then reset colors */
49 #define TILE_OUTLINE 3
66 unsigned int x, y, len, obj, color, ndol;
72 unsigned int line, hl, hr, vu, vd, dhl, dhr, dvu, dvd;
75 /* basically the same as global variables, but used to keep them in a bucket
76 and pass them around easier like the original C++ implementation */
81 XWindowAttributes xgwa;
86 struct lineStruct *dline, *eline;
87 struct gridStruct *grid;
88 unsigned int *zlist, *fdol;
90 /* draw, erase, fill, init, line, object, z indexes */
91 unsigned int di, ei, fi, ii, bi, li, eli, oi, zi;
93 unsigned int gridx, gridy, gridn; /* grid size */
94 int lwid, bwid, swid;/* line width, background width, shadow width */
96 int elwid, elpu, egridx, egridy; /* for now */
98 int bnratio; /* ratio of branch lines to new lines */
99 int maxlen; /* maximum length of line */
100 int forcemax; /* make line be max possible length */
101 int olen; /* open length set by findopen */
102 int bln; /* blocking line number set by findopen, -1=edge */
103 /* color variables */
104 int ncolors; /* number of colors for screen */
106 int rco[MAXCOLORS]; /* random ordering of colors for deo */
109 Bool newcols; /* can we create new colormaps with each screen */
111 int dmap, emap; /* pattern by which line draw order is determined */
112 int dvar, evar; /* random number added to .deo to vary */
113 int ddir, edir; /* draw/erase in forward direction or reverse */
114 int lpu; /* lines drawn per update used to adjust speed */
118 /* layered draw variables */
119 int pattern[LAYERS], shape[LAYERS], mix[LAYERS];
120 int csw[LAYERS], wsx[LAYERS], wsy[LAYERS], sec[LAYERS];
121 int cs1[LAYERS], cs2[LAYERS], cs3[LAYERS]; int cs4[LAYERS];
122 int wave[LAYERS], waveh[LAYERS], wavel[LAYERS];
123 int rx1[LAYERS], rx2[LAYERS], rx3[LAYERS];
124 int ry1[LAYERS], ry2[LAYERS], ry3[LAYERS];
126 int mode, sleep, speed, tile, dialog;
127 Bool grid_full, resized;
148 _dist(struct state *st, int x1, int x2, int y1, int y2, int s)
154 return((int)sqrt(xd*xd+yd*yd));
156 return((int)sqrt(xd*xd*st->cs1[0]*2+yd*yd));
158 return((int)sqrt(xd*xd+yd*yd*st->cs2[0]*2));
160 return((int)sqrt(xd*xd*st->cs1[0]/st->cs2[0]+yd*yd*st->cs3[0]/st->cs4[0]));
165 _wave(struct state *st, int x, int h, int l, int wave)
169 case 0: /* cos wave*/
170 return((int)(cos((double)x*M_PI/l)*h));
171 case 1: /* double wave*/
172 case 2: /* double wave*/
173 return((int)(cos((double)x*M_PI/l)*h)+(int)(sin((double)x*M_PI/l/st->cs1[1])*h));
174 case 3: /* zig zag */
175 return(abs((x%(l*2)-l))*h/l);
176 case 4: /* giant zig zag */
177 return(abs((x%(l*4)-l*2))*h*3/l);
178 case 5: /* sawtooth */
180 default: /* no wave */
186 _triangle(struct state *st, int x, int y, int rx, int ry, int t)
190 return(_min(_min(x+y+rx-(st->gridx/2),st->gridx-x+y),(st->gridy-y+(ry/2))*3/2));
192 return(_min(_min(x-rx,y-ry),(rx+ry-x-y)*2/3));
194 return(_min(_min(st->gridx-x-rx,y-ry),(rx+ry-st->gridx+x-y)*2/3));
196 return(_min(_min(x-rx,st->gridy-y-ry),(rx+ry-x-st->gridy+y)*2/3));
198 return(_min(_min(st->gridx-x-rx,st->gridy-y-ry),(rx+ry-st->gridx+x-st->gridy+y)*2/3));
202 _init_zlist(struct state *st)
204 unsigned int tmp, y, z;
206 st->gridx=st->xgwa.width/st->lwid;
207 st->gridy=st->xgwa.height/st->lwid;
208 st->gridn=st->gridx*st->gridy;
210 for (z=0; z<st->gridn; z++) {
211 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;
214 /* rather than pull x,y points randomly and wait to hit final empy cells a
215 list of all points is created and mixed so empty cells do get hit last */
216 for (z=0; z<st->gridn; z++) {
217 y=random()%st->gridn;
219 st->zlist[y]=st->zlist[z];
225 make_color_ramp_rgb (Screen *screen, Visual *visual, Colormap cmap,
226 int r1, int g1, int b1, int r2, int g2, int b2,
227 XColor *colors, int *ncolorsP, Bool closed_p)
230 double s1, s2, v1, v2;
231 rgb_to_hsv(r1, g1, b1, &h1, &s1, &v1);
232 rgb_to_hsv(r2, g2, b2, &h2, &s2, &v2);
233 make_color_ramp(screen, visual, cmap, h1, s1, v1, h2, s2, v2,
234 colors, ncolorsP, False, True, 0);
239 _init_colors(struct state *st)
242 int c1, c2, c3, h1, h2, h3;
243 int r1, g1, b1, r2, g2, b2, r3, g3, b3;
244 double s1, s2, s3, v1, v2, v3;
245 XColor tmp_col1[16], tmp_col2[16], tmp_col3[16];
247 unsigned short basecol[BASECOLORS][3]={
248 /* 0 dgray */ {0x3333,0x3333,0x3333},
249 /* 1 dbrown */ {0x6666,0x3333,0x0000},
250 /* 2 dred */ {0x9999,0x0000,0x0000},
251 /* 3 orange */ {0xFFFF,0x6666,0x0000},
252 /* 4 gold */ {0xFFFF,0xCCCC,0x0000},
253 /* 5 olive */ {0x6666,0x6666,0x0000},
254 /* 6 ivy */ {0x0000,0x6666,0x0000},
255 /* 7 dgreen */ {0x0000,0x9999,0x0000},
256 /* 8 bluegray */ {0x3333,0x6666,0x6666},
257 /* 9 dblue */ {0x0000,0x0000,0x9999},
258 /* 10 blue */ {0x3333,0x3333,0xFFFF},
259 /* 11 dpurple */ {0x6666,0x0000,0xCCCC},
260 /* 12 purple */ {0x6666,0x3333,0xFFFF},
261 /* 13 violet */ {0x9999,0x3333,0x9999},
262 /* 14 magenta */ {0xCCCC,0x3333,0xCCCC},
264 /* 15 gray */ {0x3333,0x3333,0x3333},
265 /* 16 brown */ {0x9999,0x6666,0x3333},
266 /* 17 tan */ {0xCCCC,0x9999,0x3333},
267 /* 18 red */ {0xFFFF,0x0000,0x0000},
268 /* 19 lorange */ {0xFFFF,0x9999,0x0000},
269 /* 20 yellow */ {0xFFFF,0xFFFF,0x0000},
270 /* 21 lolive */ {0x9999,0x9999,0x0000},
271 /* 22 green */ {0x3333,0xCCCC,0x0000},
272 /* 23 lgreen */ {0x3333,0xFFFF,0x3333},
273 /* 24 cyan */ {0x0000,0xCCCC,0xCCCC},
274 /* 25 sky */ {0x3333,0xFFFF,0xFFFF},
275 /* 26 marine */ {0x3333,0x6666,0xFFFF},
276 /* 27 lblue */ {0x3333,0xCCCC,0xFFFF},
277 /* 28 lpurple */ {0x9999,0x9999,0xFFFF},
278 /* 29 pink */ {0xFFFF,0x9999,0xFFFF}};
281 st->shades = (st->d3d==D3D_TILED) ? 5 : st->lwid/2+1;
282 st->ncolors=4+random()%4;
283 if (st->cmap>0) { /* tint the basecolors a bit */
284 for (c1=0; c1<BASECOLORS; c1++)
285 for (c2=0; c2<2; c2++)
286 if (!basecol[c1][c2]) {
287 basecol[c1][c2]+=random()%16000;
288 } else if (basecol[c1][c2]==0xFFFF) {
289 basecol[c1][c2]-=random()%16000;
291 basecol[c1][c2]-=8000;
292 basecol[c1][c2]+=random()%16000;
297 for (c1=0; c1<st->ncolors; c1++)
298 col[c1]=random()%BASECOLORS;
301 for (c1=0; c1<st->ncolors; c1++)
304 case 2: /* semi consecutive darks */
306 for (c1=1; c1<st->ncolors; c1++)
307 col[c1]=(col[c1-1]+1+random()%2)%15;
309 case 3: /* consecutive darks */
310 col[0]=random()%(15-st->ncolors);
311 for (c1=1; c1<st->ncolors; c1++)
315 for (c1=0; c1<st->ncolors; c1++) {
316 /* adjust colors already set */
317 for (h1=c1*st->shades-1; h1>=0; h1--)
318 st->colors[h1+st->shades]=st->colors[h1];
319 make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
320 basecol[col[c1]][0], basecol[col[c1]][1], basecol[col[c1]][2],
321 0xFFFF, 0xFFFF, 0xFFFF, st->colors, &st->shades,
328 if (st->cmap%2) { /* basecolors */
331 c2=(c1+3+(random()%5))%15;
332 c3=(c2+3+(random()%5))%15;
334 c1=random()%BASECOLORS;
335 c2=(c1+5+(random()%10))%BASECOLORS;
336 c3=(c2+5+(random()%10))%BASECOLORS;
347 } else { /* random rgb's */
351 r2=(r1+16384+random()%32768)%65535;
352 g2=(g1+16384+random()%32768)%65535;
353 b2=(b1+16384+random()%32768)%65535;
354 r3=(r2+16384+random()%32768)%65535;
355 g3=(g2+16384+random()%32768)%65535;
356 b3=(b2+16384+random()%32768)%65535;
359 case 0: /* make_color_ramp color->color */
361 case 2: /* make_color_ramp color->white */
363 st->ncolors=5+random()%5;
366 make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
367 r1, g1, b1, r2, g2, b2,
368 st->colors, &st->ncolors, random()%2);
370 case 4: /* 3 color make_color_loop */
374 st->ncolors=8+random()%12;
375 rgb_to_hsv(r1, g1, b1, &h1, &s1, &v1);
376 rgb_to_hsv(r2, g2, b2, &h2, &s2, &v2);
377 rgb_to_hsv(r3, g3, b3, &h3, &s3, &v3);
379 make_color_loop(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
380 h1, s1, v1, h2, s2, v2, h3, s3, v3,
381 st->colors, &st->ncolors, True, False);
383 case 8: /* random smooth */
385 st->ncolors=(random()%4)*6+12;
386 make_smooth_colormap (st->xgwa.screen, st->xgwa.visual,
387 st->xgwa.colormap, st->colors, &st->ncolors,
390 case 10: /* rainbow */
391 st->ncolors=(random()%4)*6+12;
392 make_uniform_colormap (st->xgwa.screen, st->xgwa.visual,
393 st->xgwa.colormap, st->colors, &st->ncolors,
396 case 11: /* dark to light blend */
401 make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
402 r1, g1, b1, 0xFFFF, 0xFFFF, 0xFFFF,
403 tmp_col1, &st->ncolors, False);
404 make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
405 r2, g2, b2, 0xFFFF, 0xFFFF, 0xFFFF,
406 tmp_col2, &st->ncolors, False);
408 for(c1=0; c1<=4; c1++) {
409 st->colors[c1*2]=tmp_col1[c1];
410 st->colors[c1*2+1]=tmp_col2[c1];
414 make_color_ramp_rgb(st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
415 r3, g3, b3, 0xFFFF, 0xFFFF, 0xFFFF,
416 tmp_col3, &st->ncolors, False);
417 for(c1=0; c1<=4; c1++) {
418 st->colors[c1*3]=tmp_col1[c1];
419 st->colors[c1*3+1]=tmp_col2[c1];
420 st->colors[c1*3+2]=tmp_col3[c1];
425 default: /* random */
426 st->ncolors=(random()%4)*6+12;
427 make_random_colormap (st->xgwa.screen, st->xgwa.visual,
428 st->xgwa.colormap, st->colors, &st->ncolors,
429 False, True, False, True);
433 /* set random color order for drawing and erasing */
434 for (c1=0; c1<MAXCOLORS; c1++)
436 for (c1=0; c1<MAXCOLORS; c1++) {
437 c3=random()%MAXCOLORS;
439 st->rco[c1]=st->rco[c3];
444 static int _comparedeo(const void *i, const void *j)
446 struct lineStruct *h1, *h2;
448 h1=(struct lineStruct *)i;
449 h2=(struct lineStruct *)j;
450 if (h1->deo > h2->deo)
452 if (h1->deo < h2->deo)
458 _hv(struct state *st, int x, int y, int d1, int d2, int pn, Bool de)
464 v1 = (de) ? st->egridx-x : st->gridx-x;
473 v1 = (de) ? st->egridy-y : st->gridy-y;
478 v2 = (de) ? st->egridx-x : st->gridx-x;
487 v2 = (de) ? st->egridy-y : st->gridy-y;
490 r = (de) ? (st->dline[st->li].hv) ? (v1+10000)*pn : (v2+10000)*-pn :
491 (st->eline[st->li].hv) ? (v1+10000)*pn : (v2+10000)*-pn;
496 _getdeo(struct state *st, int x, int y, int map, int de)
500 case 0: /* horizontal one side */
502 case 1: /* vertical one side */
504 case 2: /* horizontal two side */
505 return(_min(x,st->gridx-x)+1);
506 case 3: /* vertical two side */
507 return(_min(y,st->gridy-y)+1);
509 return(_max(abs(x-st->rx3[de]),abs(y-st->ry3[de]))+1);
510 case 5: /* two squares */
511 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);
512 case 6: /* horizontal rectangle */
513 return(_max(abs(x-st->rx3[de]),abs(y-(st->ry3[de]))*st->cs1[de])+1);
514 case 7: /* vertical rectangle */
515 return(_max(abs(x-st->rx3[de])*st->cs1[de],abs(y-(st->ry3[de])))+1);
516 case 8: /* + cross */
517 return(_min(abs(x-st->rx3[de]),abs(y-(st->ry3[de])))+1);
518 case 9: /* diagonal */
520 case 10: /* opposite diagonal */
521 return((x*3/4+st->gridy-y)+1);
522 case 11: /* diamond */
523 return((abs(x-st->rx3[de])+abs(y-st->ry3[de]))/2+1);
524 case 12: /* two diamonds */
525 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);
526 case 13: /* circle */
527 return(_dist(st,x,st->rx3[de],y,st->ry3[de],0)+1);
528 case 14: /* horizontal ellipse */
529 return(_dist(st,x,st->rx3[de],y,st->ry3[de],1)+1);
530 case 15: /* vertical ellipse */
531 return(_dist(st,x,st->rx3[de],y,st->ry3[de],2)+1);
532 case 16: /* two circles */
533 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);
534 case 17: /* horizontal straight wave */
535 return(x+_wave(st,st->gridy+y,st->csw[0]*st->cs1[0],st->csw[0]*st->cs2[0],st->wave[de]));
536 case 18: /* vertical straight wave */
537 return(y+_wave(st,st->gridx+x,st->csw[0]*st->cs1[0],st->csw[0]*st->cs2[0],st->wave[de]));
538 case 19: /* horizontal wavey wave */
539 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);
540 case 20: /* vertical wavey wave */
541 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);
542 /* no d3d for 21,22 */
543 case 21: /* simultaneous directional */
544 return(_hv(st,x,y,st->cs1[0]%2,st->cs2[0]%2,1,de));
545 case 22: /* reverse directional */
546 return(_hv(st,x,y,st->cs1[0]%2,st->cs2[0]%2,-1,de));
547 case 23: /* length */
549 return(st->dline[st->li].len*1000+random()%5000);
551 return(st->eline[st->li].len*1000+random()%5000);
552 case 24: /* object */
557 return(st->dline[st->li].obj*100);
559 return(st->eline[st->li].obj*100);
561 cr = (de) ? st->dline[st->li].color : st->eline[st->li].color;
562 if (map<34) cr=st->rco[cr];
563 if ((map%6<4) || (de)) { /* by color */
566 } else if (map%6==4) { /* by color horizontaly */
568 cr+=(x+random()%(st->gridx/2));
569 } else { /* by color vertically */
571 cr+=(y+random()%(st->gridy/2));
579 _init_screen(struct state *st)
582 struct lineStruct *tmp;
584 /* malloc memory in case of resize */
586 st->max_wxh=st->xgwa.width*st->xgwa.height;
599 st->narray = (st->xgwa.width+1)*(st->xgwa.height+1)/4+1;
600 st->dline = calloc(st->narray, sizeof(struct lineStruct));
601 st->eline = calloc(st->narray, sizeof(struct lineStruct));
602 st->grid = calloc(st->narray, sizeof(struct gridStruct));
603 st->zlist = calloc(st->narray, sizeof(unsigned int));
604 st->fdol = calloc(st->narray, sizeof(unsigned int));
605 st->odi = calloc(st->narray, sizeof(Bool));
606 if ((st->dline == NULL) || (st->eline == NULL) ||
607 (st->grid == NULL) || (st->zlist == NULL) ||
608 (st->fdol == NULL) || (st->odi == NULL)) {
609 fprintf(stderr, "not enough memory\n");
612 st->dialog = (st->xgwa.width<500) ? 1 : 0;
616 /* swap st->dline and st->eline pointers to resort and erase */
623 st->egridx=st->gridx;
624 st->egridy=st->gridy;
626 /* create new erase order */
627 for (st->li=1; st->li<=st->eli; st->li++)
628 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;
629 qsort(st->eline, st->eli+1, sizeof(struct lineStruct), _comparedeo);
633 /* clear arrays and other counters */
634 st->di=st->ei=st->fi=st->li=st->oi=st->zi=0;
636 /* li starts from 1 */
637 st->dline[0].x=st->dline[0].y=st->dline[0].len=0;
638 /* to keep it first after sorting so di is never null */
639 st->dline[0].deo=-999999999;
641 /* set random screen variables */
642 st->lwid = (st->ii==1) ? 3 : 2+((random()%6)%4);
643 st->d3d = ((st->tile==TILE_FLAT) || (st->tile==TILE_THIN) ||
644 (st->tile==TILE_OUTLINE)) ? D3D_NONE :
645 (st->tile==TILE_BLOCK) ? D3D_BLOCK :
646 (st->tile==TILE_NEON) ? D3D_NEON :
647 (st->tile==TILE_TILED) ? D3D_TILED :
648 /* force TILE_D3D on first screen to properly load all shades */
649 ((st->ii==1) && (!st->newcols)) ? D3D_TILED : (random()%5)%4;
650 /* st->d3d=D3D_BLOCK; st->lwid=2; */
651 st->outline = (st->tile==TILE_OUTLINE) ? 1 :
652 ((st->tile!=TILE_RANDOM) || (random()%5)) ? 0 : 1;
653 st->round = (st->d3d==D3D_NEON) ? 1 :
654 ((st->d3d==D3D_BLOCK) || (st->outline) || (random()%6)) ? 0 : 1;
655 if ((st->d3d) || (st->outline) || (st->round))
657 if ((!st->d3d) && (!st->round) && (!st->outline) && (st->lwid>3))
659 if (st->d3d==D3D_TILED)
661 if (st->tile==TILE_THIN)
666 st->maxlen=(st->lwid>6) ? 2+(random()%4) :
667 (st->lwid>4) ? 2+(random()%8)%6 :
668 (st->lwid>2) ? 2+(random()%12)%8 : 2+(random()%15)%10;
669 st->bnratio = 4+(random()%4)+(random()%4);
670 st->forcemax = (random()%6) ? 0 : 1;
672 if ((st->ii==1) || (st->newcols))
675 st->dmap = (st->emap+5+(random()%5))%DRAWORDERS;
677 st->dmap=20+random()%20;
679 st->dvar = (st->dmap>22) ? 100 : 10+(st->csw[0]*(random()%5));
680 st->ddir= (random()%2) ? 1 : -1;
682 st->emap = (st->dmap+10+(random()%10))%20;
683 st->evar = (st->emap>22) ? 100 : 10+(st->csw[0]*(random()%5));
684 st->edir= (random()%2) ? 1 : -1;
686 st->layers= (random()%2) ? 2 : (random()%2) ? 1 : (random()%2) ? 3 : 4;
687 st->cmap=(st->cmap+5+(random()%10))%COLORMAPS;
689 for (x=0; x<LAYERS; x++) {
690 st->pattern[x]=random()%PATTERNS;
691 st->shape[x]=random()%SHAPES;
692 st->mix[x]=random()%20;
693 nstr = (st->lwid==2) ? 20+random()%12 :
694 (st->lwid==3) ? 16+random()%8 :
695 (st->lwid==4) ? 12+random()%6 :
696 (st->lwid==5) ? 10+random()%5 :
697 (st->lwid==6) ? 8+random()%4 :
699 st->csw[x] = _max(5,st->gridy/nstr);
700 st->wsx[x] = (st->wsx[x]+3+(random()%3))%STRETCHES;
701 st->wsy[x] = (st->wsy[x]+3+(random()%3))%STRETCHES;
702 st->sec[x] = random()%5;
703 if ((!st->dialog) && (st->sec[x]<2)) st->csw[x]/=2;
704 st->cs1[x] = (st->dialog) ? 1+random()%3 : 2+random()%5;
705 st->cs2[x] = (st->dialog) ? 1+random()%3 : 2+random()%5;
706 st->cs3[x] = (st->dialog) ? 1+random()%3 : 2+random()%5;
707 st->cs4[x] = (st->dialog) ? 1+random()%3 : 2+random()%5;
708 st->wave[x]=random()%WAVES;
709 st->wavel[x]=st->csw[x]*(2+random()%6);
710 st->waveh[x]=st->csw[x]*(1+random()%3);
711 st->rx1[x]=(st->gridx/10+random()%(st->gridx*8/10));
712 st->ry1[x]=(st->gridy/10+random()%(st->gridy*8/10));
713 st->rx2[x]=(st->gridx*2/10+random()%(st->gridx*6/10));
714 st->ry2[x]=(st->gridy*2/10+random()%(st->gridy*6/10));
715 st->rx3[x]=(st->gridx*3/10+random()%(st->gridx*4/10));
716 st->ry3[x]=(st->gridy*3/10+random()%(st->gridy*4/10));
721 _shape(struct state *st, int x, int y, int rx, int ry, int n)
723 switch(st->shape[n]) {
724 case 0: /* square/rectangle */
727 return(1+_max(abs(x-rx)*st->cs1[n]/st->cs2[n],abs(y-ry)*st->cs3[n]/st->cs4[n]));
728 case 3: /* diamond */
730 return(1+(abs(x-rx)*st->cs1[n]/st->cs2[n]+abs(y-ry)*st->cs3[n]/st->cs4[n]));
731 case 5: /* 8 point star */
732 return(1+_min(_max(abs(x-rx),abs(y-ry))*3/2,abs(x-rx)+abs(y-ry)));
733 case 6: /* circle/oval */
736 return(1+_dist(st,x,rx,y,ry,st->cs1[n]));
737 case 9: /* black hole circle */
738 return(1+(st->gridx*st->gridy/(1+(_dist(st,x,rx,y,ry,st->cs2[n])))));
740 return(1+_min(abs(x-rx)*st->gridx/(abs(y-ry)+1),abs(y-ry)*st->gridx/(abs(x-rx)+1)));
741 case 11: /* 2 circles+inverted circle */
742 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]))));
744 return(1+(int)sqrt(abs((x-rx)*(y-ry))));
745 case 13: /* centered ellipse */
746 return(1+_dist(st,x,rx,y,ry,0)+_dist(st,x,st->gridx-rx,y,st->gridy-ry,0));
747 default: /* triangle */
748 return(1+_triangle(st,x,y,rx,ry,st->cs4[n]));
750 return(1+_triangle(st,x,y,rx,ry,st->cs4[n]));
754 _pattern(struct state *st, int x, int y, int n)
763 x+=(st->gridy-y)/(1+st->cs4[n]);
766 x+=_wave(st,y,st->gridx/(1+st->cs1[n]),st->gridy,0);
769 x+=_wave(st,st->gridy-y,st->gridy/(1+st->cs1[n]),st->gridy,0);
771 case 4: /* U curves */
772 x+=_wave(st,y,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0);
775 x-=_wave(st,y,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0);
780 y+=ox/(1+st->cs1[n]);
783 y+=(st->gridx-ox)/(1+st->cs1[n]);
786 y+=_wave(st,ox,st->gridx/(1+st->cs1[n]),st->gridx,0);
789 y+=_wave(st,st->gridx-ox,st->gridx/(1+st->cs1[n]),st->gridx,0);
791 case 4: /* U curves */
792 y+=_wave(st,ox,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0);
795 y-=_wave(st,ox,st->cs1[n]*st->csw[n]/2,st->gridy*2/M_PI,0);
798 switch(st->pattern[n]) {
799 case 0: /* horizontal stripes */
802 case 1: /* vertical stripes */
805 case 2: /* diagonal stripes */
806 v=(x+(y*st->cs1[n]/st->cs2[n]));
808 case 3: /* reverse diagonal stripes */
809 v=(x-(y*st->cs1[n]/st->cs2[n]));
811 case 4: /* checkerboard */
812 v=(y/st->csw[n]*3+x/st->csw[n])*st->csw[n];
814 case 5: /* diagonal checkerboard */
815 v=((x+y)/2/st->csw[n]+(x+st->gridy-y)/2/st->csw[n]*3)*st->csw[n];
817 case 6: /* + cross */
818 v=st->gridx+(_min(abs(x-st->rx3[n]),abs(y-st->ry3[n]))*2);
820 case 7: /* double + cross */
821 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;
823 case 8: /* X cross */
824 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);
826 case 9: /* double X cross */
827 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;
829 case 10: /* horizontal stripes/waves */
830 v=st->gridy+(y+_wave(st,x,st->waveh[n],st->wavel[n],st->wave[n]));
832 case 11: /* vertical stripes/waves */
833 v=st->gridx+(x+_wave(st,y,st->waveh[n],st->wavel[n],st->wave[n]));
835 case 12: /* diagonal stripes/waves */
836 v=st->gridx+(x+(y*st->cs1[n]/st->cs2[n])+_wave(st,x,st->waveh[n],st->wavel[n],st->wave[n]));
838 case 13: /* diagonal stripes/waves */
839 v=st->gridx+(x-(y*st->cs1[n]/st->cs2[n])+_wave(st,y,st->waveh[n],st->wavel[n],st->wave[n]));
841 case 14: /* horizontal spikey waves */
842 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]);
844 case 15: /* vertical spikey waves */
845 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]);
847 case 16: /* big slanted hwaves */
848 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]);
850 case 17: /* big slanted vwaves */
851 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]);
853 case 18: /* double hwave */
854 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]);
856 case 19: /* double vwave */
857 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]);
859 case 20: /* one shape */
862 v=_shape(st,x, y, st->rx3[n], st->ry3[n], n);
864 case 23: /* two shapes */
867 v=_min(_shape(st,x, y, st->rx1[n], st->ry1[n], n),_shape(st,x, y, st->rx2[n], st->ry2[n], n));
869 case 26: /* two shapes opposites */
871 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));
873 case 28: /* two shape checkerboard */
875 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];
877 case 30: /* two shape blob */
879 v=(_shape(st,x, y, st->rx1[n], st->ry1[n], n)+_shape(st,x, y, st->rx2[n], st->ry2[n], n))/2;
881 case 32: /* inverted two shape blob */
883 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;
885 case 34: /* three shapes */
887 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)));
889 case 36: /* three shape blob */
891 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;
893 case 38: /* 4 shapes */
894 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)));
896 case 39: /* four rainbows */
897 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)));
900 /* stretch or contract stripe */
903 v=(int)sqrt((int)sqrt(abs(v)*st->gridx)*st->gridx);
906 v=((int)pow(v,2)/st->gridx);
913 _getcolor(struct state *st, int x, int y)
917 for (n=0; n<st->layers; n++) {
918 cv[n]=_pattern(st,x,y,n);
919 /* first wave/shape */
920 cv[0] = (!n) ? cv[0]/st->csw[0] :
922 (st->mix[n]<5) ? (cv[0]*st->csw[0]+cv[n])/st->csw[n] :
923 /* checkerboard+ncol/2 */
924 (st->mix[n]<12) ? cv[0]+(cv[n]/st->csw[n]*st->ncolors/2) :
926 (st->mix[n]<16) ? cv[0]+(cv[n]/st->csw[n]) :
928 (st->mix[n]<18) ? cv[0]-(cv[n]/st->csw[n]) :
929 /* r to l morph mix */
930 (st->mix[n]==18) ? ((cv[0]*x)+(cv[n]*(st->gridx-x)/st->csw[n]))/st->gridx :
931 /* u to d morph mix */
932 ((cv[0]*y)+(cv[n]*(st->gridy-y)/st->csw[n]))/st->gridy;
937 /* return value=line direction
938 st->olen=open space to edge or next blocking line
939 st->bln=blocking line number or -1 if edge blocks */
941 _findopen(struct state *st, int x, int y, int z)
943 int dir, od[4], no=0;
945 if (((st->grid[z].hl) || (st->grid[z].hr)) &&
946 ((st->grid[z].vu) || (st->grid[z].vd)))
948 if ((z>st->gridx) && (!st->grid[z].hl) && (!st->grid[z].hr) &&
949 (!st->grid[z-st->gridx].line)) {
953 if ((z<st->gridn-st->gridx) && (!st->grid[z].hl) &&
954 (!st->grid[z].hr) && (!st->grid[z+st->gridx].line)) {
958 if ((x) && (!st->grid[z].hl) && (!st->grid[z].hr) &&
959 (!st->grid[z-1].line)) {
963 if (((z+1)%st->gridx) && (!st->grid[z].hl) && (!st->grid[z].hr) &&
964 (!st->grid[z+1].line)) {
972 while ((st->olen<=st->maxlen) && (!st->bln)) {
975 st->bln = (y-st->olen<0) ? -1 :
976 st->grid[z-(st->olen*st->gridx)].line;
978 st->bln = (y+st->olen>=st->gridy) ? -1 :
979 st->grid[z+(st->olen*st->gridx)].line;
981 st->bln = (x-st->olen<0) ? -1 :
982 st->grid[z-st->olen].line;
984 st->bln = (x+st->olen>=st->gridx) ? -1 :
985 st->grid[z+st->olen].line;
992 _fillgrid(struct state *st)
994 unsigned int gridc, n, add;
996 gridc=st->gridx*st->dline[st->li].y+st->dline[st->li].x;
997 add = (st->dline[st->li].hv) ? 1 : st->gridx;
998 for (n=0; n<=st->dline[st->li].len; n++) {
1001 if (!st->grid[gridc].line) {
1003 st->grid[gridc].line=st->li;
1005 if (st->dline[st->li].hv) {
1007 st->grid[gridc].hr=st->li;
1008 if (n<st->dline[st->li].len)
1009 st->grid[gridc].hl=st->li;
1012 st->grid[gridc].vd=st->li;
1013 if (n<st->dline[st->li].len)
1014 st->grid[gridc].vu=st->li;
1016 if (st->fi>=st->gridn) {
1024 _newline(struct state *st)
1026 int bl, bz, dir, lt, x, y, z;
1029 z=st->zlist[st->zi];
1033 dir=_findopen(st,x,y,z);
1035 if (!st->grid[z].line) {
1036 /* this is an empty space, make a new line unless nothing is open around it */
1037 if (dir==DIR_NONE) {
1038 /* nothing is open, force a len 1 branch in any direction */
1040 while ((dir==DIR_NONE) ||
1041 ((dir==DIR_UP) && (!y)) ||
1042 ((dir==DIR_DOWN) && (y+1==st->gridy)) ||
1043 ((dir==DIR_LEFT) && (!x)) ||
1044 ((dir==DIR_RIGHT) && (x+1==st->gridx))) {
1047 bz = (dir==DIR_UP) ? z-st->gridx : (dir==DIR_DOWN) ? z+st->gridx : (dir==DIR_LEFT) ? z-1 : z+1;
1048 bl = st->grid[bz].line;
1049 } else if ((st->bnratio>1) && (st->bln>0) &&
1050 (st->olen<st->maxlen) && (random()%st->bnratio)) {
1051 /* branch into blocking line */
1055 /* make a new line and new object */
1060 /* this is a filled space, make a branch unless nothing is open around it */
1063 /* make a branch out of this line */
1065 bl=st->grid[z].line;
1068 st->dline[st->li].len = (lt==LINE_FORCE) ? 1 : (lt==LINE_BRIN) ?
1069 st->olen+1 : (!st->forcemax) ? st->olen : 1+random()%st->olen;
1070 st->dline[st->li].x=x;
1072 st->dline[st->li].x-=st->dline[st->li].len;
1073 st->dline[st->li].y=y;
1075 st->dline[st->li].y-=st->dline[st->li].len;
1076 st->dline[st->li].hv = ((dir==DIR_LEFT) || (dir==DIR_RIGHT)) ?
1078 st->dline[st->li].obj = (lt==LINE_NEW) ? st->oi :
1081 int color = (_getcolor(st,x,y))%st->ncolors;
1082 if (color < 0) color += st->ncolors;
1083 st->dline[st->li].color = color;
1085 st->dline[st->li].color = st->dline[bl].color;
1087 st->dline[st->li].deo=(_getdeo(st,x,y,st->dmap,1) +
1088 (random()%st->dvar) + (random()%st->dvar))*st->ddir;
1089 st->dline[st->li].ndol=0;
1094 _create_screen(struct state *st)
1096 while(!st->grid_full)
1098 qsort(st->dline, st->li+1, sizeof(struct lineStruct), _comparedeo);
1099 /*st->lpu=st->li/20/((6-st->speed)*3);
1100 Used to use a computed lpu, lines per update to control draw speed
1101 draw 1/lpu of the lines before each XSync which takes a split second
1102 the higher the lpu, the quicker the screen draws. This worked somewhat
1103 after the 4->5 update, however with the Mac updating so much more slowly,
1104 values tuned for it draw the screen in a blink on Linux. Therefore we
1105 draw 1/200th of the screen with each update and sleep, if necessary */
1106 st->lpu = (st->dialog) ? st->li/50 : st->li/200;
1107 if (!st->lpu) st->lpu = 1;
1109 st->mode=MODE_ERASE;
1113 _fill_outline(struct state *st, int di)
1119 x=st->dline[di].x*st->lwid+1;
1120 y=st->dline[di].y*st->lwid+1;
1121 if (st->dline[di].hv) {
1122 w=(st->dline[di].len+1)*st->lwid-3;
1126 h=(st->dline[di].len+1)*st->lwid-3;
1128 XFillRectangle (st->display, st->window, st->bgc, x, y, w, h);
1132 _XFillRectangle(struct state *st, int di, int adj)
1134 int a, b, x, y, w, h;
1136 x=st->dline[di].x*st->lwid;
1137 y=st->dline[di].y*st->lwid;
1138 if (st->dline[di].hv) {
1139 w=(st->dline[di].len+1)*st->lwid-1;
1143 h=(st->dline[di].len+1)*st->lwid-1;
1160 XFillRectangle(st->display, st->window, st->fgc, x, y, w, h);
1162 if (h<st->lwid) { /* horizontal */
1164 for (b=0; b<=a; b++)
1165 XFillRectangle(st->display, st->window, st->fgc,
1166 x+b, y+a-b, w-b*2, h-((a-b)*2));
1167 } else { /* vertical */
1169 for (b=0; b<=a; b++)
1170 XFillRectangle(st->display, st->window, st->fgc,
1171 x+a-b, y+b, w-((a-b)*2), h-b*2);
1177 _XFillTriangle(struct state *st, int color, int x1, int y1, int x2, int y2,
1188 XSetForeground(st->display, st->fgc, st->colors[color].pixel);
1189 XFillPolygon (st->display, st->window, st->fgc, points, 3, Convex,
1194 _XFillPolygon4(struct state *st, int color, int x1, int y1, int x2, int y2,
1195 int x3, int y3, int x4, int y4)
1207 XSetForeground(st->display, st->fgc, st->colors[color].pixel);
1208 XFillPolygon (st->display, st->window, st->fgc, points, 4, Convex,
1213 _draw_tiled(struct state *st, int color)
1215 int a, c, d, x, y, z, m1, m2, lr, nl, w, h;
1216 a = (st->dline[st->di].hv) ? 1 : st->gridx;
1217 z = st->dline[st->di].y*st->gridx+st->dline[st->di].x;
1218 m1 = (st->lwid-1)/2;
1223 /* draw tiles one grid cell at a time */
1224 for (c=0; c<=st->dline[st->di].len; c++) {
1225 if (st->dline[st->di].hv) {
1226 x = (st->dline[st->di].x+c)*st->lwid;
1227 y = st->dline[st->di].y*st->lwid;
1229 st->grid[z].dhr=st->di;
1230 if (c<st->dline[st->di].len)
1231 st->grid[z].dhl=st->di;
1233 x = st->dline[st->di].x*st->lwid;
1234 y = (st->dline[st->di].y+c)*st->lwid;
1236 st->grid[z].dvd=st->di;
1237 if (c<st->dline[st->di].len)
1238 st->grid[z].dvu=st->di;
1241 if (st->grid[z].dhl)
1243 if (st->grid[z].dhr)
1245 if (st->grid[z].dvu)
1247 if (st->grid[z].dvd)
1249 /* draw line base */
1252 case 2: /* vertical */
1259 h = ((d==1) || (d==5)) ? lr : nl;
1260 XSetForeground(st->display, st->fgc,
1261 st->colors[color].pixel);
1262 XFillRectangle (st->display, st->window, st->fgc,
1264 XSetForeground(st->display, st->fgc,
1265 st->colors[color+3].pixel);
1266 XFillRectangle (st->display, st->window, st->fgc,
1270 case 8: /* horizontal */
1276 w = (d==4) ? lr : nl;
1277 XSetForeground(st->display, st->fgc,
1278 st->colors[color+1].pixel);
1279 XFillRectangle (st->display, st->window, st->fgc,
1281 XSetForeground(st->display, st->fgc,
1282 st->colors[color+2].pixel);
1283 XFillRectangle (st->display, st->window, st->fgc,
1289 case 1: /* bottom end ^ */
1290 _XFillTriangle(st,color+2, x, y+lr, x+lr, y+lr, x+m2, y+m2);
1292 case 2: /* top end \/ */
1293 _XFillTriangle(st,color+1, x, y, x+lr, y, x+m2, y+m2);
1295 case 4: /* right end < */
1296 _XFillTriangle(st,color+3, x+lr, y, x+lr, y+lr, x+m2, y+m2);
1298 case 5: /* LR corner */
1299 _XFillTriangle(st,color+1, x, y+m2, x+m2, y+m2, x, y);
1300 _XFillPolygon4(st,color+2, x, y+m2, x+m2, y+m2, x+lr, y+lr, x, y+lr);
1302 case 6: /* UR corner */
1303 _XFillPolygon4(st,color+1, x, y+m2, x+m2, y+m2, x+lr, y, x, y);
1304 _XFillTriangle(st,color+2, x, y+m2, x+m2, y+m2, x, y+lr);
1306 case 7: /* T > into line */
1307 _XFillTriangle(st,color+1, x, y+m2, x+m2, y+m2, x, y);
1308 _XFillTriangle(st,color+2, x, y+m2, x+m2, y+m2, x, y+lr);
1310 case 8: /* left end > */
1311 _XFillTriangle(st,color, x, y, x, y+lr, x+m2, y+m2);
1313 case 9: /* LL corner */
1314 _XFillPolygon4(st,color, x+m2, y, x+m2, y+m2, x, y+lr, x, y);
1315 _XFillTriangle(st,color+3, x+m2, y, x+m2, y+m2, x+lr, y);
1317 case 10: /* UL corner */
1318 _XFillPolygon4(st,color, x+m2, y+nl, x+m2, y+m2, x, y, x, y+nl);
1319 _XFillPolygon4(st,color+3, x+m2, y+nl, x+m2, y+m2, x+lr, y+lr, x+lr, y+nl);
1321 case 11: /* T < into line */
1322 _XFillPolygon4(st,color+1, x+nl, y+m2, x+m2, y+m2, x+lr, y, x+nl, y);
1323 _XFillPolygon4(st,color+2, x+nl, y+m2, x+m2, y+m2, x+lr, y+lr, x+nl, y+lr);
1325 case 13: /* T \/ into line */
1326 _XFillTriangle(st,color, x+m2, y, x+m2, y+m2, x, y);
1327 _XFillTriangle(st,color+3, x+m2, y, x+m2, y+m2, x+lr, y);
1329 case 14: /* T ^ into line */
1330 _XFillPolygon4(st,color, x+m2, y+nl, x+m2, y+m2, x, y+lr, x, y+nl);
1331 _XFillPolygon4(st,color+3, x+m2, y+nl, x+m2, y+m2, x+lr, y+lr, x+lr, y+nl);
1333 case 15: /* X intersection */
1334 _XFillTriangle(st,color+1, x, y+m2, x+m2, y+m2, x, y);
1335 _XFillTriangle(st,color+2, x, y+m2, x+m2, y+m2, x, y+lr);
1336 _XFillPolygon4(st,color+1, x+nl, y+m2, x+m2, y+m2, x+lr, y, x+nl, y);
1337 _XFillPolygon4(st,color+2, x+nl, y+m2, x+m2, y+m2, x+lr, y+lr, x+nl, y+lr);
1345 _mselapsed(struct state *st)
1348 gettimeofday(&t, NULL);
1349 t.tv_sec -= st->time.tv_sec;
1350 t.tv_usec -= st->time.tv_usec;
1351 return ((long)t.tv_sec*1000000+t.tv_usec);
1355 _draw_lines(struct state *st)
1357 int n, z, a, color, sh, di;
1359 for (a=0; a<=st->oi; a++)
1362 for (st->di=st->bi; st->di<_min(st->li+1,st->bi+st->lpu); st->di++) {
1363 color=(st->dline[st->di].color%st->ncolors)*st->shades;
1364 XSetForeground(st->display, st->fgc, st->colors[color].pixel);
1368 st->dline[st->di].ndol=st->fdol[st->dline[st->di].obj];
1369 st->fdol[st->dline[st->di].obj]=st->di;
1370 for (sh=0; sh<st->lwid/2; sh++) {
1371 XSetForeground(st->display, st->fgc,
1372 st->colors[color+sh].pixel);
1375 _XFillRectangle(st,di,sh);
1376 di=st->dline[di].ndol;
1381 st->dline[st->di].ndol=st->fdol[st->dline[st->di].obj];
1382 st->fdol[st->dline[st->di].obj]=st->di;
1383 for (sh=0; sh<st->lwid/2; sh++) {
1384 XSetForeground(st->display, st->fgc,
1385 st->colors[color+(st->lwid/2)-sh-1].pixel);
1388 _XFillRectangle(st,di,sh);
1389 di=st->dline[di].ndol;
1394 _draw_tiled(st,color);
1396 default: /* D3D_NONE */
1397 _XFillRectangle(st,st->di,0);
1399 _fill_outline(st, st->di);
1400 z=st->dline[st->di].y*st->gridx+st->dline[st->di].x;
1401 a = (st->dline[st->di].hv) ? 1 : st->gridx;
1402 for (n=0; n<=st->dline[st->di].len; n++) {
1403 _fill_outline(st, st->grid[z].dhl);
1404 _fill_outline(st, st->grid[z].dhr);
1405 _fill_outline(st, st->grid[z].dvu);
1406 _fill_outline(st, st->grid[z].dvd);
1407 if (st->dline[st->di].hv) {
1409 st->grid[z].dhr=st->di;
1410 if (n<st->dline[st->di].len)
1411 st->grid[z].dhl=st->di;
1414 st->grid[z].dvd=st->di;
1415 if (n<st->dline[st->di].len)
1416 st->grid[z].dvu=st->di;
1424 if (st->di>st->li) {
1426 st->mode=MODE_CREATE;
1433 _erase_lines(struct state *st)
1437 for (st->di=st->bi; st->di<_min(st->eli+1,st->bi+st->elpu); st->di++) {
1438 if (st->eline[st->di].hv) {
1439 XFillRectangle (st->display, st->window, st->bgc,
1440 st->eline[st->di].x*st->elwid,
1441 st->eline[st->di].y*st->elwid,
1442 (st->eline[st->di].len+1)*st->elwid, st->elwid);
1444 XFillRectangle (st->display, st->window, st->bgc,
1445 st->eline[st->di].x*st->elwid,
1446 st->eline[st->di].y*st->elwid,
1447 st->elwid, (st->eline[st->di].len+1)*st->elwid);
1449 if (st->di==st->eli) /* clear just in case */
1450 XFillRectangle(st->display, st->window, st->bgc, 0, 0,
1451 st->xgwa.width, st->xgwa.height);
1453 if (st->di>st->eli) {
1456 st->mode=MODE_CREATE;
1466 abstractile_init(Display *display, Window window)
1468 struct state *st = (struct state *) calloc (1, sizeof(*st));
1470 /* struct utsname os;*/
1472 char *tile = get_string_resource(display, "tile", "Tile");
1473 if (tile && !strcmp(tile, "random")) st->tile = TILE_RANDOM;
1474 else if (tile && !strcmp(tile, "flat")) st->tile = TILE_FLAT;
1475 else if (tile && !strcmp(tile, "thin")) st->tile = TILE_THIN;
1476 else if (tile && !strcmp(tile, "outline")) st->tile = TILE_OUTLINE;
1477 else if (tile && !strcmp(tile, "block")) st->tile = TILE_BLOCK;
1478 else if (tile && !strcmp(tile, "neon")) st->tile = TILE_NEON;
1479 else if (tile && !strcmp(tile, "tiled")) st->tile = TILE_TILED;
1481 if (tile && *tile && !!strcmp(tile, "random"))
1482 fprintf(stderr, "%s: unknown tile option %s\n", progname, tile);
1483 st->tile = TILE_RANDOM;
1486 st->speed = get_integer_resource(display, "speed", "Integer");
1487 if (st->speed < 0) st->speed = 0;
1488 if (st->speed > 5) st->speed = 5;
1489 st->sleep = get_integer_resource(display, "sleep", "Integer");
1490 if (st->sleep < 0) st->sleep = 0;
1491 if (st->sleep > 60) st->sleep = 60;
1493 st->display=display;
1496 /* get screen size and create Graphics Contexts */
1497 XGetWindowAttributes (display, window, &st->xgwa);
1498 gcv.foreground = get_pixel_resource(display, st->xgwa.colormap,
1499 "foreground", "Foreground");
1500 st->fgc = XCreateGC (display, window, GCForeground, &gcv);
1501 gcv.foreground = get_pixel_resource(display, st->xgwa.colormap,
1502 "background", "Background");
1503 st->bgc = XCreateGC (display, window, GCForeground, &gcv);
1505 /* Um, no. This is obscene. -jwz.
1507 st->newcols=((!strcmp(os.sysname,"Linux")) || (!strcmp(os.sysname,"Darwin")))
1512 st->mode=MODE_CREATE;
1518 static unsigned long
1519 abstractile_draw (Display *dpy, Window window, void *closure)
1521 struct state *st = (struct state *) closure;
1524 gettimeofday(&st->time, NULL);
1526 /* If the window is too small, do nothing, sorry! */
1527 if (st->xgwa.width > 20 && st->xgwa.height > 20) {
1542 usleep = ((!st->ii) && (st->mode==MODE_CREATE)) ? 0 :
1543 (st->mode==MODE_CREATE) ? st->sleep*1000000-mse :
1544 /* speed=0-5, goal is 10,8,6,4,2,0 sec normal and 5,4,3,2,1,0 dialog */
1545 (5-st->speed)*(2-st->dialog)*100000/st->lpu-mse;
1552 abstractile_reshape (Display *dpy, Window window, void *closure,
1553 unsigned int w, unsigned int h)
1555 struct state *st = (struct state *) closure;
1557 st->xgwa.height = h;
1558 if (w*h>st->max_wxh)
1563 abstractile_event (Display *dpy, Window window, void *closure, XEvent *event)
1565 struct state *st = (struct state *) closure;
1566 if (screenhack_event_helper (dpy, window, event))
1568 st->mode=MODE_CREATE;
1576 abstractile_free (Display *dpy, Window window, void *closure)
1578 struct state *st = (struct state *) closure;
1582 static const char *abstractile_defaults [] = {
1583 ".background: black",
1584 ".foreground: white",
1590 "*ignoreRotation: True",
1595 static XrmOptionDescRec abstractile_options [] = {
1596 { "-sleep", ".sleep", XrmoptionSepArg, 0 },
1597 { "-speed", ".speed", XrmoptionSepArg, 0 },
1598 { "-tile", ".tile", XrmoptionSepArg, 0 },
1602 XSCREENSAVER_MODULE ("Abstractile", abstractile)