ref: ee5d653d61460a31666dc0bf8c9b011832a0e431
dir: /pill/pill.c/
#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;
}
}
}