From 37da2899f40661e3e9631e497da8dc59b971cbd0 Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Fri, 22 Dec 2006 17:07:39 +0000 Subject: 20060303a --- libtk/cpoly.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 libtk/cpoly.c (limited to 'libtk/cpoly.c') diff --git a/libtk/cpoly.c b/libtk/cpoly.c new file mode 100644 index 00000000..4033da3c --- /dev/null +++ b/libtk/cpoly.c @@ -0,0 +1,270 @@ +#include "lib9.h" +#include "draw.h" +#include "tk.h" +#include "canvs.h" + +#define O(t, e) ((long)(&((t*)0)->e)) + +typedef struct TkCpoly TkCpoly; +struct TkCpoly +{ + int width; + Image* stipple; + Image* pen; + TkCanvas* canv; + int smooth; + int steps; + int winding; +}; + +static +TkStab tkwinding[] = +{ + "nonzero", ~0, + "odd", 1, + nil +}; + +/* Polygon Options (+ means implemented) + +fill + +smooth + +splinesteps + +stipple + +tags + +width + +outline +*/ +static +TkOption polyopts[] = +{ + "width", OPTnnfrac, O(TkCpoly, width), nil, + "stipple", OPTbmap, O(TkCpoly, stipple), nil, + "smooth", OPTstab, O(TkCpoly, smooth), tkbool, + "splinesteps", OPTdist, O(TkCpoly, steps), nil, + "winding", OPTstab, O(TkCpoly, winding), tkwinding, + nil +}; + +static +TkOption itemopts[] = +{ + "tags", OPTctag, O(TkCitem, tags), nil, + "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill), + "outline", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd), + nil +}; + +void +tkcvspolysize(TkCitem *i) +{ + int w; + TkCpoly *p; + + p = TKobj(TkCpoly, i); + w = TKF2I(p->width); + + i->p.bb = bbnil; + tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb); + i->p.bb = insetrect(i->p.bb, -w); +} + +char* +tkcvspolycreat(Tk* tk, char *arg, char **val) +{ + char *e; + TkCpoly *p; + TkCitem *i; + TkCanvas *c; + TkOptab tko[3]; + + c = TKobj(TkCanvas, tk); + + i = tkcnewitem(tk, TkCVpoly, sizeof(TkCitem)+sizeof(TkCpoly)); + if(i == nil) + return TkNomem; + + p = TKobj(TkCpoly, i); + p->width = TKI2F(1); + p->winding = ~0; + + e = tkparsepts(tk->env->top, &i->p, &arg, 1); + if(e == nil && i->p.npoint < 3) + e = TkBadvl; + if(e != nil) { + tkcvsfreeitem(i); + return e; + } + + tko[0].ptr = p; + tko[0].optab = polyopts; + 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; + } + p->canv = c; + + e = tkcaddtag(tk, i, 1); + if(e != nil) { + tkcvsfreeitem(i); + return e; + } + + tkcvspolysize(i); + tkmkpen(&p->pen, i->env, p->stipple); + + e = tkvalue(val, "%d", i->id); + if(e != nil) { + tkcvsfreeitem(i); + return e; + } + + tkcvsappend(c, i); + tkbbmax(&c->update, &i->p.bb); + tkcvssetdirty(tk); + return nil; +} + +char* +tkcvspolycget(TkCitem *i, char *arg, char **val) +{ + TkOptab tko[3]; + TkCpoly *p = TKobj(TkCpoly, i); + + tko[0].ptr = p; + tko[0].optab = polyopts; + tko[1].ptr = i; + tko[1].optab = itemopts; + tko[2].ptr = nil; + + return tkgencget(tko, arg, val, i->env->top); +} + +char* +tkcvspolyconf(Tk *tk, TkCitem *i, char *arg) +{ + char *e; + TkOptab tko[3]; + TkCpoly *p = TKobj(TkCpoly, i); + + tko[0].ptr = p; + tko[0].optab = polyopts; + tko[1].ptr = i; + tko[1].optab = itemopts; + tko[2].ptr = nil; + + e = tkparse(tk->env->top, arg, tko, nil); + + tkcvspolysize(i); + tkmkpen(&p->pen, i->env, p->stipple); + + return e; +} + +void +tkcvspolyfree(TkCitem *i) +{ + TkCpoly *p; + + p = TKobj(TkCpoly, i); + if(p->stipple) + freeimage(p->stipple); + if(p->pen) + freeimage(p->pen); +} + +void +tkcvspolydraw(Image *img, TkCitem *i, TkEnv *pe) +{ + int w; + TkEnv *e; + TkCpoly *p; + Image *pen; + Point *pts; + + USED(pe); + + p = TKobj(TkCpoly, i); + + e = i->env; + + pen = p->pen; + if(pen == nil && (e->set & (1<p.drawpt; + if(i->p.npoint > 0 && pen != nil) { + if (p->smooth == BoolT) + fillbezspline(img, pts, i->p.npoint+1, p->winding, pen, pts[0]); + else + fillpoly(img, pts, i->p.npoint+1, p->winding, pen, pts[0]); + } + + w = TKF2I(p->width) - 1; + if(w >= 0 && (e->set & (1<env, TkCforegnd); + if (p->smooth == BoolT) + bezspline(img, pts, i->p.npoint+1, Enddisc, Enddisc, w, pen, pts[0]); + else + poly(img, pts, i->p.npoint+1, Enddisc, Enddisc, w, pen, pts[0]); + } +} + +char* +tkcvspolycoord(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.drawpt[i->p.npoint] = i->p.drawpt[0]; + i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y))); + } + else { + e = tkparsepts(i->env->top, &p, &arg, 1); + if(e != nil) + return e; + if(p.npoint < 2) { + tkfreepoint(&p); + return TkFewpt; + } + tkfreepoint(&i->p); + i->p = p; + tkcvspolysize(i); + } + return nil; +} + +int +tkcvspolyhit(TkCitem *item, Point p) +{ + Point *poly; + int r, np, fill, w; + TkCpoly *l; + TkEnv *e; + + l = TKobj(TkCpoly, item); + w = TKF2I(l->width) + 2; /* include some slop */ + e = item->env; + fill = e->set & (1<smooth == BoolT) { + /* this works but it's slow if used intensively... */ + np = getbezsplinepts(item->p.drawpt, item->p.npoint + 1, &poly); + if (fill) + r = tkinsidepoly(poly, np, l->winding, p); + else + r = tklinehit(poly, np, w, p); + free(poly); + } else { + if (fill) + r = tkinsidepoly(item->p.drawpt, item->p.npoint, l->winding, p); + else + r = tklinehit(item->p.drawpt, item->p.npoint + 1, w, p); + } + return r; +} -- cgit v1.2.3