mischiefadd cf1b376511 years agoHistory
237 lines · 4.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include <geometry.h> typedef struct Vert{	Point3 world;	Point3 screen;	int color;}Vert; int		nocubes;int		ncolor;Quaternion	q = {1.,0.,0.,0.};Image		*image;Image		*bg;Image		*color[256];Rectangle	viewrect;int		prevsel; Point3p3(double x, double y, double z, double w){	Point3 p; 	p.x = x;	p.y = y;	p.z = z;	p.w = w;	return p;} intcmp(Vert *a, Vert *b){	if(a->screen.z>b->screen.z)		return -1;	if(a->screen.z<b->screen.z)		return 1;	return 0;} /* crummy hack */voidreadcolmap(Display *d, RGB *cmap){	int i, rgb, r, g, b; 	for(i=0; i<256; i++){		rgb = cmap2rgb(i);		r = rgb>>16;		g = (rgb>>8)&0xFF;		b = rgb & 0xFF;		cmap[i].red = r|(r<<8)|(r<<16)|(r<<24);		cmap[i].green = g|(g<<8)|(g<<16)|(g<<24);		cmap[i].blue = b|(b<<8)|(b<<16)|(b<<24);	}} voidcolorspace(RGB *cmap, Vert *v){	Space *view;	int i; 	for(i=0;i!=ncolor;i++){		v[i].world.x=(cmap[i].red>>24)/255.-.5;		v[i].world.y=(cmap[i].green>>24)/255.-.5;		v[i].world.z=(cmap[i].blue>>24)/255.-.5;		v[i].world.w=1.;		v[i].color=i;	}	view = pushmat(0);	viewport(view, viewrect, 1.);	persp(view, 30., 3., 7.);	look(view, p3(0., 0., -5., 1.), p3(0., 0., 0., 1.),		p3(0., 1., 0., 1.));	qrot(view, q);	for(i=0;i!=ncolor;i++)		v[i].screen = xformpointd(v[i].world, 0, view);	popmat(view);} voidline3(Vert a, Vert b){	line(image, Pt(a.screen.x, a.screen.y), Pt(b.screen.x, b.screen.y), 0, 0, 0, display->white, ZP);}  voidredraw(void){	int i, m;	RGB cmap[256];	Vert v[256]; 	readcolmap(display, cmap);	colorspace(cmap, v);	draw(image, image->r, bg, nil, Pt(0, 0));	m = Dx(viewrect)/2;	if(m > Dy(viewrect)/2)		m = Dy(viewrect)/2;	ellipse(image, addpt(viewrect.min, divpt(Pt(Dx(viewrect), Dy(viewrect)), 2)),		m, m, 1, display->white, ZP); 	line3(v[0], v[0x36]);	line3(v[0x36], v[0x32]);	line3(v[0x32], v[0x3F]);	line3(v[0x3F], v[0]);		line3(v[0xF0], v[0xF3]);	line3(v[0xF3], v[0xFF]);	line3(v[0xFF], v[0xFC]);	line3(v[0xFC], v[0xF0]); 	line3(v[0], v[0xF0]);	line3(v[0x36], v[0xF3]);	line3(v[0x32], v[0xFF]);	line3(v[0x3F], v[0xFC]); 	qsort(v, ncolor, sizeof(Vert), (int(*)(const void*, const void*))cmp);	if(!nocubes)		for(i=0; i!=ncolor; i++)			draw(image, rectaddpt(Rect(-3, -3, 4, 4), Pt(v[i].screen.x, v[i].screen.y)),				color[v[i].color], nil, Pt(0, 0));	draw(screen, image->r, image, nil, image->r.min);	flushimage(display, 1);} voideresized(int new){	int dx, dy; 	if(new && getwindow(display, Refnone) < 0){		fprint(2, "colors: can't reattach to window: %r\n");		exits("reshaped");	}	draw(screen, screen->r, display->black, nil, ZP);	replclipr(screen, 0, insetrect(screen->r, 3));	viewrect = screen->clipr;	viewrect.min.y += stringsize(font, "0i").y + 5;	if(image)		freeimage(image);	image = allocimage(display, viewrect, screen->chan, 0, DNofill);	dx = viewrect.max.x-viewrect.min.x;	dy = viewrect.max.y-viewrect.min.y;	if(dx>dy){		viewrect.min.x=(viewrect.min.x+viewrect.max.x-dy)/2;		viewrect.max.x=viewrect.min.x+dy;	}	else{		viewrect.min.y=(viewrect.min.y+viewrect.max.y-dx)/2;		viewrect.max.y=viewrect.min.y+dx;	}	if(image==nil){		fprint(2, "can't allocate image\n");		exits("bad allocimage");	}	prevsel = -1;	redraw();} void main(int argc, char **argv){	Vert v[256];	RGB cmap[256];	char buf[100];	Point p;	Mouse m;	int i;	ulong bgcol; 	bgcol = DNofill;	ARGBEGIN{	case 'n':		nocubes = 1;		break;	case 'b':		bgcol = DBlack;		break;	case 'w':		bgcol = DWhite;		break;	}ARGEND 	initdraw(0,0,0);	ncolor=256;	for(i=0;i!=ncolor;i++)		color[i] = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, cmap2rgba(i));	if(bgcol==DNofill){		bg = allocimage(display, Rect(0, 0, 2, 2), screen->chan, 1, DWhite);		draw(bg, Rect(0, 0, 1, 1), color[0], nil, Pt(0, 0));		draw(bg, Rect(1, 1, 2, 2), color[0], nil, Pt(0, 0));	}else		bg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, bgcol); 	einit(Emouse);	eresized(0); 	for(;;){		m = emouse();		if(m.buttons&1)			qball(viewrect, &m, &q, redraw, 0);		else if(m.buttons & 2){			readcolmap(display, cmap);			colorspace(cmap, v);			qsort(v, ncolor, sizeof(Vert), (int(*)(const void*, const void*))cmp);			while(m.buttons){				for(i=ncolor-1; i!=0; i--){					if(ptinrect(m.xy, rectaddpt(Rect(-3, -3, 4, 4), Pt(v[i].screen.x, v[i].screen.y)))){						i = v[i].color;						if(i == prevsel)							break;						sprint(buf, "index %3d r %3ld g %3ld b %3ld",							i,							cmap[i].red>>24,							cmap[i].green>>24,							cmap[i].blue>>24);						p = addpt(screen->r.min, Pt(2,2));						draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->black, nil, p);						string(screen, p, display->white, ZP, font, buf);						prevsel = i;						break;					}				}				m = emouse();			}		}else if(m.buttons&4){			do				m = emouse();			while(m.buttons);			exits(0);		}	}}