xref: /inferno-os/libtk/coval.c (revision 7781741266783e4df3b35d42a55e8e504838898b)
137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "draw.h"
337da2899SCharles.Forsyth #include "tk.h"
437da2899SCharles.Forsyth #include "canvs.h"
537da2899SCharles.Forsyth 
637da2899SCharles.Forsyth #define	O(t, e)		((long)(&((t*)0)->e))
737da2899SCharles.Forsyth typedef void	(*Drawfn)(Image*, Point, int, int, Image*, int);
837da2899SCharles.Forsyth 
937da2899SCharles.Forsyth /* Oval Options (+ means implemented)
1037da2899SCharles.Forsyth 	+fill
1137da2899SCharles.Forsyth 	+outline
1237da2899SCharles.Forsyth 	+stipple
1337da2899SCharles.Forsyth 	+tags
1437da2899SCharles.Forsyth 	+width
1537da2899SCharles.Forsyth */
1637da2899SCharles.Forsyth 
1737da2899SCharles.Forsyth typedef struct TkCoval TkCoval;
1837da2899SCharles.Forsyth struct TkCoval
1937da2899SCharles.Forsyth {
2037da2899SCharles.Forsyth 	int	width;
2137da2899SCharles.Forsyth 	Image*	stipple;
2237da2899SCharles.Forsyth 	Image*	pen;
2337da2899SCharles.Forsyth 	TkCanvas*	canv;
2437da2899SCharles.Forsyth };
2537da2899SCharles.Forsyth 
2637da2899SCharles.Forsyth static
2737da2899SCharles.Forsyth TkOption ovalopts[] =
2837da2899SCharles.Forsyth {
2937da2899SCharles.Forsyth 	"width",	OPTnnfrac,	O(TkCoval, width),	nil,			/* XXX should be nnfrac */
3037da2899SCharles.Forsyth 	"stipple",	OPTbmap,	O(TkCoval, stipple),	nil,
3137da2899SCharles.Forsyth 	nil
3237da2899SCharles.Forsyth };
3337da2899SCharles.Forsyth 
3437da2899SCharles.Forsyth static
3537da2899SCharles.Forsyth TkOption itemopts[] =
3637da2899SCharles.Forsyth {
3737da2899SCharles.Forsyth 	"tags",		OPTctag,	O(TkCitem, tags),	nil,
3837da2899SCharles.Forsyth 	"fill",		OPTcolr,	O(TkCitem, env),	IAUX(TkCfill),
3937da2899SCharles.Forsyth 	"outline",	OPTcolr,	O(TkCitem, env),	IAUX(TkCforegnd),
4037da2899SCharles.Forsyth 	nil
4137da2899SCharles.Forsyth };
4237da2899SCharles.Forsyth 
4337da2899SCharles.Forsyth void
tkcvsovalsize(TkCitem * i)4437da2899SCharles.Forsyth tkcvsovalsize(TkCitem *i)
4537da2899SCharles.Forsyth {
4637da2899SCharles.Forsyth 	int w;
4737da2899SCharles.Forsyth 	TkCoval *o;
4837da2899SCharles.Forsyth 
4937da2899SCharles.Forsyth 	o = TKobj(TkCoval, i);
5037da2899SCharles.Forsyth 	w = TKF2I(o->width)*2;
5137da2899SCharles.Forsyth 
5237da2899SCharles.Forsyth 	i->p.bb = bbnil;
5337da2899SCharles.Forsyth 	tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
5437da2899SCharles.Forsyth 	i->p.bb = insetrect(i->p.bb, -w);
5537da2899SCharles.Forsyth }
5637da2899SCharles.Forsyth 
5737da2899SCharles.Forsyth char*
tkcvsovalcreat(Tk * tk,char * arg,char ** val)5837da2899SCharles.Forsyth tkcvsovalcreat(Tk* tk, char *arg, char **val)
5937da2899SCharles.Forsyth {
6037da2899SCharles.Forsyth 	char *e;
6137da2899SCharles.Forsyth 	TkCoval *o;
6237da2899SCharles.Forsyth 	TkCitem *i;
6337da2899SCharles.Forsyth 	TkCanvas *c;
6437da2899SCharles.Forsyth 	TkOptab tko[3];
6537da2899SCharles.Forsyth 
6637da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
6737da2899SCharles.Forsyth 
6837da2899SCharles.Forsyth 	i = tkcnewitem(tk, TkCVoval, sizeof(TkCitem)+sizeof(TkCoval));
6937da2899SCharles.Forsyth 	if(i == nil)
7037da2899SCharles.Forsyth 		return TkNomem;
7137da2899SCharles.Forsyth 
7237da2899SCharles.Forsyth 	o = TKobj(TkCoval, i);
7337da2899SCharles.Forsyth 	o->width = TKI2F(1);
7437da2899SCharles.Forsyth 	o->canv = c;
7537da2899SCharles.Forsyth 	e = tkparsepts(tk->env->top, &i->p, &arg, 0);
7637da2899SCharles.Forsyth 	if(e != nil) {
7737da2899SCharles.Forsyth 		tkcvsfreeitem(i);
7837da2899SCharles.Forsyth 		return e;
7937da2899SCharles.Forsyth 	}
8037da2899SCharles.Forsyth 	if(i->p.npoint != 2) {
8137da2899SCharles.Forsyth 		tkcvsfreeitem(i);
8237da2899SCharles.Forsyth 		return TkFewpt;
8337da2899SCharles.Forsyth 	}
8437da2899SCharles.Forsyth 
8537da2899SCharles.Forsyth 	tko[0].ptr = o;
8637da2899SCharles.Forsyth 	tko[0].optab = ovalopts;
8737da2899SCharles.Forsyth 	tko[1].ptr = i;
8837da2899SCharles.Forsyth 	tko[1].optab = itemopts;
8937da2899SCharles.Forsyth 	tko[2].ptr = nil;
9037da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
9137da2899SCharles.Forsyth 	if(e != nil) {
9237da2899SCharles.Forsyth 		tkcvsfreeitem(i);
9337da2899SCharles.Forsyth 		return e;
9437da2899SCharles.Forsyth 	}
9537da2899SCharles.Forsyth 	e = tkcaddtag(tk, i, 1);
9637da2899SCharles.Forsyth 	if(e != nil) {
9737da2899SCharles.Forsyth 		tkcvsfreeitem(i);
9837da2899SCharles.Forsyth 		return e;
9937da2899SCharles.Forsyth 	}
10037da2899SCharles.Forsyth 
10137da2899SCharles.Forsyth 	tkcvsovalsize(i);
10237da2899SCharles.Forsyth 
10337da2899SCharles.Forsyth 	e = tkvalue(val, "%d", i->id);
10437da2899SCharles.Forsyth 	if(e != nil) {
10537da2899SCharles.Forsyth 		tkcvsfreeitem(i);
10637da2899SCharles.Forsyth 		return e;
10737da2899SCharles.Forsyth 	}
10837da2899SCharles.Forsyth 
10937da2899SCharles.Forsyth 	tkcvsappend(c, i);
11037da2899SCharles.Forsyth 	tkbbmax(&c->update, &i->p.bb);
11137da2899SCharles.Forsyth 	tkmkpen(&o->pen, i->env, o->stipple);
11237da2899SCharles.Forsyth 	tkcvssetdirty(tk);
11337da2899SCharles.Forsyth 	return nil;
11437da2899SCharles.Forsyth }
11537da2899SCharles.Forsyth 
11637da2899SCharles.Forsyth char*
tkcvsovalcget(TkCitem * i,char * arg,char ** val)11737da2899SCharles.Forsyth tkcvsovalcget(TkCitem *i, char *arg, char **val)
11837da2899SCharles.Forsyth {
11937da2899SCharles.Forsyth 	TkOptab tko[3];
12037da2899SCharles.Forsyth 	TkCoval *o = TKobj(TkCoval, i);
12137da2899SCharles.Forsyth 
12237da2899SCharles.Forsyth 	tko[0].ptr = o;
12337da2899SCharles.Forsyth 	tko[0].optab = ovalopts;
12437da2899SCharles.Forsyth 	tko[1].ptr = i;
12537da2899SCharles.Forsyth 	tko[1].optab = itemopts;
12637da2899SCharles.Forsyth 	tko[2].ptr = nil;
12737da2899SCharles.Forsyth 
12837da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, i->env->top);
12937da2899SCharles.Forsyth }
13037da2899SCharles.Forsyth 
13137da2899SCharles.Forsyth char*
tkcvsovalconf(Tk * tk,TkCitem * i,char * arg)13237da2899SCharles.Forsyth tkcvsovalconf(Tk *tk, TkCitem *i, char *arg)
13337da2899SCharles.Forsyth {
13437da2899SCharles.Forsyth 	char *e;
13537da2899SCharles.Forsyth 	TkOptab tko[3];
13637da2899SCharles.Forsyth 	TkCoval *o = TKobj(TkCoval, i);
13737da2899SCharles.Forsyth 
13837da2899SCharles.Forsyth 	tko[0].ptr = o;
13937da2899SCharles.Forsyth 	tko[0].optab = ovalopts;
14037da2899SCharles.Forsyth 	tko[1].ptr = i;
14137da2899SCharles.Forsyth 	tko[1].optab = itemopts;
14237da2899SCharles.Forsyth 	tko[2].ptr = nil;
14337da2899SCharles.Forsyth 
14437da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
14537da2899SCharles.Forsyth 	tkcvsovalsize(i);
14637da2899SCharles.Forsyth 	tkmkpen(&o->pen, i->env, o->stipple);
14737da2899SCharles.Forsyth 
14837da2899SCharles.Forsyth 	return e;
14937da2899SCharles.Forsyth }
15037da2899SCharles.Forsyth 
15137da2899SCharles.Forsyth void
tkcvsovalfree(TkCitem * i)15237da2899SCharles.Forsyth tkcvsovalfree(TkCitem *i)
15337da2899SCharles.Forsyth {
15437da2899SCharles.Forsyth 	TkCoval *o;
15537da2899SCharles.Forsyth 
15637da2899SCharles.Forsyth 	o = TKobj(TkCoval, i);
15737da2899SCharles.Forsyth 	if(o->stipple)
15837da2899SCharles.Forsyth 		freeimage(o->stipple);
15937da2899SCharles.Forsyth 	if(o->pen)
16037da2899SCharles.Forsyth 		freeimage(o->pen);
16137da2899SCharles.Forsyth }
16237da2899SCharles.Forsyth 
16337da2899SCharles.Forsyth void
tkcvsovaldraw(Image * img,TkCitem * i,TkEnv * pe)16437da2899SCharles.Forsyth tkcvsovaldraw(Image *img, TkCitem *i, TkEnv *pe)
16537da2899SCharles.Forsyth {
16637da2899SCharles.Forsyth 	Point c;
16737da2899SCharles.Forsyth 	TkEnv *e;
16837da2899SCharles.Forsyth 	Image *pen;
16937da2899SCharles.Forsyth 	TkCoval *o;
17037da2899SCharles.Forsyth 	Rectangle d;
17137da2899SCharles.Forsyth 	int w, dx, dy;
17237da2899SCharles.Forsyth 
17337da2899SCharles.Forsyth 	USED(pe);
17437da2899SCharles.Forsyth 
17537da2899SCharles.Forsyth 	d.min = i->p.drawpt[0];
17637da2899SCharles.Forsyth 	d.max = i->p.drawpt[1];
17737da2899SCharles.Forsyth 
17837da2899SCharles.Forsyth 	e = i->env;
17937da2899SCharles.Forsyth 	o = TKobj(TkCoval, i);
18037da2899SCharles.Forsyth 
18137da2899SCharles.Forsyth 	pen = o->pen;
18237da2899SCharles.Forsyth 	if(pen == nil && (e->set & (1<<TkCfill)))
18337da2899SCharles.Forsyth 		pen = tkgc(e, TkCfill);
18437da2899SCharles.Forsyth 
18537da2899SCharles.Forsyth 	w = TKF2I(o->width)/2;
18637da2899SCharles.Forsyth 	if(w < 0)
18737da2899SCharles.Forsyth 		return;
18837da2899SCharles.Forsyth 
18937da2899SCharles.Forsyth 	d = canonrect(d);
19037da2899SCharles.Forsyth 	dx = Dx(d)/2;
19137da2899SCharles.Forsyth 	dy = Dy(d)/2;
19237da2899SCharles.Forsyth 	c.x = d.min.x + dx;
19337da2899SCharles.Forsyth 	c.y = d.min.y + dy;
19437da2899SCharles.Forsyth 	if(pen != nil)
19537da2899SCharles.Forsyth 		fillellipse(img, c, dx, dy, pen, c);
19637da2899SCharles.Forsyth 	ellipse(img, c, dx, dy, w, tkgc(e, TkCforegnd), c);
19737da2899SCharles.Forsyth }
19837da2899SCharles.Forsyth 
19937da2899SCharles.Forsyth char*
tkcvsovalcoord(TkCitem * i,char * arg,int x,int y)20037da2899SCharles.Forsyth tkcvsovalcoord(TkCitem *i, char *arg, int x, int y)
20137da2899SCharles.Forsyth {
20237da2899SCharles.Forsyth 	char *e;
20337da2899SCharles.Forsyth 	TkCpoints p;
20437da2899SCharles.Forsyth 
20537da2899SCharles.Forsyth 	if(arg == nil) {
20637da2899SCharles.Forsyth 		tkxlatepts(i->p.parampt, i->p.npoint, x, y);
20737da2899SCharles.Forsyth 		tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
20837da2899SCharles.Forsyth 		i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
20937da2899SCharles.Forsyth 	}
21037da2899SCharles.Forsyth 	else {
21137da2899SCharles.Forsyth 		e = tkparsepts(i->env->top, &p, &arg, 0);
21237da2899SCharles.Forsyth 		if(e != nil)
21337da2899SCharles.Forsyth 			return e;
21437da2899SCharles.Forsyth 		if(p.npoint != 2) {
21537da2899SCharles.Forsyth 			tkfreepoint(&p);
21637da2899SCharles.Forsyth 			return TkFewpt;
21737da2899SCharles.Forsyth 		}
21837da2899SCharles.Forsyth 		tkfreepoint(&i->p);
21937da2899SCharles.Forsyth 		i->p = p;
22037da2899SCharles.Forsyth 		tkcvsovalsize(i);
22137da2899SCharles.Forsyth 	}
22237da2899SCharles.Forsyth 	return nil;
22337da2899SCharles.Forsyth }
22437da2899SCharles.Forsyth 
22537da2899SCharles.Forsyth int
tkcvsovalhit(TkCitem * i,Point p)22637da2899SCharles.Forsyth tkcvsovalhit(TkCitem *i, Point p)
22737da2899SCharles.Forsyth {
22837da2899SCharles.Forsyth 	TkCoval *o;
22937da2899SCharles.Forsyth 	int w, dx, dy;
23037da2899SCharles.Forsyth 	Rectangle d;
231*77817412Sforsyth 	vlong v;
23237da2899SCharles.Forsyth 
23337da2899SCharles.Forsyth 	o = TKobj(TkCoval, i);
23437da2899SCharles.Forsyth 	w = TKF2I(o->width)/2;
23537da2899SCharles.Forsyth 	d = canonrect(Rpt(i->p.drawpt[0], i->p.drawpt[1]));
23637da2899SCharles.Forsyth 	d = insetrect(d, -(w/2 + 1));
23737da2899SCharles.Forsyth 
23837da2899SCharles.Forsyth 	dx = Dx(d)/2;
23937da2899SCharles.Forsyth 	dy = Dy(d)/2;
24037da2899SCharles.Forsyth 
24137da2899SCharles.Forsyth 	p.x -= d.min.x + dx;
24237da2899SCharles.Forsyth 	p.y -= d.min.y + dy;
24337da2899SCharles.Forsyth 
24437da2899SCharles.Forsyth 	dx *= dx;
24537da2899SCharles.Forsyth 	dy *= dy;
24637da2899SCharles.Forsyth 
24737da2899SCharles.Forsyth 	/* XXX can we do this nicely without overflow and without vlongs? */
248*77817412Sforsyth 	v = (vlong)(p.x*p.x)*dy;
249*77817412Sforsyth 	v += (vlong)(p.y*p.y)*dx;
250*77817412Sforsyth 	return v < (vlong)dx*dy;
25137da2899SCharles.Forsyth }
252