[comp.windows.x] Moir patterns and some more

danny@humus.huji.ac.il (Danny Braniss) (09/06/88)

Xsmoke is a program that generates a neet pattern, and together with xpalet
makes weird things on a colour screen. It runs on a Sun-3/110C. and soon I will
test it on an Apollo. I would be greatful to receive back comments/fixes, since
this is a 'learning programme' for me, and though it works, there are many
'black magic' tricks that I'm not certain about. This program also causes
the appearance of a bug that has been hunting me for some time. It concerns
the sun running os-3.4, and anybody else! The tcp/ip gets stuck. When I run
xsmoke on another cpu (ie Gould (4.3Bsd) or IBM-RT/PC(4.3)), it 'sometimes'
hangs in 'XPutImage', and in most of the Yellow Pages updates too.

(Sorry, but xpalet is still 'under developement', to be released soon, and
xsmoke is unfinished)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Makefile
#	xsmoke.1
#	xsmoke.c
#	GetArgs.c
# This archive created: Sat Sep  3 14:26:53 1988
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Makefile'
then
    echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
LIB=GetArgs.o
all: xsmoke xpalet

xsmoke: xsmoke.o $(LIB)
	cc -o xsmoke xsmoke.o $(LIB) -lX

xpalet: xpalet.o $(LIB)
	cc -o xpalet xpalet.o $(LIB) -lX

clean:
	rm -f xsmoke xpalet *.o *~ core

SHAR_EOF
fi
if test -f 'xsmoke.1'
then
    echo shar: "will not over-write existing file 'xsmoke.1'"
else
cat << \SHAR_EOF > 'xsmoke.1'
.TH XSMOKE 1
.SH NAME
xsmoke - smoking clover program
.SH SYNOPSIS
.B xsmoke
[x11 options] [-colors n]
.SH DESCRIPTION
This program runs the
.B "smoking clover"
algorithm which was deported from M.I.T by Phil Agre.
It initializes a square window
by drawing vectors from the center of the area to each point on the perimiter.
The value of each pixel is set to the number of vectors crossing it mod the
number of colors --the default is all the color available-- which can be
set with
.B "-colors n".
This results in a rectangular moire pattern.
.SH AUTHOR
Revived by Daniel Braniss, moir pattern Algorithm supplied by Phil Agre.
.SH "SEE ALSO"
xpalet(1)
.SH BUGS
I see no connection between the program's name and output.
SHAR_EOF
fi
if test -f 'xsmoke.c'
then
    echo shar: "will not over-write existing file 'xsmoke.c'"
else
cat << \SHAR_EOF > 'xsmoke.c'
#ifndef lint
static char *rcsid = "$Header: xsmoke.c,v 1.1 88/09/02 21:07:43 danny Locked $";
#endif
#include <stdio.h>
#include <X11/Xlib.h>
/*
 | Make SMOKE!
 */
#define USAGE "[X11 options] [-colors n]"
int	colors, size;
char	*pic;

char	*ST_display;
char	*ST_geometry;
char	*ST_fg;
char	*ST_bg;
char	*ST_fn;
char	*pname;
int	ST_reverse;

Display	*dpy;
int	screen;
XImage	IMAGE, *image;
GC	gc;
int	debug;
Window	SetupWindow();
int dontuse;

main(cc, vv)
char **vv;
{
	Window	wd;
	int	ncolors = 0;

	cc = GetArgs(cc, vv);
	while(cc-- > 0) {
		char *p = *vv++;

		if(strcmp(p, "-colors") == 0) {
			if(cc > 0) {
				ncolors = atoi(*vv++);
				cc--;
			}
		}
		else
		if(strcmp(p, "-dontuse") == 0) {
			if(cc > 0) {
				dontuse = atoi(*vv++);
				cc--;
			}

		} else
		if(strcmp(p, "-d") == 0)
			debug++;
		else {
			fprintf(stderr, "Usage: %s %s\n", pname, USAGE);
			exit(-1);
		}
	}
	dpy = XOpenDisplay(ST_display);
	if(dpy == 0)
		exit(-1);
	screen = DefaultScreen(dpy);
	wd = SetupWindow(512, 512, &pic);
	size = image->height;
	colors -= dontuse;
	if((ncolors > 0) && ((ncolors) < colors))
		colors = ncolors;
	if(debug)
		fprintf(stderr, "using %d colors\n", colors);
	MoirPattern(wd, image, colors);
	loop(wd);
}

/*
 | Init the Moir pattern
 */
MoirPattern(wd, image, colors)
XImage	*image;
{
	char *pic;
	int size;
	int *rline;
	int x, y, alpha;
	int center;

	size = image->height;
	pic = image->data;
	rline = (int *) malloc(size * sizeof(int));
	center= size/2;
	/*
	 | 1/8 of the square;
	 */
	for(x = 0; x < center; x++) {
		/*
		 | alpha is the length of a cross section of the triangle
		 */
		alpha = x + 1;
		bzero(rline, sizeof(int)*alpha);
		for(y = 0; y < center; y++)
			rline[(alpha * y) / center]++;
		/*
		 | Now make 8 copies
		 */
		for(y = 0; y < alpha; y++) {
			int v = map_color(rline[y], colors);
			char *p;

			p = &pic[(center - y) * size];
			p[x + center] = p[center - x] = v;
			p = &pic[(center - x) * size];
			p[y + center] = p[center - y] = v;
			p = &pic[(center + y) * size];
			p[x + center] = p[center - x] = v;
			p = &pic[(center + x) * size];
			p[y + center] = p[center - y] = v;
		}
	}
	/*
	 |now display it in 4 chunks
	 */
	XPutImage(dpy, wd, gc, image, center, 0, center, 0, center, center);
	XPutImage(dpy, wd, gc, image, 0, center, 0, center, center, center);
	XPutImage(dpy, wd, gc, image, center, center, center, center, center, center);
	XPutImage(dpy, wd, gc, image, 0, 0, 0, 0, center, center);

}

map_color(c, ncolors)
{
	static int off = 0;

	if(off == 0) {
		int seed = time(0);
		srand(seed);
		off = rand();
	}
	c += off;
	c %= (ncolors-dontuse);
	return c+dontuse;
}
/*
 | All that has to do with creating the image
 */
#include <X11/Xutil.h>
#include <X11/cursorfont.h>

Window
SetupWindow(w, h, pic)
char **pic;
{
	XGCValues	xGCv;
	XWindowAttributes	ATR;
	XSetWindowAttributes	attr;
	Window	wd;
	Visual *visual;
	XVisualInfo vinfo, *vinfos;

	wd = XCreateSimpleWindow(dpy, RootWindow(dpy, screen),
				 0, 0,
				 w, h,
				 0,
				 BlackPixel(dpy, screen),
				 WhitePixel(dpy, screen));
	if(wd == 0) {
		fprintf(stderr, "cannot create window!\n");
		return 0;
	}
	XStoreName(dpy, wd, pname);
	EXPose(dpy, wd);
	XGetWindowAttributes(dpy, wd, &ATR);
	
	if(ATR.height > ATR.width)
		h = w = ATR.width;
	else
		w = h = ATR.height;
	if(!*pic && (*pic = (char *)malloc((unsigned int)(h * w))) == 0) {
		fprintf(stderr, "Not enough memory for picture!\n");
		exit(-1);
	}
	/*
	 | find out if it's colour
	 */
	colors = ATR.visual->map_entries;
	if(colors <= 2) {
		fprintf(stderr, "Sorry, no colours\n");
		exit(-1);
	}
	image = XCreateImage(dpy,
			     DefaultVisual(dpy, screen),
			     DisplayPlanes(dpy, screen),
			     ZPixmap,
			     0, 
			     *pic,
			     w, w, 8, 0);
	if(image == NULL) {
		perror("XCreateImage");
		exit(-1);
	}
	XMoveResizeWindow(dpy, wd, ATR.x, ATR.y, w, w);

	attr.override_redirect = True;
	attr.colormap = DefaultColormap(dpy, screen);
	attr.cursor = XCreateFontCursor(dpy, XC_trek);
	attr.background_pixel = BlackPixel(dpy, screen);
	XChangeWindowAttributes(dpy, wd,
				CWOverrideRedirect | CWColormap | CWCursor |
				GCBackground,
				&attr);
	xGCv.function = GXcopy;
	xGCv.background = (unsigned long)WhitePixel(dpy, screen);
	xGCv.foreground = (unsigned long)BlackPixel(dpy, screen);
#define GFMask GCFunction |GCForeground | GCBackground  /**/
	gc = XCreateGC(dpy, wd, GFMask, &xGCv);
	return wd;
}

EXPose(dpy, wd)
Display *dpy;
Window *wd;
{
	XEvent event;
	XExposeEvent *expose = (XExposeEvent *)&event;

	XSelectInput(dpy, wd, ExposureMask);
	XMapWindow(dpy, wd);
	for(;;) {
		XNextEvent(dpy, &event);
		switch((int)event.type) {
		case Expose:
			return;
		}
	}
}

loop(wd)
Window *wd;
{
	XEvent event;
	XExposeEvent *expose = (XExposeEvent *)&event;
	XSelectInput(dpy, wd, ButtonPressMask | ExposureMask | KeyPressMask |
		     KeyReleaseMask | EnterWindowMask | LeaveWindowMask);
	fprintf(stderr, "loop entered\n");

	for(;;) {
		XNextEvent(dpy, &event);
		if(debug)
			fprintf(stderr, "type: %d\n", (int)event.type);
		switch((int)event.type) {
		case ButtonPress: {
			XButtonEvent *e = (XButtonEvent *) &event;

			switch(e->button) {
			case Button1:
			case Button3:
			case Button2:
				return 0;
			}}
			break;

		case Expose:
			if(debug)
				fprintf(stderr,
					"Exposing %d...\n", expose->count);
			XPutImage(dpy,
				  wd,
				  gc,
				  image,
				  expose->x, expose->y,
				  expose->x, expose->y,
				  expose->width, expose->height);
			break;
		}

	}
}



SHAR_EOF
fi
if test -f 'GetArgs.c'
then
    echo shar: "will not over-write existing file 'GetArgs.c'"
else
cat << \SHAR_EOF > 'GetArgs.c'
extern char *ST_display;
extern char *ST_geometry;
extern char *ST_fg;
extern char *ST_bg;
extern char *ST_fn;
extern int ST_reverse;
extern char *pname;
char *index(), *rindex();

GetArgs(cc, vv)
char **vv;
{
	char **V, *p, **v0;

	V = v0 = vv;
	pname = *vv++;
	if(p = rindex(pname, '/'))
		pname = ++p;
	*V = *vv;
	while(cc-- > 1) {
		p = *vv++;
		switch(*p) {
		case '-':
			if(strcmp(p, "-display") == 0)
				ST_display = *vv++, cc--;
			else
			if(strcmp(p, "-geometry") == 0)
				ST_geometry = *vv++, cc--;
			else
			if(strcmp(p, "-fg") == 0)
				ST_fg = *vv++, cc--;
			else
			if(strcmp(p, "-bg") == 0)
				ST_bg = *vv++, cc--;
			else
		        if(strcmp(p, "-fn") == 0)
				ST_fn = *vv++, cc--;
			else
			if(strcmp(p, "-rv") == 0)
				ST_reverse++;
			else
				goto copy;
			break;
		case '=':
			ST_geometry = ++p;
			break;
		default:
			if(index(p, ':'))
				ST_display = p;
			else {
		copy:		if(V < vv) 
					*V = p;
				V++;
			}
		}
	}
	return V - v0;
}
SHAR_EOF
fi
exit 0
#	End of shell archive

	danny.

=======================================================================