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