shithub: pain

ref: ee5d653d61460a31666dc0bf8c9b011832a0e431
dir: /pill/pill.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

#define STEPS 3600
#define RADIUS .95
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define RAD2DEG(r_) ((180.0)/PI * (r_))
#define DEG2RAD(r_) (PI/(180.0) * (r_))
#define BACKGROUNDCOLOR 0x22272EFF
#define RECTANGLE(w, h) ((Rectangle){(Point){(0),(0)}, (Point){(w),(h)}})

Image * Circle = nil;
uint CircleBPL = 0;
u32int * RawCircle = nil;
uint RawCircleSize = 0;
Image * Background = nil;
int RunApp = 1;

static unsigned int
hsv2rgb(float h, float s, float v)
{
	// Taken from Computer Graphics: Principle and Practice
	unsigned int rgb;
	float f, p, q, t, r = 0.0, g = 0.0, b = 0.0;
	int i;
	
	h = RAD2DEG(h);
	if (h == 360.0)
		h = 0.0;

	h /= 60.0;
	i = (int)floor(h);
	f = h - i;
	p = v * (1.0 - s);
	q = v * (1.0 - (s * f));
	t = v * (1.0 - (s * (1.0 - f)));

	switch(i)
	{
		case 0:
			r = v;
			g = t;
			b = p;
			break;
		case 1:
			r = q;
			g = v;
			b = p;
			break;
		case 2:
			r = p;
			g = v;
			b = t;
			break;
		case 3:
			r = p;
			g = q;
			b = v;
			break;
		case 4:
			r = t;
			g = p;
			b = v;
			break;
		case 5:
			r = v;
			g = p;
			b = t;
			break;
		default:
			break;
	}

	rgb = (0xff & (uint)(b));
	rgb |= (0xff & (uint)(g)) << 8;
	rgb |= (0xff & (uint)(r)) << 16;
	return rgb << 8;
}

static void
updatecircle(void)
{
	float t, i, l, s;
	Point c, e;

	if (Circle != nil) {
		freeimage(Circle);
	}
	Circle = allocimage(display, RECTANGLE(Dx(screen->r), Dy(screen->r)), RGBA32, 1, BACKGROUNDCOLOR);
	if (Circle == nil)
		sysfatal("initcanvas: %r");
	if (RawCircle != nil) {
		free(RawCircle);
	}
	CircleBPL = bytesperline(Circle->r, Circle->depth);
	RawCircleSize = CircleBPL * Dy(Circle->r);
	RawCircle = malloc(RawCircleSize);
	unloadimage(Circle, Circle->r, (uchar *)RawCircle, RawCircleSize);

	c.x = Dx(Circle->r)/2;
	c.y = Dy(Circle->r)/2;

	l = MIN(Dx(screen->r), Dy(screen->r));
	l *= RADIUS/2.0;
	
	i = 1/(l*2);
	for(t = 0.0; t < (2*PI); t += i) {
		for (s = 0; s < l; s += 0.1) {
			e.x = c.x + s * cos(t);
			e.y = c.y + s * sin(t);
			RawCircle[Dx(Circle->r) * e.y + e.x] = hsv2rgb(t, 1, (s/l)*100.0);
		}
	}

	loadimage(Circle, Circle->r, (uchar *)RawCircle, RawCircleSize);
}

static void
drawcanvas(void)
{
	draw(screen, screen->r, Background, nil, ZP);
	draw(screen, screen->r, Circle, nil, ZP);
}

void
setbackground(ulong col)
{	
	if (Background != nil)
		freeimage(Background);

	Background = allocimage(display, RECTANGLE(1, 1), RGBA32, 1, col);
	if (Background == nil)
		sysfatal("setbackground: %r");
}

static void
initcanvas(void)
{
	updatecircle();
	setbackground(BACKGROUNDCOLOR);
	drawcanvas();
}

void
eresized(int)
{	
	if(getwindow(display, Refnone) < 0)
		sysfatal("getwindow: %r");
	initcanvas();
}

void
main(int argc, char * argv[])
{
	Event e;

	USED(argc);
	USED(argv);
	
	if (initdraw(nil, nil, "pill") < 0)
		sysfatal("initdraw: %r\n");
	einit(Emouse | Ekeyboard);
	initcanvas();
	for (;RunApp;) {
		switch(event(&e)) {
		case Ekeyboard:
			if (e.kbdc == 'q') {
				RunApp = 0;
			}
			break;
		}
	}
}