forsyth20100801b696ef316 years agoHistory
251 lines · 4.1 KB · C
RawDownload
#include "lib9.h"#include "draw.h"#include "tk.h"#include "canvs.h" #define	O(t, e)		((long)(&((t*)0)->e))typedef void	(*Drawfn)(Image*, Point, int, int, Image*, int); /* Oval Options (+ means implemented)	+fill	+outline	+stipple	+tags	+width*/ typedef struct TkCoval TkCoval;struct TkCoval{	int	width;	Image*	stipple;	Image*	pen;	TkCanvas*	canv;}; staticTkOption ovalopts[] ={	"width",	OPTnnfrac,	O(TkCoval, width),	nil,			/* XXX should be nnfrac */	"stipple",	OPTbmap,	O(TkCoval, stipple),	nil,	nil}; staticTkOption itemopts[] ={	"tags",		OPTctag,	O(TkCitem, tags),	nil,	"fill",		OPTcolr,	O(TkCitem, env),	IAUX(TkCfill),	"outline",	OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),	nil}; voidtkcvsovalsize(TkCitem *i){	int w;	TkCoval *o; 	o = TKobj(TkCoval, i);	w = TKF2I(o->width)*2; 	i->p.bb = bbnil;	tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);	i->p.bb = insetrect(i->p.bb, -w);} char*tkcvsovalcreat(Tk* tk, char *arg, char **val){	char *e;	TkCoval *o;	TkCitem *i;	TkCanvas *c;	TkOptab tko[3]; 	c = TKobj(TkCanvas, tk); 	i = tkcnewitem(tk, TkCVoval, sizeof(TkCitem)+sizeof(TkCoval));	if(i == nil)		return TkNomem; 	o = TKobj(TkCoval, i);	o->width = TKI2F(1);	o->canv = c;	e = tkparsepts(tk->env->top, &i->p, &arg, 0);	if(e != nil) {		tkcvsfreeitem(i);		return e;	}	if(i->p.npoint != 2) {		tkcvsfreeitem(i);		return TkFewpt;	} 	tko[0].ptr = o;	tko[0].optab = ovalopts;	tko[1].ptr = i;	tko[1].optab = itemopts;	tko[2].ptr = nil;	e = tkparse(tk->env->top, arg, tko, nil);	if(e != nil) {		tkcvsfreeitem(i);		return e;	}	e = tkcaddtag(tk, i, 1);	if(e != nil) {		tkcvsfreeitem(i);		return e;	} 	tkcvsovalsize(i); 	e = tkvalue(val, "%d", i->id);	if(e != nil) {		tkcvsfreeitem(i);		return e;	} 	tkcvsappend(c, i);	tkbbmax(&c->update, &i->p.bb);	tkmkpen(&o->pen, i->env, o->stipple);	tkcvssetdirty(tk);	return nil;} char*tkcvsovalcget(TkCitem *i, char *arg, char **val){	TkOptab tko[3];	TkCoval *o = TKobj(TkCoval, i); 	tko[0].ptr = o;	tko[0].optab = ovalopts;	tko[1].ptr = i;	tko[1].optab = itemopts;	tko[2].ptr = nil; 	return tkgencget(tko, arg, val, i->env->top);} char*tkcvsovalconf(Tk *tk, TkCitem *i, char *arg){	char *e;	TkOptab tko[3];	TkCoval *o = TKobj(TkCoval, i); 	tko[0].ptr = o;	tko[0].optab = ovalopts;	tko[1].ptr = i;	tko[1].optab = itemopts;	tko[2].ptr = nil; 	e = tkparse(tk->env->top, arg, tko, nil);	tkcvsovalsize(i);	tkmkpen(&o->pen, i->env, o->stipple); 	return e;} voidtkcvsovalfree(TkCitem *i){	TkCoval *o; 	o = TKobj(TkCoval, i);	if(o->stipple)		freeimage(o->stipple);	if(o->pen)		freeimage(o->pen);} voidtkcvsovaldraw(Image *img, TkCitem *i, TkEnv *pe){	Point c;	TkEnv *e;	Image *pen;	TkCoval *o;	Rectangle d;	int w, dx, dy; 	USED(pe); 	d.min = i->p.drawpt[0];	d.max = i->p.drawpt[1]; 	e = i->env;	o = TKobj(TkCoval, i); 	pen = o->pen;	if(pen == nil && (e->set & (1<<TkCfill)))		pen = tkgc(e, TkCfill); 	w = TKF2I(o->width)/2;	if(w < 0)		return; 	d = canonrect(d);	dx = Dx(d)/2;	dy = Dy(d)/2;	c.x = d.min.x + dx;	c.y = d.min.y + dy;	if(pen != nil)		fillellipse(img, c, dx, dy, pen, c);	ellipse(img, c, dx, dy, w, tkgc(e, TkCforegnd), c);} char*tkcvsovalcoord(TkCitem *i, char *arg, int x, int y){	char *e;	TkCpoints p; 	if(arg == nil) {		tkxlatepts(i->p.parampt, i->p.npoint, x, y);		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));	}	else {		e = tkparsepts(i->env->top, &p, &arg, 0);		if(e != nil)			return e;		if(p.npoint != 2) {			tkfreepoint(&p);			return TkFewpt;		}		tkfreepoint(&i->p);		i->p = p;		tkcvsovalsize(i);	}	return nil;} inttkcvsovalhit(TkCitem *i, Point p){	TkCoval *o;	int w, dx, dy;	Rectangle d;	vlong v;		o = TKobj(TkCoval, i);	w = TKF2I(o->width)/2;	d = canonrect(Rpt(i->p.drawpt[0], i->p.drawpt[1]));	d = insetrect(d, -(w/2 + 1)); 	dx = Dx(d)/2;	dy = Dy(d)/2; 	p.x -= d.min.x + dx;	p.y -= d.min.y + dy; 	dx *= dx;	dy *= dy; 	/* XXX can we do this nicely without overflow and without vlongs? */	v = (vlong)(p.x*p.x)*dy;	v += (vlong)(p.y*p.y)*dx;	return v < (vlong)dx*dy;}